Created
October 15, 2016 18:03
-
-
Save Ahmed-Hady/f3e0963fa8afce52b0c2ec46be9f7257 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 4738492dda369dcd10034b5b0242819aaaa9d5d8 Mon Sep 17 00:00:00 2001 | |
From: Ahmed Hady <ahmedhady6@gmail.com> | |
Date: Sat, 15 Oct 2016 20:01:36 +0200 | |
Subject: [PATCH] CAF Patch | |
--- | |
arch/arm/kernel/vmlinux.lds.S | 1 + | |
arch/arm/mach-msm/Kconfig | 13 +- | |
arch/arm/mach-msm/audio-7627a-devices.c | 2 +- | |
arch/arm/mach-msm/board-msm7627a-camera.c | 15 + | |
arch/arm/mach-msm/board-msm7x27.c | 2 +- | |
arch/arm/mach-msm/board-msm7x27a.c | 168 +-- | |
arch/arm/mach-msm/board-qrd7627a.c | 160 +-- | |
arch/arm/mach-msm/cpufreq_limit.c | 128 ++ | |
arch/arm/mach-msm/devices-msm7x27a.c | 16 +- | |
arch/arm/mach-msm/include/mach/iommu.h | 10 +- | |
arch/arm/mach-msm/include/mach/memory.h | 2 +- | |
arch/arm/mach-msm/include/mach/msm_adsp.h | 2 +- | |
arch/arm/mach-msm/include/mach/msm_audio_aac.h | 2 +- | |
arch/arm/mach-msm/include/mach/msm_bus.h | 4 +- | |
arch/arm/mach-msm/include/mach/msm_bus_board.h | 2 +- | |
arch/arm/mach-msm/include/mach/msm_dcvs.h | 92 +- | |
arch/arm/mach-msm/include/mach/msm_dcvs_scm.h | 100 +- | |
arch/arm/mach-msm/include/mach/msm_memtypes.h | 4 +- | |
.../mach-msm/include/mach/qdsp5/acdb_commands.h | 2 +- | |
arch/arm/mach-msm/include/mach/qdsp5/audio_acdbi.h | 2 +- | |
.../mach-msm/include/mach/qdsp5/qdsp5audplaycmdi.h | 2 +- | |
.../mach-msm/include/mach/qdsp5/qdsp5audplaymsg.h | 2 +- | |
.../mach-msm/include/mach/qdsp5/qdsp5audpreproc.h | 2 +- | |
.../include/mach/qdsp5/qdsp5audpreproccmdi.h | 2 +- | |
.../include/mach/qdsp5/qdsp5audpreprocmsg.h | 2 +- | |
.../mach-msm/include/mach/qdsp5/qdsp5audreccmdi.h | 2 +- | |
.../mach-msm/include/mach/qdsp5/qdsp5audrecmsg.h | 2 +- | |
.../mach-msm/include/mach/qdsp5/qdsp5jpegcmdi.h | 2 +- | |
.../arm/mach-msm/include/mach/qdsp5/qdsp5jpegmsg.h | 2 +- | |
.../arm/mach-msm/include/mach/qdsp5/qdsp5lpmcmdi.h | 2 +- | |
arch/arm/mach-msm/include/mach/qdsp5/qdsp5lpmmsg.h | 2 +- | |
.../arm/mach-msm/include/mach/qdsp5/qdsp5rmtcmdi.h | 2 +- | |
arch/arm/mach-msm/include/mach/qdsp5/qdsp5rmtmsg.h | 2 +- | |
.../mach-msm/include/mach/qdsp5/qdsp5vdeccmdi.h | 2 +- | |
.../arm/mach-msm/include/mach/qdsp5/qdsp5vdecmsg.h | 2 +- | |
.../mach-msm/include/mach/qdsp5/qdsp5venccmdi.h | 2 +- | |
.../arm/mach-msm/include/mach/qdsp5/qdsp5vfecmdi.h | 2 +- | |
arch/arm/mach-msm/include/mach/qdsp5/qdsp5vfemsg.h | 2 +- | |
arch/arm/mach-msm/include/mach/qdsp5/snd_adie.h | 2 +- | |
arch/arm/mach-msm/memory.c | 15 +- | |
arch/arm/mach-msm/msm_dcvs.c | 1204 +++++++++++------ | |
arch/arm/mach-msm/msm_dcvs_scm.c | 133 +- | |
arch/arm/mach-msm/msm_turbo.c | 51 + | |
arch/arm/mach-msm/qdsp5/audio_ac3.c | 2 +- | |
arch/arm/mach-msm/qdsp5/audio_amrnb.c | 2 +- | |
arch/arm/mach-msm/qdsp5/audio_amrnb_in.c | 1 + | |
arch/arm/mach-msm/qdsp5/audio_voicememo.c | 2 +- | |
drivers/base/genlock.c | 36 +- | |
drivers/char/random.c | 4 +- | |
drivers/cpufreq/cpufreq_smartass2.c | 8 +- | |
drivers/crypto/msm/qce.c | 153 +-- | |
drivers/crypto/msm/qcedev.c | 252 +--- | |
drivers/gpu/ion/ion_carveout_heap.c | 94 +- | |
drivers/gpu/ion/ion_cma_heap.c | 46 +- | |
drivers/gpu/ion/ion_cp_heap.c | 293 ++--- | |
drivers/gpu/ion/ion_heap.c | 1 + | |
drivers/gpu/ion/ion_iommu_heap.c | 269 +++- | |
drivers/gpu/ion/msm/msm_ion.c | 40 +- | |
drivers/gpu/msm/a2xx_reg.h | 3 +- | |
drivers/gpu/msm/a3xx_reg.h | 2 +- | |
drivers/gpu/msm/adreno.c | 4 +- | |
drivers/gpu/msm/adreno.h | 15 +- | |
drivers/gpu/msm/adreno_a2xx.c | 14 +- | |
drivers/gpu/msm/adreno_a3xx.c | 2 +- | |
drivers/gpu/msm/adreno_a3xx_snapshot.c | 2 +- | |
drivers/gpu/msm/adreno_drawctxt.c | 2 +- | |
drivers/gpu/msm/adreno_drawctxt.h | 2 +- | |
drivers/gpu/msm/adreno_ringbuffer.c | 6 +- | |
drivers/gpu/msm/adreno_ringbuffer.h | 2 +- | |
drivers/gpu/msm/adreno_snapshot.c | 2 +- | |
drivers/gpu/msm/kgsl.c | 2 +- | |
drivers/gpu/msm/kgsl.h | 2 +- | |
drivers/gpu/msm/kgsl_debugfs.c | 2 +- | |
drivers/gpu/msm/kgsl_debugfs.h | 2 +- | |
drivers/gpu/msm/kgsl_device.h | 2 +- | |
drivers/gpu/msm/kgsl_iommu.c | 2 +- | |
drivers/gpu/msm/kgsl_iommu.h | 2 +- | |
drivers/gpu/msm/kgsl_mmu.c | 2 +- | |
drivers/gpu/msm/kgsl_pwrctrl.c | 2 +- | |
drivers/gpu/msm/kgsl_pwrctrl.h | 4 +- | |
drivers/gpu/msm/kgsl_pwrscale.c | 2 +- | |
drivers/gpu/msm/kgsl_sharedmem.c | 2 +- | |
drivers/gpu/msm/kgsl_sharedmem.h | 2 +- | |
drivers/gpu/msm/kgsl_snapshot.c | 2 +- | |
drivers/gpu/msm/kgsl_trace.h | 2 +- | |
drivers/gpu/msm/z180.c | 2 +- | |
drivers/gpu/msm/z180.h | 2 +- | |
drivers/gpu/msm/z180_reg.h | 2 +- | |
.../media/dvb/mpq/demux/mpq_dmx_plugin_common.h | 4 +- | |
.../media/video/msm/gemini/msm_gemini_platform.c | 6 - | |
drivers/media/video/msm/msm_camera.c | 26 +- | |
drivers/media/video/msm/msm_isp.c | 1 - | |
drivers/media/video/msm/msm_mctl.c | 1 - | |
drivers/media/video/msm/msm_mctl_buf.c | 1 - | |
drivers/media/video/msm/msm_mctl_pp.c | 1 - | |
drivers/media/video/msm/msm_mem.c | 37 +- | |
drivers/media/video/msm/msm_v4l2_video.c | 20 +- | |
drivers/media/video/msm/msm_vfe7x.c | 2 +- | |
drivers/media/video/msm/msm_vfe7x27a.c | 1 - | |
drivers/media/video/msm/msm_vfe7x27a_v4l2.c | 2 +- | |
drivers/media/video/msm/msm_vfe_stats_buf.c | 42 +- | |
drivers/media/video/msm/wfd/wfd-ioctl.c | 2 - | |
drivers/media/video/videobuf-msm-mem.c | 58 +- | |
drivers/media/video/videobuf2-msm-mem.c | 24 +- | |
drivers/misc/qseecom.c | 4 +- | |
drivers/staging/Kconfig | 1 - | |
drivers/staging/Makefile | 2 +- | |
drivers/staging/android/binder.c | 9 +- | |
drivers/staging/qcache/Kconfig | 8 - | |
drivers/staging/qcache/Makefile | 3 - | |
drivers/staging/qcache/fmem.c | 344 ----- | |
drivers/staging/qcache/qcache-main.c | 1358 -------------------- | |
drivers/staging/qcache/tmem.c | 833 ------------ | |
drivers/staging/qcache/tmem.h | 212 --- | |
drivers/video/fbsysfs.c | 2 +- | |
drivers/video/msm/Kconfig | 3 + | |
drivers/video/msm/Makefile | 16 +- | |
drivers/video/msm/external_common.c | 2 +- | |
drivers/video/msm/external_common.h | 2 +- | |
drivers/video/msm/hdmi_msm.c | 2 +- | |
drivers/video/msm/hdmi_msm.h | 2 +- | |
drivers/video/msm/mdp.c | 4 +- | |
drivers/video/msm/mdp.h | 2 +- | |
drivers/video/msm/mdp4.h | 4 +- | |
drivers/video/msm/mdp4_hsic.c | 2 +- | |
drivers/video/msm/mdp4_overlay.c | 2 +- | |
drivers/video/msm/mdp4_overlay_dsi_cmd.c | 2 +- | |
drivers/video/msm/mdp4_overlay_mddi.c | 2 +- | |
drivers/video/msm/mdp4_overlay_writeback.c | 2 +- | |
drivers/video/msm/mdp4_util.c | 2 +- | |
drivers/video/msm/mdp4_wfd_writeback.c | 2 +- | |
drivers/video/msm/mdp_hw_init.c | 2 +- | |
drivers/video/msm/mdss/mdss.h | 2 +- | |
drivers/video/msm/mdss/mdss_fb.c | 3 +- | |
drivers/video/msm/mdss/mdss_fb.h | 4 +- | |
drivers/video/msm/mdss/mdss_mdp.c | 2 +- | |
drivers/video/msm/mdss/mdss_mdp.h | 26 +- | |
drivers/video/msm/mdss/mdss_mdp_ctl.c | 2 +- | |
drivers/video/msm/mdss/mdss_mdp_formats.h | 432 ++----- | |
drivers/video/msm/mdss/mdss_mdp_hwio.h | 2 +- | |
drivers/video/msm/mdss/mdss_mdp_intf_video.c | 2 +- | |
drivers/video/msm/mdss/mdss_mdp_intf_writeback.c | 34 +- | |
drivers/video/msm/mdss/mdss_mdp_overlay.c | 2 +- | |
drivers/video/msm/mdss/mdss_mdp_pipe.c | 66 +- | |
drivers/video/msm/mdss/mdss_mdp_pp.c | 2 +- | |
drivers/video/msm/mdss/mdss_mdp_rotator.c | 2 +- | |
drivers/video/msm/mdss/mdss_mdp_rotator.h | 2 +- | |
drivers/video/msm/mdss/mdss_mdp_util.c | 53 +- | |
drivers/video/msm/mdss/mdss_mdp_wb.c | 2 +- | |
drivers/video/msm/mdss/mdss_panel.h | 2 +- | |
drivers/video/msm/mdss/mdss_wb.c | 2 +- | |
drivers/video/msm/mhl/mhl_8334.c | 2 +- | |
drivers/video/msm/mhl/mhl_8334.h | 2 +- | |
drivers/video/msm/mhl/mhl_defs.h | 2 +- | |
drivers/video/msm/mhl/mhl_devcap.h | 2 +- | |
drivers/video/msm/mhl/mhl_i2c_utils.c | 2 +- | |
drivers/video/msm/mhl/mhl_i2c_utils.h | 2 +- | |
drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c | 2 - | |
drivers/video/msm/mipi_dsi.c | 21 +- | |
drivers/video/msm/mipi_dsi.h | 4 +- | |
drivers/video/msm/mipi_dsi_host.c | 42 +- | |
drivers/video/msm/mipi_novatek.c | 2 +- | |
drivers/video/msm/mipi_novatek_cmd_qhd_pt.c | 2 +- | |
drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c | 1 + | |
drivers/video/msm/msm_fb.h | 8 +- | |
drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c | 2 +- | |
drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h | 2 +- | |
drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h | 2 +- | |
drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h | 2 +- | |
drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c | 2 +- | |
drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c | 7 +- | |
.../msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c | 2 +- | |
.../video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c | 2 +- | |
.../video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h | 2 +- | |
.../video/msm/vidc/1080p/ddl/vcd_ddl_properties.c | 2 +- | |
.../video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c | 2 +- | |
.../video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h | 2 +- | |
drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c | 4 +- | |
drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h | 2 +- | |
drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c | 2 +- | |
drivers/video/msm/vidc/1080p/ddl/vidc.c | 2 +- | |
drivers/video/msm/vidc/1080p/ddl/vidc.h | 2 +- | |
drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h | 2 +- | |
drivers/video/msm/vidc/1080p/ddl/vidc_hwio_reg.h | 2 +- | |
drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.c | 2 +- | |
drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.h | 2 +- | |
.../vidc/1080p/resource_tracker/vcd_res_tracker.c | 4 +- | |
.../vidc/1080p/resource_tracker/vcd_res_tracker.h | 4 +- | |
.../1080p/resource_tracker/vcd_res_tracker_api.h | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vcd_ddl.c | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vcd_ddl.h | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vcd_ddl_api.h | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vcd_ddl_core.h | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c | 2 +- | |
.../msm/vidc/720p/ddl/vcd_ddl_internal_property.h | 2 +- | |
.../msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.h | 2 +- | |
.../video/msm/vidc/720p/ddl/vcd_ddl_properties.c | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c | 5 +- | |
drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vidc.c | 2 +- | |
drivers/video/msm/vidc/720p/ddl/vidc.h | 2 +- | |
.../vidc/720p/resource_tracker/vcd_res_tracker.c | 8 +- | |
.../vidc/720p/resource_tracker/vcd_res_tracker.h | 4 +- | |
.../720p/resource_tracker/vcd_res_tracker_api.h | 2 +- | |
drivers/video/msm/vidc/common/dec/vdec.c | 48 +- | |
drivers/video/msm/vidc/common/dec/vdec_internal.h | 2 +- | |
drivers/video/msm/vidc/common/enc/venc.c | 4 +- | |
drivers/video/msm/vidc/common/enc/venc_internal.c | 74 +- | |
drivers/video/msm/vidc/common/enc/venc_internal.h | 2 +- | |
drivers/video/msm/vidc/common/init/vidc_init.c | 36 +- | |
.../msm/vidc/common/init/vidc_init_internal.h | 2 +- | |
drivers/video/msm/vidc/common/vcd/vcd.h | 2 +- | |
drivers/video/msm/vidc/common/vcd/vcd_api.c | 2 +- | |
drivers/video/msm/vidc/common/vcd/vcd_client_sm.c | 2 +- | |
drivers/video/msm/vidc/common/vcd/vcd_client_sm.h | 2 +- | |
drivers/video/msm/vidc/common/vcd/vcd_core.h | 4 +- | |
drivers/video/msm/vidc/common/vcd/vcd_device_sm.c | 2 +- | |
drivers/video/msm/vidc/common/vcd/vcd_device_sm.h | 2 +- | |
drivers/video/msm/vidc/common/vcd/vcd_power_sm.c | 2 +- | |
drivers/video/msm/vidc/common/vcd/vcd_power_sm.h | 2 +- | |
drivers/video/msm/vidc/common/vcd/vcd_scheduler.c | 2 +- | |
drivers/video/msm/vidc/common/vcd/vcd_sub.c | 5 +- | |
drivers/video/msm/vidc/common/vcd/vcd_util.c | 2 +- | |
drivers/video/msm/vidc/common/vcd/vcd_util.h | 2 +- | |
include/asm-generic/vmlinux.lds.h | 5 + | |
include/linux/android_pmem.h | 1 + | |
include/linux/genlock.h | 1 + | |
include/linux/msm_audio.h | 2 +- | |
include/linux/msm_mdp.h | 2 +- | |
include/linux/netfilter/Kbuild | 10 +- | |
include/linux/netfilter/xt_CONNMARK_new.h | 6 + | |
include/linux/netfilter/xt_DSCP_new.h | 26 + | |
include/linux/netfilter/xt_MARK_new.h | 6 + | |
include/linux/netfilter/xt_RATEEST_new.h | 15 + | |
include/linux/netfilter/xt_TCPMSS_new.h | 12 + | |
include/linux/netfilter_ipv4/Kbuild | 4 +- | |
include/linux/netfilter_ipv4/ipt_ECN_new.h | 33 + | |
include/linux/netfilter_ipv4/ipt_TTL_new.h | 23 + | |
include/linux/netfilter_ipv6/Kbuild | 2 +- | |
include/linux/netfilter_ipv6/ip6t_HL_new.h | 24 + | |
include/linux/sched.h | 4 +- | |
include/linux/security.h | 1 + | |
include/linux/writeback.h | 15 + | |
kernel/sched/core.c | 3 +- | |
kernel/sched/fair.c | 12 +- | |
kernel/sched/features.h | 2 +- | |
kernel/sched/rt.c | 40 - | |
kernel/sched/sched.h | 1 - | |
kernel/sysctl.c | 27 + | |
mm/Kconfig | 9 + | |
mm/memory.c | 47 + | |
mm/page-writeback.c | 130 +- | |
mm/vmscan.c | 2 +- | |
net/ipv4/netfilter/ipt_ECN.c | 2 +- | |
net/netfilter/Makefile | 8 +- | |
net/netfilter/xt_DSCP_new.c | 164 +++ | |
net/netfilter/xt_HL_new.c | 169 +++ | |
net/netfilter/xt_RATEEST_new.c | 195 +++ | |
net/netfilter/xt_TCPMSS_new.c | 320 +++++ | |
scripts/mod/modpost.c | 2 +- | |
security/apparmor/domain.c | 35 + | |
security/commoncap.c | 7 +- | |
security/integrity/ima/ima_iint.c | 169 +++ | |
security/keys/encrypted.c | 902 +++++++++++++ | |
security/keys/encrypted.h | 54 + | |
security/selinux/hooks.c | 10 +- | |
security/smc/Makefile | 49 + | |
273 files changed, 4910 insertions(+), 5210 deletions(-) | |
create mode 100644 arch/arm/mach-msm/cpufreq_limit.c | |
create mode 100644 arch/arm/mach-msm/msm_turbo.c | |
delete mode 100644 drivers/staging/qcache/Kconfig | |
delete mode 100644 drivers/staging/qcache/Makefile | |
delete mode 100644 drivers/staging/qcache/fmem.c | |
delete mode 100644 drivers/staging/qcache/qcache-main.c | |
delete mode 100644 drivers/staging/qcache/tmem.c | |
delete mode 100644 drivers/staging/qcache/tmem.h | |
create mode 100644 include/linux/netfilter/xt_CONNMARK_new.h | |
create mode 100644 include/linux/netfilter/xt_DSCP_new.h | |
create mode 100644 include/linux/netfilter/xt_MARK_new.h | |
create mode 100644 include/linux/netfilter/xt_RATEEST_new.h | |
create mode 100644 include/linux/netfilter/xt_TCPMSS_new.h | |
create mode 100644 include/linux/netfilter_ipv4/ipt_ECN_new.h | |
create mode 100644 include/linux/netfilter_ipv4/ipt_TTL_new.h | |
create mode 100644 include/linux/netfilter_ipv6/ip6t_HL_new.h | |
create mode 100644 net/netfilter/xt_DSCP_new.c | |
create mode 100644 net/netfilter/xt_HL_new.c | |
create mode 100644 net/netfilter/xt_RATEEST_new.c | |
create mode 100644 net/netfilter/xt_TCPMSS_new.c | |
create mode 100644 security/integrity/ima/ima_iint.c | |
create mode 100644 security/keys/encrypted.c | |
create mode 100644 security/keys/encrypted.h | |
create mode 100644 security/smc/Makefile | |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S | |
index d33f4a1..176696c 100644 | |
--- a/arch/arm/kernel/vmlinux.lds.S | |
+++ b/arch/arm/kernel/vmlinux.lds.S | |
@@ -185,6 +185,7 @@ SECTIONS | |
INIT_SETUP(16) | |
INIT_CALLS | |
CON_INITCALL | |
+ COMPAT_EXPORTS | |
SECURITY_INITCALL | |
INIT_RAM_FS | |
} | |
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig | |
index 2da06bc..61c6590 100644 | |
--- a/arch/arm/mach-msm/Kconfig | |
+++ b/arch/arm/mach-msm/Kconfig | |
@@ -988,7 +988,7 @@ config PHYS_OFFSET | |
config KERNEL_MSM_CONTIG_MEM_REGION | |
bool "Enable in-kernel contiguous memory region" | |
default y if ARCH_MSM8X60 | |
- depends on ANDROID_PMEM && (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSM8974) | |
+ depends on (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSM8974) | |
help | |
Enable the in-kernel contiguous memory allocator. Sets up a | |
region of physically contiguous memory. This memory is | |
@@ -1695,7 +1695,6 @@ config MSM_AVS_HW | |
config MSM_HW3D | |
tristate "MSM Hardware 3D Register Driver" | |
- default y | |
help | |
Provides access to registers needed by the userspace OpenGL|ES | |
library. | |
@@ -2191,6 +2190,14 @@ config MSM_EVENT_TIMER | |
events that require the core to be awake and ready to handle the | |
event. | |
+config MSM_EVENT_TIMER | |
+ bool "Event timer" | |
+ help | |
+ This option enables a modules that manages a list of event timers that | |
+ need to be monitored by the PM. The enables the PM code to monitor | |
+ events that require the core to be awake and ready to handle the | |
+ event. | |
+ | |
config MSM_NOPM | |
default y if !PM | |
bool | |
@@ -2265,7 +2272,7 @@ config MSM_RUN_QUEUE_STATS | |
on when to switch off/on the other cores. | |
config MSM_SM_EVENT | |
- bool "Enable system event monitor" | |
+ bool "Enable system event monitor | |
select UNCACHED_BUF | |
default n | |
diff --git a/arch/arm/mach-msm/audio-7627a-devices.c b/arch/arm/mach-msm/audio-7627a-devices.c | |
index 30a079f..c53333b 100644 | |
--- a/arch/arm/mach-msm/audio-7627a-devices.c | |
+++ b/arch/arm/mach-msm/audio-7627a-devices.c | |
@@ -13,7 +13,7 @@ | |
#include <linux/kernel.h> | |
#include <linux/init.h> | |
#include <linux/platform_device.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <mach/board.h> | |
#include "board-msm7627a.h" | |
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c | |
index df7a974..7b1c066 100755 | |
--- a/arch/arm/mach-msm/board-msm7627a-camera.c | |
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c | |
@@ -1542,6 +1542,15 @@ static void __init msm7x27a_init_cam(void) | |
msm_camera_sensor_ov8825_data.sensor_pwd = GPIO_SKU3_CAM_5MP_SHDN_N; | |
sensor_board_info_ov8825.mount_angle = 90; | |
#endif | |
+ | |
+#ifdef CONFIG_OV5647_SUNNY_P5V02S | |
+ //Add SKUA specific settings, ov5647/Mp9v113 GPIOs | |
+ msm_camera_sensor_ov5647_data.sensor_reset = QRD_SKUA_GPIO_CAM_5MP_RESET; | |
+ msm_camera_sensor_ov5647_data.sensor_pwd = QRD_SKUA_GPIO_CAM_5MP_SHDN_EN; | |
+ msm_camera_sensor_ov5647_data.vcm_pwd = 0; | |
+ msm_camera_sensor_ov5647_data.vcm_enable = 0; | |
+#endif | |
+ | |
#ifdef CONFIG_AR0543 | |
sensor_board_info_ar0543.cam_vreg = ar0543_gpio_vreg; | |
sensor_board_info_ar0543.num_vreg = ARRAY_SIZE(ar0543_gpio_vreg); | |
@@ -1780,6 +1789,12 @@ static struct i2c_board_info i2c_camera_devices_skud[] = { | |
.platform_data = &msm_camera_sensor_ov5648_truly_cm8352_data, | |
}, | |
#endif | |
+#ifdef CONFIG_OV5647_SUNNY_P5V02S | |
+ { | |
+ I2C_BOARD_INFO("ov5647", 0x36 << 1),//original | |
+ .platform_data = &msm_camera_sensor_ov5647_data, | |
+ }, | |
+#endif | |
}; | |
static struct i2c_board_info i2c_camera_devices_skue[] = { | |
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c | |
index 5f0d75f..524e9e9 100644 | |
--- a/arch/arm/mach-msm/board-msm7x27.c | |
+++ b/arch/arm/mach-msm/board-msm7x27.c | |
@@ -54,7 +54,7 @@ | |
#include <linux/mtd/nand.h> | |
#include <linux/mtd/partitions.h> | |
#include <linux/i2c.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <mach/camera.h> | |
#ifdef CONFIG_USB_G_ANDROID | |
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c | |
index 98e98a5..7c05c23 100755 | |
--- a/arch/arm/mach-msm/board-msm7x27a.c | |
+++ b/arch/arm/mach-msm/board-msm7x27a.c | |
@@ -38,7 +38,7 @@ | |
#include <linux/i2c.h> | |
#include <linux/i2c/sx150x.h> | |
#include <linux/gpio.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <linux/bootmem.h> | |
#include <linux/mfd/marimba.h> | |
#include <mach/vreg.h> | |
@@ -68,8 +68,8 @@ | |
#include <mach/gpiomux.h> | |
-#define PMEM_KERNEL_EBI1_SIZE 0x3A000 | |
-#define MSM_PMEM_AUDIO_SIZE 0xF0000 | |
+#define RESERVE_KERNEL_EBI1_SIZE 0x3A000 | |
+#define MSM_RESERVE_AUDIO_SIZE 0xF0000 | |
#define BOOTLOADER_BASE_ADDR 0x10000 | |
//start yang.chenglei@byd added for smem_kpanic | |
@@ -208,13 +208,11 @@ static struct msm_i2c_platform_data msm_gsbi1_qup_i2c_pdata = { | |
#ifdef CONFIG_ARCH_MSM7X27A | |
//lwl modify | |
-#define MSM_PMEM_MDP_SIZE 0x2300000 | |
-//#define MSM_PMEM_MDP_SIZE 0 | |
-//end | |
-#define MSM7x25A_MSM_PMEM_MDP_SIZE 0x1500000 | |
+#define MSM_RESERVE_MDP_SIZE 0x2300000 | |
+#define MSM7x25A_MSM_RESERVE_MDP_SIZE 0x1500000 | |
-#define MSM_PMEM_ADSP_SIZE 0x1300000 | |
-#define MSM7x25A_MSM_PMEM_ADSP_SIZE 0xB91000 | |
+#define MSM_RESERVE_ADSP_SIZE 0x1300000 | |
+#define MSM7x25A_MSM_RESERVE_ADSP_SIZE 0xB91000 | |
#define CAMERA_ZSL_SIZE (SZ_1M * 60) | |
#endif | |
@@ -539,61 +537,24 @@ static struct msm_pm_boot_platform_data msm_pm_8625_boot_pdata __initdata = { | |
.v_addr = MSM_CFG_CTL_BASE, | |
}; | |
-static struct android_pmem_platform_data android_pmem_adsp_pdata = { | |
- .name = "pmem_adsp", | |
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP, | |
- .cached = 1, | |
- .memory_type = MEMTYPE_EBI1, | |
-}; | |
- | |
-static struct platform_device android_pmem_adsp_device = { | |
- .name = "android_pmem", | |
- .id = 1, | |
- .dev = { .platform_data = &android_pmem_adsp_pdata }, | |
-}; | |
- | |
-static unsigned pmem_mdp_size = MSM_PMEM_MDP_SIZE; | |
-static int __init pmem_mdp_size_setup(char *p) | |
+static unsigned reserve_mdp_size = MSM_RESERVE_MDP_SIZE; | |
+static int __init reserve_mdp_size_setup(char *p) | |
{ | |
- pmem_mdp_size = memparse(p, NULL); | |
+ reserve_mdp_size = memparse(p, NULL); | |
return 0; | |
} | |
-early_param("pmem_mdp_size", pmem_mdp_size_setup); | |
+early_param("reserve_mdp_size", reserve_mdp_size_setup); | |
-static unsigned pmem_adsp_size = MSM_PMEM_ADSP_SIZE; | |
-static int __init pmem_adsp_size_setup(char *p) | |
+static unsigned reserve_adsp_size = MSM_RESERVE_ADSP_SIZE; | |
+static int __init reserve_adsp_size_setup(char *p) | |
{ | |
- pmem_adsp_size = memparse(p, NULL); | |
+ reserve_adsp_size = memparse(p, NULL); | |
return 0; | |
} | |
-early_param("pmem_adsp_size", pmem_adsp_size_setup); | |
- | |
-static struct android_pmem_platform_data android_pmem_audio_pdata = { | |
- .name = "pmem_audio", | |
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP, | |
- .cached = 0, | |
- .memory_type = MEMTYPE_EBI1, | |
-}; | |
+early_param("reserve_adsp_size", reserve_adsp_size_setup); | |
-static struct platform_device android_pmem_audio_device = { | |
- .name = "android_pmem", | |
- .id = 2, | |
- .dev = { .platform_data = &android_pmem_audio_pdata }, | |
-}; | |
- | |
-static struct android_pmem_platform_data android_pmem_pdata = { | |
- .name = "pmem", | |
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP, | |
- .cached = 1, | |
- .memory_type = MEMTYPE_EBI1, | |
-}; | |
-static struct platform_device android_pmem_device = { | |
- .name = "android_pmem", | |
- .id = 0, | |
- .dev = { .platform_data = &android_pmem_pdata }, | |
-}; | |
static u32 msm_calculate_batt_capacity(u32 current_voltage); | |
@@ -767,9 +728,6 @@ static struct platform_device *msm7627a_surf_ffa_devices[] __initdata = { | |
static struct platform_device *common_devices[] __initdata = { | |
&android_usb_device, | |
- &android_pmem_device, | |
- &android_pmem_adsp_device, | |
- &android_pmem_audio_device, | |
&msm_device_nand, | |
&msm_device_snd, | |
&msm_device_cad, | |
@@ -797,44 +755,47 @@ static struct platform_device *msm8625_surf_devices[] __initdata = { | |
&msm8625_kgsl_3d0, | |
}; | |
-static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE; | |
-static int __init pmem_kernel_ebi1_size_setup(char *p) | |
+static unsigned reserve_kernel_ebi1_size = RESERVE_KERNEL_EBI1_SIZE; | |
+static int __init reserve_kernel_ebi1_size_setup(char *p) | |
{ | |
- pmem_kernel_ebi1_size = memparse(p, NULL); | |
+ reserve_kernel_ebi1_size = memparse(p, NULL); | |
return 0; | |
} | |
-early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup); | |
+early_param("reserve_kernel_ebi1_size", reserve_kernel_ebi1_size_setup); | |
-static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE; | |
-static int __init pmem_audio_size_setup(char *p) | |
+static unsigned reserve_audio_size = MSM_RESERVE_AUDIO_SIZE; | |
+static int __init reserve_audio_size_setup(char *p) | |
{ | |
- pmem_audio_size = memparse(p, NULL); | |
+ reserve_audio_size = memparse(p, NULL); | |
return 0; | |
} | |
-early_param("pmem_audio_size", pmem_audio_size_setup); | |
+early_param("reserve_audio_size", reserve_audio_size_setup); | |
static void fix_sizes(void) | |
{ | |
if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) { | |
- pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE; | |
- pmem_adsp_size = MSM7x25A_MSM_PMEM_ADSP_SIZE; | |
+ reserve_mdp_size = MSM7x25A_MSM_RESERVE_MDP_SIZE;; | |
+ reserve_adsp_size = MSM7x25A_MSM_RESERVE_ADSP_SIZE; | |
} else { | |
- pmem_mdp_size = MSM_PMEM_MDP_SIZE; | |
- pmem_adsp_size = MSM_PMEM_ADSP_SIZE; | |
+ reserve_mdp_size = MSM_RESERVE_MDP_SIZE; | |
+ reserve_adsp_size = MSM_RESERVE_ADSP_SIZE; | |
} | |
- //if (get_ddr_size() > SZ_512M) | |
- // pmem_adsp_size = CAMERA_ZSL_SIZE; | |
+ if (get_ddr_size() > SZ_512M) | |
+ reserve_adsp_size = CAMERA_ZSL_SIZE; | |
#ifdef CONFIG_ION_MSM | |
- msm_ion_audio_size = MSM_PMEM_AUDIO_SIZE; | |
- msm_ion_sf_size = pmem_mdp_size; | |
+ msm_ion_audio_size = MSM_RESERVE_AUDIO_SIZE; | |
+ msm_ion_sf_size = reserve_mdp_size; | |
#ifdef CONFIG_CMA | |
- msm_ion_camera_size = CAMERA_ZSL_SIZE; | |
- msm_ion_camera_size_carving = 0; | |
+ if (get_ddr_size() > SZ_256M) | |
+ reserve_adsp_size = CAMERA_ZSL_SIZE; | |
+ msm_ion_camera_size = reserve_adsp_size; | |
+ msm_ion_camera_size_carving = 0; | |
#else | |
- msm_ion_camera_size = pmem_adsp_size; | |
+ msm_ion_camera_size = reserve_adsp_size; | |
msm_ion_camera_size_carving = msm_ion_camera_size; | |
+ | |
#endif | |
#endif | |
} | |
@@ -874,7 +835,7 @@ struct ion_platform_heap msm7x27a_heaps[] = { | |
.name = ION_VMALLOC_HEAP_NAME, | |
}, | |
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
- /* PMEM_ADSP = CAMERA */ | |
+ /* ION_ADSP = CAMERA */ | |
{ | |
.id = ION_CAMERA_HEAP_ID, | |
.type = CAMERA_HEAP_TYPE, | |
@@ -891,7 +852,7 @@ struct ion_platform_heap msm7x27a_heaps[] = { | |
.memory_type = ION_EBI_TYPE, | |
.extra_data = (void *)&co_ion_pdata, | |
}, | |
- /* PMEM_MDP = SF */ | |
+ /* ION_MDP = SF */ | |
{ | |
.id = ION_SF_HEAP_ID, | |
.type = ION_HEAP_TYPE_CARVEOUT, | |
@@ -936,54 +897,11 @@ static struct memtype_reserve msm7x27a_reserve_table[] __initdata = { | |
}, | |
}; | |
-#ifdef CONFIG_ANDROID_PMEM | |
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION | |
-static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = { | |
- &android_pmem_adsp_pdata, | |
- &android_pmem_audio_pdata, | |
- &android_pmem_pdata, | |
-}; | |
-#endif | |
-#endif | |
- | |
-static void __init size_pmem_devices(void) | |
-{ | |
-#ifdef CONFIG_ANDROID_PMEM | |
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION | |
- android_pmem_adsp_pdata.size = pmem_adsp_size; | |
- android_pmem_pdata.size = pmem_mdp_size; | |
- android_pmem_audio_pdata.size = pmem_audio_size; | |
-#endif | |
-#endif | |
-} | |
- | |
-#ifdef CONFIG_ANDROID_PMEM | |
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION | |
-static void __init reserve_memory_for(struct android_pmem_platform_data *p) | |
-{ | |
- msm7x27a_reserve_table[p->memory_type].size += p->size; | |
-} | |
-#endif | |
-#endif | |
- | |
-static void __init reserve_pmem_memory(void) | |
-{ | |
-#ifdef CONFIG_ANDROID_PMEM | |
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION | |
- unsigned int i; | |
- for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) | |
- reserve_memory_for(pmem_pdata_array[i]); | |
- | |
- msm7x27a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size; | |
-#endif | |
-#endif | |
-} | |
- | |
static void __init size_ion_devices(void) | |
{ | |
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
ion_pdata.heaps[1].size = msm_ion_camera_size; | |
- ion_pdata.heaps[2].size = PMEM_KERNEL_EBI1_SIZE; | |
+ ion_pdata.heaps[2].size = RESERVE_KERNEL_EBI1_SIZE; | |
ion_pdata.heaps[3].size = msm_ion_sf_size; | |
ion_pdata.heaps[4].size = msm_ion_audio_size; | |
#endif | |
@@ -992,8 +910,8 @@ static void __init size_ion_devices(void) | |
static void __init reserve_ion_memory(void) | |
{ | |
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION) | |
- msm7x27a_reserve_table[MEMTYPE_EBI1].size += PMEM_KERNEL_EBI1_SIZE; | |
- msm7x27a_reserve_table[MEMTYPE_EBI1].size += | |
+ msm7x27a_reserve_table[MEMTYPE_EBI1].size += RESERVE_KERNEL_EBI1_SIZE; | |
+ msm7x27a_reserve_table[MEMTYPE_EBI1].size += | |
msm_ion_camera_size_carving; | |
msm7x27a_reserve_table[MEMTYPE_EBI1].size += msm_ion_sf_size; | |
#endif | |
@@ -1002,8 +920,6 @@ static void __init reserve_ion_memory(void) | |
static void __init msm7x27a_calculate_reserve_sizes(void) | |
{ | |
fix_sizes(); | |
- size_pmem_devices(); | |
- reserve_pmem_memory(); | |
size_ion_devices(); | |
reserve_ion_memory(); | |
} | |
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c | |
index 89b86a3..bde0aac 100755 | |
--- a/arch/arm/mach-msm/board-qrd7627a.c | |
+++ b/arch/arm/mach-msm/board-qrd7627a.c | |
@@ -20,7 +20,7 @@ | |
#include <linux/mtd/nand.h> | |
#include <linux/mtd/partitions.h> | |
#include <linux/i2c.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <linux/bootmem.h> | |
#include <linux/mfd/marimba.h> | |
#include <linux/power_supply.h> | |
@@ -70,8 +70,8 @@ | |
#include "board-msm7627a.h" | |
#include "board-msm7627a-sensor.h" | |
-#define PMEM_KERNEL_EBI1_SIZE 0x3A000 | |
-#define MSM_PMEM_AUDIO_SIZE 0xF0000 | |
+#define RESERVE_KERNEL_EBI1_SIZE 0x3A000 | |
+#define MSM_RESERVE_AUDIO_SIZE 0xF0000 | |
#define BOOTLOADER_BASE_ADDR 0x10000 | |
#define BAHAMA_SLAVE_ID_FM_REG 0x02 | |
#define FM_GPIO 83 | |
@@ -182,8 +182,8 @@ static struct platform_device msm8625q_i2c_gpio = { | |
}; | |
#ifdef CONFIG_ARCH_MSM7X27A | |
-#define MSM_PMEM_MDP_SIZE 0x2300000 | |
-#define MSM_PMEM_ADSP_SIZE 0x1200000 | |
+#define MSM_RESERVE_MDP_SIZE 0x2300000 | |
+#define MSM_RESERVE_ADSP_SIZE 0x9600000 | |
#define CAMERA_ZSL_SIZE (SZ_1M * 60) | |
#ifdef CONFIG_ION_MSM | |
@@ -491,61 +491,23 @@ static struct msm_pm_boot_platform_data msm_pm_8625_boot_pdata __initdata = { | |
.v_addr = MSM_CFG_CTL_BASE, | |
}; | |
-static struct android_pmem_platform_data android_pmem_adsp_pdata = { | |
- .name = "pmem_adsp", | |
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP, | |
- .cached = 1, | |
- .memory_type = MEMTYPE_EBI1, | |
-}; | |
- | |
-static struct platform_device android_pmem_adsp_device = { | |
- .name = "android_pmem", | |
- .id = 1, | |
- .dev = { .platform_data = &android_pmem_adsp_pdata }, | |
-}; | |
- | |
-static unsigned pmem_mdp_size = MSM_PMEM_MDP_SIZE; | |
-static int __init pmem_mdp_size_setup(char *p) | |
+static unsigned reserve_mdp_size = MSM_RESERVE_MDP_SIZE; | |
+static int __init reserve_mdp_size_setup(char *p) | |
{ | |
- pmem_mdp_size = memparse(p, NULL); | |
+ reserve_mdp_size = memparse(p, NULL); | |
return 0; | |
} | |
-early_param("pmem_mdp_size", pmem_mdp_size_setup); | |
+early_param("reserve_mdp_size", reserve_mdp_size_setup); | |
-static unsigned pmem_adsp_size = MSM_PMEM_ADSP_SIZE; | |
-static int __init pmem_adsp_size_setup(char *p) | |
+static unsigned reserve_adsp_size = MSM_RESERVE_ADSP_SIZE; | |
+static int __init reserve_adsp_size_setup(char *p) | |
{ | |
- pmem_adsp_size = memparse(p, NULL); | |
+ reserve_adsp_size = memparse(p, NULL); | |
return 0; | |
} | |
-early_param("pmem_adsp_size", pmem_adsp_size_setup); | |
- | |
-static struct android_pmem_platform_data android_pmem_audio_pdata = { | |
- .name = "pmem_audio", | |
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP, | |
- .cached = 0, | |
- .memory_type = MEMTYPE_EBI1, | |
-}; | |
- | |
-static struct platform_device android_pmem_audio_device = { | |
- .name = "android_pmem", | |
- .id = 2, | |
- .dev = { .platform_data = &android_pmem_audio_pdata }, | |
-}; | |
- | |
-static struct android_pmem_platform_data android_pmem_pdata = { | |
- .name = "pmem", | |
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP, | |
- .cached = 1, | |
- .memory_type = MEMTYPE_EBI1, | |
-}; | |
-static struct platform_device android_pmem_device = { | |
- .name = "android_pmem", | |
- .id = 0, | |
- .dev = { .platform_data = &android_pmem_pdata }, | |
-}; | |
+early_param("reserve_adsp_size", reserve_adsp_size_setup); | |
static u32 msm_calculate_batt_capacity(u32 current_voltage); | |
@@ -793,9 +755,6 @@ static struct i2c_board_info i2c2_info[] __initdata = { | |
static struct platform_device *common_devices[] __initdata = { | |
&android_usb_device, | |
- &android_pmem_device, | |
- &android_pmem_adsp_device, | |
- &android_pmem_audio_device, | |
&msm_batt_device, | |
&msm_device_adspdec, | |
&msm_device_snd, | |
@@ -858,42 +817,44 @@ static struct platform_device *msm8625q_lcd_camera_devices[] __initdata = { | |
&evbd_vreg_gpio_ext_1p8v, | |
}; | |
-static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE; | |
-static int __init pmem_kernel_ebi1_size_setup(char *p) | |
+static unsigned reserve_kernel_ebi1_size = RESERVE_KERNEL_EBI1_SIZE; | |
+static int __init reserve_kernel_ebi1_size_setup(char *p) | |
{ | |
- pmem_kernel_ebi1_size = memparse(p, NULL); | |
+ reserve_kernel_ebi1_size = memparse(p, NULL); | |
return 0; | |
} | |
-early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup); | |
+early_param("reserve_kernel_ebi1_size", reserve_kernel_ebi1_size_setup); | |
-static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE; | |
-static int __init pmem_audio_size_setup(char *p) | |
+static unsigned reserve_audio_size = MSM_RESERVE_AUDIO_SIZE; | |
+static int __init reserve_audio_size_setup(char *p) | |
{ | |
- pmem_audio_size = memparse(p, NULL); | |
+ reserve_audio_size = memparse(p, NULL); | |
return 0; | |
} | |
-early_param("pmem_audio_size", pmem_audio_size_setup); | |
+early_param("reserve_audio_size", reserve_audio_size_setup); | |
static void fix_sizes(void) | |
{ | |
if (get_ddr_size() > SZ_512M) | |
- pmem_adsp_size = CAMERA_ZSL_SIZE; | |
+ reserve_adsp_size = CAMERA_ZSL_SIZE; | |
else { | |
if (machine_is_msm8625q_skue() || machine_is_msm8625q_evbd() | |
|| machine_is_msm8625q_skud()) | |
- pmem_mdp_size = 0; | |
+ reserve_mdp_size = 0; | |
} | |
#ifdef CONFIG_ION_MSM | |
- msm_ion_audio_size = MSM_PMEM_AUDIO_SIZE; | |
+ msm_ion_audio_size = MSM_RESERVE_AUDIO_SIZE; | |
+ msm_ion_sf_size = reserve_mdp_size; | |
#ifdef CONFIG_CMA | |
- msm_ion_camera_size = CAMERA_ZSL_SIZE; | |
- msm_ion_camera_size_carving = 0; | |
+ if (get_ddr_size() > SZ_256M) | |
+ reserve_adsp_size = CAMERA_ZSL_SIZE; | |
+ msm_ion_camera_size = reserve_adsp_size; | |
+ msm_ion_camera_size_carving = 0; | |
#else | |
- msm_ion_camera_size = pmem_adsp_size; | |
- msm_ion_camera_size_carving = msm_ion_camera_size; | |
+ msm_ion_camera_size = reserve_adsp_size; | |
+ msm_ion_camera_size_carving = msm_ion_camera_size; | |
#endif | |
- msm_ion_sf_size = pmem_mdp_size; | |
#endif | |
} | |
@@ -932,7 +893,7 @@ struct ion_platform_heap msm7627a_heaps[] = { | |
.name = ION_VMALLOC_HEAP_NAME, | |
}, | |
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
- /* PMEM_ADSP = CAMERA */ | |
+ /* ION_ADSP = CAMERA */ | |
{ | |
.id = ION_CAMERA_HEAP_ID, | |
.type = CAMERA_HEAP_TYPE, | |
@@ -949,7 +910,7 @@ struct ion_platform_heap msm7627a_heaps[] = { | |
.memory_type = ION_EBI_TYPE, | |
.extra_data = (void *)&co_ion_pdata, | |
}, | |
- /* PMEM_MDP = SF */ | |
+ /* ION_MDP = SF */ | |
{ | |
.id = ION_SF_HEAP_ID, | |
.type = ION_HEAP_TYPE_CARVEOUT, | |
@@ -994,56 +955,11 @@ static struct memtype_reserve msm7627a_reserve_table[] __initdata = { | |
}, | |
}; | |
-#ifdef CONFIG_ANDROID_PMEM | |
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION | |
-static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = { | |
- &android_pmem_adsp_pdata, | |
- &android_pmem_audio_pdata, | |
- &android_pmem_pdata, | |
-}; | |
-#endif | |
-#endif | |
- | |
-static void __init size_pmem_devices(void) | |
-{ | |
-#ifdef CONFIG_ANDROID_PMEM | |
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION | |
- unsigned int i; | |
- | |
- android_pmem_adsp_pdata.size = pmem_adsp_size; | |
- android_pmem_pdata.size = pmem_mdp_size; | |
- android_pmem_audio_pdata.size = pmem_audio_size; | |
-#endif | |
-#endif | |
-} | |
- | |
-#ifdef CONFIG_ANDROID_PMEM | |
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION | |
-static void __init reserve_memory_for(struct android_pmem_platform_data *p) | |
-{ | |
- msm7627a_reserve_table[p->memory_type].size += p->size; | |
-} | |
-#endif | |
-#endif | |
- | |
-static void __init reserve_pmem_memory(void) | |
-{ | |
-#ifdef CONFIG_ANDROID_PMEM | |
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION | |
- unsigned int i; | |
- for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) | |
- reserve_memory_for(pmem_pdata_array[i]); | |
- | |
- msm7627a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size; | |
-#endif | |
-#endif | |
-} | |
- | |
static void __init size_ion_devices(void) | |
{ | |
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
ion_pdata.heaps[1].size = msm_ion_camera_size; | |
- ion_pdata.heaps[2].size = PMEM_KERNEL_EBI1_SIZE; | |
+ ion_pdata.heaps[2].size = RESERVE_KERNEL_EBI1_SIZE; | |
ion_pdata.heaps[3].size = msm_ion_sf_size; | |
ion_pdata.heaps[4].size = msm_ion_audio_size; | |
#endif | |
@@ -1052,18 +968,16 @@ static void __init size_ion_devices(void) | |
static void __init reserve_ion_memory(void) | |
{ | |
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION) | |
- msm7627a_reserve_table[MEMTYPE_EBI1].size += PMEM_KERNEL_EBI1_SIZE; | |
- msm7627a_reserve_table[MEMTYPE_EBI1].size += msm_ion_sf_size; | |
- msm7627a_reserve_table[MEMTYPE_EBI1].size += | |
+ msm7627a_reserve_table[MEMTYPE_EBI1].size += RESERVE_KERNEL_EBI1_SIZE; | |
+ msm7627a_reserve_table[MEMTYPE_EBI1].size += | |
msm_ion_camera_size_carving; | |
+ msm7627a_reserve_table[MEMTYPE_EBI1].size += msm_ion_sf_size; | |
#endif | |
} | |
static void __init msm7627a_calculate_reserve_sizes(void) | |
{ | |
fix_sizes(); | |
- size_pmem_devices(); | |
- reserve_pmem_memory(); | |
size_ion_devices(); | |
reserve_ion_memory(); | |
} | |
diff --git a/arch/arm/mach-msm/cpufreq_limit.c b/arch/arm/mach-msm/cpufreq_limit.c | |
new file mode 100644 | |
index 0000000..7ce63cc | |
--- /dev/null | |
+++ b/arch/arm/mach-msm/cpufreq_limit.c | |
@@ -0,0 +1,128 @@ | |
+/* | |
+ * Author: Paul Reioux aka Faux123 <reioux@gmail.com> | |
+ * | |
+ * Copyright 2012 Paul Reioux | |
+ * | |
+ * 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/module.h> | |
+#include <linux/kobject.h> | |
+#include <linux/sysfs.h> | |
+ | |
+#include <linux/cpu.h> | |
+#include <linux/cpufreq.h> | |
+ | |
+#include <mach/cpufreq.h> | |
+ | |
+#define MSM_CPUFREQ_LIMIT_VERSION 1 | |
+ | |
+static uint32_t limited_max_freq = MSM_CPUFREQ_NO_LIMIT; | |
+ | |
+static int update_cpu_max_freq(int cpu, uint32_t max_freq) | |
+{ | |
+ int ret = 0; | |
+ | |
+ ret = msm_cpufreq_set_freq_limits(cpu, MSM_CPUFREQ_NO_LIMIT, max_freq); | |
+ if (ret) | |
+ return ret; | |
+ | |
+ limited_max_freq = max_freq; | |
+ if (max_freq != MSM_CPUFREQ_NO_LIMIT) | |
+ pr_info("msm_cpufreq_limit: Limiting cpu%d max frequency to %d\n", | |
+ cpu, max_freq); | |
+ else | |
+ pr_info("msm_cpufreq_limit: Max frequency reset for cpu%d\n", cpu); | |
+ | |
+ ret = cpufreq_update_policy(cpu); | |
+ | |
+ return ret; | |
+} | |
+ | |
+static ssize_t msm_cpufreq_limit_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) | |
+{ | |
+ return sprintf(buf, "%u\n", limited_max_freq); | |
+} | |
+ | |
+static ssize_t msm_cpufreq_limit_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) | |
+{ | |
+ int cpu = 0; | |
+ int ret = 0; | |
+ uint32_t max_freq = limited_max_freq; | |
+ | |
+ unsigned int data; | |
+ | |
+ if(sscanf(buf, "%u\n", &data) == 1) { | |
+ for_each_possible_cpu(cpu) { | |
+ ret = update_cpu_max_freq(cpu, max_freq); | |
+ if (ret) | |
+ pr_debug("Unable to limit cpu%d max freq to %d\n", | |
+ cpu, max_freq); | |
+ } | |
+ if (!ret) | |
+ limited_max_freq = data; | |
+ } | |
+ | |
+ return count; | |
+} | |
+ | |
+static ssize_t msm_cpufreq_limit_version_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) | |
+{ | |
+ return sprintf(buf, "version: %u\n", MSM_CPUFREQ_LIMIT_VERSION); | |
+} | |
+ | |
+static struct kobj_attribute msm_cpufreq_limit_attribute = | |
+ __ATTR(cpufreq_limit, 0666, msm_cpufreq_limit_show, msm_cpufreq_limit_store); | |
+ | |
+static struct kobj_attribute msm_cpufreq_limit_version_attribute = | |
+ __ATTR(msm_cpufreq_limit_version, 0444 , msm_cpufreq_limit_version_show, NULL); | |
+ | |
+static struct attribute *msm_cpufreq_limit_attrs[] = | |
+ { | |
+ &msm_cpufreq_limit_attribute.attr, | |
+ &msm_cpufreq_limit_version_attribute.attr, | |
+ NULL, | |
+ }; | |
+ | |
+static struct attribute_group msm_cpufreq_limit_attr_group = | |
+ { | |
+ .attrs = msm_cpufreq_limit_attrs, | |
+ }; | |
+ | |
+static struct kobject *msm_cpufreq_limit_kobj; | |
+ | |
+static int msm_cpufreq_limit_init(void) | |
+{ | |
+ int sysfs_result; | |
+ | |
+ msm_cpufreq_limit_kobj = kobject_create_and_add("msm_cpufreq_limit", kernel_kobj); | |
+ if (!msm_cpufreq_limit_kobj) { | |
+ pr_err("%s msm_cpufreq_limit_kobj kobject create failed!\n", __FUNCTION__); | |
+ return -ENOMEM; | |
+ } | |
+ | |
+ sysfs_result = sysfs_create_group(msm_cpufreq_limit_kobj, &msm_cpufreq_limit_attr_group); | |
+ | |
+ if (sysfs_result) { | |
+ pr_info("%s msm_cpufreq_limit_kobj create failed!\n", __FUNCTION__); | |
+ kobject_put(msm_cpufreq_limit_kobj); | |
+ } | |
+ return sysfs_result; | |
+} | |
+ | |
+static void msm_cpufreq_limit_exit(void) | |
+{ | |
+ if (msm_cpufreq_limit_kobj != NULL) | |
+ kobject_put(msm_cpufreq_limit_kobj); | |
+} | |
+ | |
+module_init(msm_cpufreq_limit_init); | |
+module_exit(msm_cpufreq_limit_exit); | |
\ No newline at end of file | |
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c | |
index 789f3b2..b074ab5 100755 | |
--- a/arch/arm/mach-msm/devices-msm7x27a.c | |
+++ b/arch/arm/mach-msm/devices-msm7x27a.c | |
@@ -968,27 +968,15 @@ void __init msm8x25_kgsl_3d0_init(void) | |
kgsl_3d0_pdata.strtstp_sleepwake = false; | |
if (cpu_is_msm8625()) { | |
- if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2) | |
/* 8x25 v2.0 & above supports a higher GPU frequency */ | |
- kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 320000000; | |
- else | |
- kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 300000000; | |
- | |
+ kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 320000000; | |
kgsl_3d0_pdata.pwrlevel[0].bus_freq = 200000000; | |
} else if (cpu_is_msm8625q()) { | |
- kgsl_3d0_pdata.num_levels = 4; | |
+ //kgsl_3d0_pdata.num_levels = 4; | |
kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 400000000; | |
kgsl_3d0_pdata.pwrlevel[0].bus_freq = 300000000; | |
- kgsl_3d0_pdata.pwrlevel[1].gpu_freq = 320000000; | |
- kgsl_3d0_pdata.pwrlevel[1].bus_freq = 300000000; | |
- | |
- kgsl_3d0_pdata.pwrlevel[2].gpu_freq = 245760000; | |
- kgsl_3d0_pdata.pwrlevel[2].bus_freq = 160000000; | |
- | |
- kgsl_3d0_pdata.pwrlevel[3].gpu_freq = 133000000; | |
- kgsl_3d0_pdata.pwrlevel[3].bus_freq = 0; | |
} | |
} | |
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h | |
index 88ad993..45c6ce5 100644 | |
--- a/arch/arm/mach-msm/include/mach/iommu.h | |
+++ b/arch/arm/mach-msm/include/mach/iommu.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
@@ -69,6 +69,10 @@ struct msm_iommu_ctx_dev { | |
* @irq: Interrupt number | |
* @clk: The bus clock for this IOMMU hardware instance | |
* @pclk: The clock for the IOMMU bus interconnect | |
+ * @aclk: Alternate clock for this IOMMU core, if any | |
+ * @name: Human-readable name of this IOMMU device | |
+ * @gdsc: Regulator needed to power this HW block (v2 only) | |
+ * @nsmr: Size of the SMT on this HW block (v2 only) | |
* | |
* A msm_iommu_drvdata holds the global driver data about a single piece | |
* of an IOMMU hardware instance. | |
@@ -89,6 +93,10 @@ struct msm_iommu_drvdata { | |
* @pdev: Platform device associated wit this HW instance | |
* @attached_elm: List element for domains to track which devices are | |
* attached to them | |
+ * @attached_domain Domain currently attached to this context (if any) | |
+ * @name Human-readable name of this context device | |
+ * @sids List of Stream IDs mapped to this context (v2 only) | |
+ * @nsid Number of Stream IDs mapped to this context (v2 only) | |
* | |
* A msm_iommu_ctx_drvdata holds the driver data for a single context bank | |
* within each IOMMU hardware instance | |
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h | |
index 94c9553..fa24f7e 100644 | |
--- a/arch/arm/mach-msm/include/mach/memory.h | |
+++ b/arch/arm/mach-msm/include/mach/memory.h | |
@@ -1,7 +1,7 @@ | |
/* arch/arm/mach-msm/include/mach/memory.h | |
* | |
* Copyright (C) 2007 Google, Inc. | |
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved. | |
* | |
* This software is licensed under the terms of the GNU General Public | |
* License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/msm_adsp.h b/arch/arm/mach-msm/include/mach/msm_adsp.h | |
index 0797447..ea08f0c 100644 | |
--- a/arch/arm/mach-msm/include/mach/msm_adsp.h | |
+++ b/arch/arm/mach-msm/include/mach/msm_adsp.h | |
@@ -1,7 +1,7 @@ | |
/* include/asm-arm/arch-msm/msm_adsp.h | |
* | |
* Copyright (C) 2008 Google, Inc. | |
- * Copyright (c) 2009-2010, 2012 The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2009-2010, 2012 Code Aurora Forum. All rights reserved. | |
* | |
* This software is licensed under the terms of the GNU General Public | |
* License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/msm_audio_aac.h b/arch/arm/mach-msm/include/mach/msm_audio_aac.h | |
index ac54173..8c4d91b 100644 | |
--- a/arch/arm/mach-msm/include/mach/msm_audio_aac.h | |
+++ b/arch/arm/mach-msm/include/mach/msm_audio_aac.h | |
@@ -1,6 +1,6 @@ | |
/* arch/arm/mach-msm/include/mach/msm_audio_aac.h | |
* | |
- * Copyright (c) 2009 The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2009 Code Aurora Forum. 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 and | |
diff --git a/arch/arm/mach-msm/include/mach/msm_bus.h b/arch/arm/mach-msm/include/mach/msm_bus.h | |
index 37add65..aacf1f7 100644 | |
--- a/arch/arm/mach-msm/include/mach/msm_bus.h | |
+++ b/arch/arm/mach-msm/include/mach/msm_bus.h | |
@@ -43,8 +43,8 @@ | |
struct msm_bus_vectors { | |
int src; /* Master */ | |
int dst; /* Slave */ | |
- unsigned int ab; /* Arbitrated bandwidth */ | |
- unsigned int ib; /* Instantaneous bandwidth */ | |
+ uint64_t ab; /* Arbitrated bandwidth */ | |
+ uint64_t ib; /* Instantaneous bandwidth */ | |
}; | |
struct msm_bus_paths { | |
diff --git a/arch/arm/mach-msm/include/mach/msm_bus_board.h b/arch/arm/mach-msm/include/mach/msm_bus_board.h | |
index 3e221aa..d95e4a4 100644 | |
--- a/arch/arm/mach-msm/include/mach/msm_bus_board.h | |
+++ b/arch/arm/mach-msm/include/mach/msm_bus_board.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/arch/arm/mach-msm/include/mach/msm_dcvs.h b/arch/arm/mach-msm/include/mach/msm_dcvs.h | |
index d546b43..492885a 100644 | |
--- a/arch/arm/mach-msm/include/mach/msm_dcvs.h | |
+++ b/arch/arm/mach-msm/include/mach/msm_dcvs.h | |
@@ -18,6 +18,12 @@ | |
#define CORE_NAME_MAX (32) | |
#define CORES_MAX (10) | |
+#define CPU_OFFSET 1 /* used to notify TZ the core number */ | |
+#define GPU_OFFSET (CORES_MAX * 2/3) /* there will be more cpus than gpus, | |
+ * let the GPU be assigned fewer core | |
+ * elements and start later | |
+ */ | |
+ | |
enum msm_core_idle_state { | |
MSM_DCVS_IDLE_ENTER, | |
MSM_DCVS_IDLE_EXIT, | |
@@ -30,43 +36,14 @@ enum msm_core_control_event { | |
MSM_DCVS_DISABLE_HIGH_LATENCY_MODES, | |
}; | |
-/** | |
- * struct msm_dcvs_idle | |
- * | |
- * API for idle code to register and send idle enter/exit | |
- * notifications to msm_dcvs driver. | |
- */ | |
-struct msm_dcvs_idle { | |
- const char *core_name; | |
- /* Enable/Disable idle state/notifications */ | |
- int (*enable)(struct msm_dcvs_idle *self, | |
- enum msm_core_control_event event); | |
+struct msm_gov_platform_data { | |
+ struct msm_dcvs_core_info *info; | |
+ int latency; | |
}; | |
/** | |
- * msm_dcvs_idle_source_register | |
- * @drv: Pointer to the source driver | |
- * @return: Handle to be used for sending idle state notifications. | |
- * | |
- * Register the idle driver with the msm_dcvs driver to send idle | |
- * state notifications for the core. | |
- */ | |
-extern int msm_dcvs_idle_source_register(struct msm_dcvs_idle *drv); | |
- | |
-/** | |
- * msm_dcvs_idle_source_unregister | |
- * @drv: Pointer to the source driver | |
- * @return: | |
- * 0 on success | |
- * -EINVAL | |
- * | |
- * Description: Unregister the idle driver with the msm_dcvs driver | |
- */ | |
-extern int msm_dcvs_idle_source_unregister(struct msm_dcvs_idle *drv); | |
- | |
-/** | |
* msm_dcvs_idle | |
- * @handle: Handle provided back at registration | |
+ * @dcvs_core_id: The id returned by msm_dcvs_register_core | |
* @state: The enter/exit idle state the core is in | |
* @iowaited: iowait in us | |
* on iMSM_DCVS_IDLE_EXIT. | |
@@ -78,7 +55,7 @@ extern int msm_dcvs_idle_source_unregister(struct msm_dcvs_idle *drv); | |
* | |
* Send idle state notifications to the msm_dcvs driver | |
*/ | |
-int msm_dcvs_idle(int handle, enum msm_core_idle_state state, | |
+int msm_dcvs_idle(int dcvs_core_id, enum msm_core_idle_state state, | |
uint32_t iowaited); | |
/** | |
@@ -95,9 +72,10 @@ struct msm_dcvs_core_info { | |
/** | |
* msm_dcvs_register_core | |
- * @core_name: Unique name identifier for the core. | |
- * @group_id: Cores that are to be grouped for synchronized frequency scaling | |
+ * @type: whether this is a CPU or a GPU | |
+ * @type_core_num: The number of the core for a type | |
* @info: The core specific algorithm parameters. | |
+ * @sensor: The thermal sensor number of the core in question | |
* @return : | |
* 0 on success, | |
* -ENOSYS, | |
@@ -106,37 +84,30 @@ struct msm_dcvs_core_info { | |
* Register the core with msm_dcvs driver. Done once at init before calling | |
* msm_dcvs_freq_sink_register | |
* Cores that need to run synchronously must share the same group id. | |
- * If a core doesnt care to be in any group, the group_id should be 0. | |
- */ | |
-extern int msm_dcvs_register_core(const char *core_name, uint32_t group_id, | |
- struct msm_dcvs_core_info *info); | |
- | |
-/** | |
- * struct msm_dcvs_freq | |
- * | |
- * API for clock driver code to register and receive frequency change | |
- * request for the core from the msm_dcvs driver. | |
*/ | |
-struct msm_dcvs_freq { | |
- const char *core_name; | |
- /* Callback from msm_dcvs to set the core frequency */ | |
- int (*set_frequency)(struct msm_dcvs_freq *self, | |
- unsigned int freq); | |
- unsigned int (*get_frequency)(struct msm_dcvs_freq *self); | |
-}; | |
+extern int msm_dcvs_register_core( | |
+ enum msm_dcvs_core_type type, | |
+ int type_core_num, | |
+ struct msm_dcvs_core_info *info, | |
+ int (*set_frequency)(int type_core_num, unsigned int freq), | |
+ unsigned int (*get_frequency)(int type_core_num), | |
+ int (*idle_enable)(int type_core_num, | |
+ enum msm_core_control_event event), | |
+ int (*set_floor_frequency)(int type_core_num, unsigned int freq), | |
+ int sensor); | |
/** | |
- * msm_dcvs_freq_sink_register | |
+ * msm_dcvs_freq_sink_start | |
* @drv: The sink driver | |
* @return: Handle unique to the core. | |
* | |
* Register the clock driver code with the msm_dvs driver to get notified about | |
* frequency change requests. | |
*/ | |
-extern int msm_dcvs_freq_sink_register(struct msm_dcvs_freq *drv); | |
+extern int msm_dcvs_freq_sink_start(int dcvs_core_id); | |
/** | |
- * msm_dcvs_freq_sink_unregister | |
+ * msm_dcvs_freq_sink_stop | |
* @drv: The sink driver | |
* @return: | |
* 0 on success, | |
@@ -145,6 +116,13 @@ extern int msm_dcvs_freq_sink_register(struct msm_dcvs_freq *drv); | |
* Unregister the sink driver for the core. This will cause the source driver | |
* for the core to stop sending idle pulses. | |
*/ | |
-extern int msm_dcvs_freq_sink_unregister(struct msm_dcvs_freq *drv); | |
+extern int msm_dcvs_freq_sink_stop(int dcvs_core_id); | |
+/** | |
+ * msm_dcvs_update_limits | |
+ * @drv: The sink driver | |
+ * | |
+ * Update the frequency known to dcvs when the limits are changed. | |
+ */ | |
+extern void msm_dcvs_update_limits(int dcvs_core_id); | |
#endif | |
diff --git a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h | |
index 63474db..3969a72 100644 | |
--- a/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h | |
+++ b/arch/arm/mach-msm/include/mach/msm_dcvs_scm.h | |
@@ -45,7 +45,6 @@ struct msm_dcvs_core_param { | |
uint32_t num_freq; /* number of msm_dcvs_freq_entry passed */ | |
}; | |
- | |
#ifdef CONFIG_MSM_DCVS | |
/** | |
* Initialize DCVS algorithm in TrustZone. | |
@@ -61,20 +60,9 @@ struct msm_dcvs_core_param { | |
extern int msm_dcvs_scm_init(size_t size); | |
/** | |
- * Create an empty core group | |
- * | |
- * @return: | |
- * 0 on success. | |
- * -ENOMEM: Insufficient memory. | |
- * -EINVAL: Invalid args. | |
- */ | |
-extern int msm_dcvs_scm_create_group(uint32_t id); | |
- | |
-/** | |
- * Registers cores as part of a group | |
+ * Registers cores with the DCVS algo. | |
* | |
* @core_id: The core identifier that will be used for communication with DCVS | |
- * @group_id: The group to which this core will be added to. | |
* @param: The core parameters | |
* @freq: Array of frequency and energy values | |
* | |
@@ -83,9 +71,8 @@ extern int msm_dcvs_scm_create_group(uint32_t id); | |
* -ENOMEM: Insufficient memory. | |
* -EINVAL: Invalid args. | |
*/ | |
-extern int msm_dcvs_scm_register_core(uint32_t core_id, uint32_t group_id, | |
- struct msm_dcvs_core_param *param, | |
- struct msm_dcvs_freq_entry *freq); | |
+extern int msm_dcvs_scm_register_core(uint32_t core_id, | |
+ struct msm_dcvs_core_param *param); | |
/** | |
* Set DCVS algorithm parameters | |
@@ -101,6 +88,33 @@ extern int msm_dcvs_scm_set_algo_params(uint32_t core_id, | |
struct msm_dcvs_algo_param *param); | |
/** | |
+ * Set MPDecision algorithm parameters | |
+ * | |
+ * @param: The param data structure | |
+ * 0 on success. | |
+ * -EINVAL: Invalid args. | |
+ */ | |
+extern int msm_mpd_scm_set_algo_params(struct msm_mpd_algo_param *param); | |
+ | |
+/** | |
+ * Set frequency and power characteristics for the core. | |
+ * | |
+ * @param core_id: The core identifier that will be used to interace with the | |
+ * DCVS algo. | |
+ * @param pwr_param: power params | |
+ * @param freq_entry: frequency characteristics desired | |
+ * @param coeffs: Coefficients that will describe the power curve | |
+ * | |
+ * @return int | |
+ * 0 on success. | |
+ * -EINVAL: Invalid args. | |
+ */ | |
+extern int msm_dcvs_scm_set_power_params(uint32_t core_id, | |
+ struct msm_dcvs_power_params *pwr_param, | |
+ struct msm_dcvs_freq_entry *freq_entry, | |
+ struct msm_dcvs_energy_curve_coeffs *coeffs); | |
+ | |
+/** | |
* Do an SCM call. | |
* | |
* @core_id: The core identifier. | |
@@ -126,19 +140,44 @@ extern int msm_dcvs_scm_set_algo_params(uint32_t core_id, | |
* @param1: time taken in usec to switch to the frequency | |
* @ret0: New QoS timer value for the core in usec | |
* @ret1: unused | |
- * MSM_DCVS_SCM_ENABLE_CORE | |
- * @param0: enable(1) or disable(0) core | |
- * @param1: active clock frequency of the core in KHz | |
- * @ret0: New clock frequency for the core in KHz | |
- * @ret1: unused | |
- * MSM_DCVS_SCM_RESET_CORE | |
+ * MSM_DCVS_SCM_CORE_ONLINE | |
* @param0: active clock frequency of the core in KHz | |
+ * @param1: time taken to online the core | |
+ * @ret0: unused | |
+ * @ret1: unused | |
+ * MSM_DCVS_SCM_CORE_OFFLINE | |
+ * @param0: time taken to offline the core | |
+ * @param1: unused | |
+ * @ret0: unused | |
+ * @ret1: unused | |
+ * MSM_DCVS_SCM_CORE_UNAVAILABLE | |
+ * @param0: TODO:bitmask | |
+ * @param1: unused | |
+ * @ret0: Bitmask of cores to bring online/offline. | |
+ * @ret1: Mp Decision slack time. Common to all cores. | |
+ * MSM_DCVS_SCM_DCVS_ENABLE | |
+ * @param0: 1 to enable; 0 to disable DCVS | |
* @param1: unused | |
* @ret0: New clock frequency for the core in KHz | |
* @ret1: unused | |
- * @return: | |
- * 0 on success, | |
- * SCM return values | |
+ * MSM_DCVS_SCM_MPD_ENABLE | |
+ * @param0: 1 to enable; 0 to disable MP Decision | |
+ * @param1: unused | |
+ * @ret0: unused | |
+ * @ret1: unused | |
+ * MSM_DCVS_SCM_RUNQ_UPDATE | |
+ * @param0: run q value | |
+ * @param1: unused | |
+ * @ret0: Bitmask of cores online | |
+ * @ret1: New QoS timer for MP Decision (usec) | |
+ * MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED | |
+ * @param0: unused | |
+ * @param1: unused | |
+ * @ret0: Bitmask of cores online | |
+ * @ret1: New QoS timer for MP Decision (usec) | |
+ * @return: | |
+ * 0 on success, | |
+ * SCM return values | |
*/ | |
extern int msm_dcvs_scm_event(uint32_t core_id, | |
enum msm_dcvs_scm_event event_id, | |
@@ -148,16 +187,21 @@ extern int msm_dcvs_scm_event(uint32_t core_id, | |
#else | |
static inline int msm_dcvs_scm_init(uint32_t phy, size_t bytes) | |
{ return -ENOSYS; } | |
-static inline int msm_dcvs_scm_create_group(uint32_t id) | |
-{ return -ENOSYS; } | |
static inline int msm_dcvs_scm_register_core(uint32_t core_id, | |
- uint32_t group_id, | |
struct msm_dcvs_core_param *param, | |
struct msm_dcvs_freq_entry *freq) | |
{ return -ENOSYS; } | |
static inline int msm_dcvs_scm_set_algo_params(uint32_t core_id, | |
struct msm_dcvs_algo_param *param) | |
{ return -ENOSYS; } | |
+static inline int msm_mpd_scm_set_algo_params( | |
+ struct msm_mpd_algo_param *param) | |
+{ return -ENOSYS; } | |
+static inline int msm_dcvs_set_power_params(uint32_t core_id, | |
+ struct msm_dcvs_power_params *pwr_param, | |
+ struct msm_dcvs_freq_entry *freq_entry, | |
+ struct msm_dcvs_energy_curve_coeffs *coeffs) | |
+{ return -ENOSYS; } | |
static inline int msm_dcvs_scm_event(uint32_t core_id, | |
enum msm_dcvs_scm_event event_id, | |
uint32_t param0, uint32_t param1, | |
diff --git a/arch/arm/mach-msm/include/mach/msm_memtypes.h b/arch/arm/mach-msm/include/mach/msm_memtypes.h | |
index 64c28e8..5fd3968 100644 | |
--- a/arch/arm/mach-msm/include/mach/msm_memtypes.h | |
+++ b/arch/arm/mach-msm/include/mach/msm_memtypes.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and | |
@@ -67,4 +67,6 @@ struct reserve_info { | |
extern struct reserve_info *reserve_info; | |
unsigned long __init reserve_memory_for_fmem(unsigned long, unsigned long); | |
+int __init dt_scan_for_memory_reserve(unsigned long node, const char *uname, | |
+ int depth, void *data); | |
#endif | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/acdb_commands.h b/arch/arm/mach-msm/include/mach/qdsp5/acdb_commands.h | |
index b24a3d9..188af9f 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/acdb_commands.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/acdb_commands.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/audio_acdbi.h b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdbi.h | |
index 682e4d9..5558f03 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/audio_acdbi.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdbi.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012 The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2009-2011, Code Aurora Forum. 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 and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audplaycmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audplaycmdi.h | |
index 67ee549..575a286 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audplaycmdi.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audplaycmdi.h | |
@@ -17,7 +17,7 @@ EXTERNALIZED FUNCTIONS | |
Send buffer to AUDPLAY task | |
-Copyright (c) 1992-2009, The Linux Foundation. All rights reserved. | |
+Copyright (c) 1992-2009, Code Aurora Forum. All rights reserved. | |
This software is licensed under the terms of the GNU General Public | |
License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audplaymsg.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audplaymsg.h | |
index e79554a..0bf2468 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audplaymsg.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audplaymsg.h | |
@@ -12,7 +12,7 @@ REFERENCES | |
None | |
-Copyright (c) 1992-2009, The Linux Foundation. All rights reserved. | |
+Copyright (c) 1992-2009, Code Aurora Forum. All rights reserved. | |
This software is licensed under the terms of the GNU General Public | |
License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproc.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproc.h | |
index 7153c2d..5c7c5dc 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproc.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproc.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2011-2012, Code Aurora Forum. 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 and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproccmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproccmdi.h | |
index 0fc1e46..a38d224 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproccmdi.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproccmdi.h | |
@@ -15,7 +15,7 @@ | |
* EXTERNALIZED FUNCTIONS | |
* None | |
* | |
-* Copyright (c) 1992-2009, 2012 The Linux Foundation. All rights reserved. | |
+* Copyright (c) 1992-2009, 2012 Code Aurora Forum. All rights reserved. | |
* | |
* This software is licensed under the terms of the GNU General Public | |
* License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreprocmsg.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreprocmsg.h | |
index 6a93279..d299995 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreprocmsg.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreprocmsg.h | |
@@ -15,7 +15,7 @@ | |
* EXTERNALIZED FUNCTIONS | |
* None | |
* | |
-* Copyright (c) 1992-2009, 2012 The Linux Foundation. All rights reserved. | |
+* Copyright (c) 1992-2009, 2012 Code Aurora Forum. All rights reserved. | |
* | |
* This software is licensed under the terms of the GNU General Public | |
* License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audreccmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audreccmdi.h | |
index 72f12c9..5045de0 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audreccmdi.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audreccmdi.h | |
@@ -15,7 +15,7 @@ | |
* EXTERNALIZED FUNCTIONS | |
* None | |
* | |
- * Copyright (c) 1992-2009, 2011 The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 1992-2009, 2011 Code Aurora Forum. All rights reserved. | |
* | |
* This software is licensed under the terms of the GNU General Public | |
* License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audrecmsg.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audrecmsg.h | |
index 22bdaa2..339e4f7 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audrecmsg.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audrecmsg.h | |
@@ -15,7 +15,7 @@ | |
* EXTERNALIZED FUNCTIONS | |
* None | |
* | |
- * Copyright (c) 1992-2009, 2011 The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 1992-2009, 2011 Code Aurora Forum. All rights reserved. | |
* | |
* This software is licensed under the terms of the GNU General Public | |
* License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5jpegcmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5jpegcmdi.h | |
index 40e96d7..7f25f47 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5jpegcmdi.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5jpegcmdi.h | |
@@ -15,7 +15,7 @@ REFERENCES | |
EXTERNALIZED FUNCTIONS | |
None | |
-Copyright (c) 1992-2009, The Linux Foundation. All rights reserved. | |
+Copyright (c) 1992-2009, Code Aurora Forum. All rights reserved. | |
This software is licensed under the terms of the GNU General Public | |
License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5jpegmsg.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5jpegmsg.h | |
index 9b5ce77..993af42 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5jpegmsg.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5jpegmsg.h | |
@@ -15,7 +15,7 @@ REFERENCES | |
EXTERNALIZED FUNCTIONS | |
None | |
-Copyright (c) 1992-2009, The Linux Foundation. All rights reserved. | |
+Copyright (c) 1992-2009, Code Aurora Forum. All rights reserved. | |
This software is licensed under the terms of the GNU General Public | |
License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5lpmcmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5lpmcmdi.h | |
index 3d4fe56..4ab6cbf 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5lpmcmdi.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5lpmcmdi.h | |
@@ -15,7 +15,7 @@ REFERENCES | |
EXTERNALIZED FUNCTIONS | |
None | |
-Copyright (c) 1992-2009, The Linux Foundation. All rights reserved. | |
+Copyright (c) 1992-2009, Code Aurora Forum. All rights reserved. | |
This software is licensed under the terms of the GNU General Public | |
License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5lpmmsg.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5lpmmsg.h | |
index 81f766d..68f8874 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5lpmmsg.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5lpmmsg.h | |
@@ -15,7 +15,7 @@ REFERENCES | |
EXTERNALIZED FUNCTIONS | |
None | |
-Copyright (c) 1992-2009, The Linux Foundation. All rights reserved. | |
+Copyright (c) 1992-2009, Code Aurora Forum. All rights reserved. | |
This software is licensed under the terms of the GNU General Public | |
License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5rmtcmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5rmtcmdi.h | |
index 9b9521f..7a66b68 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5rmtcmdi.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5rmtcmdi.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, Code Aurora Forum. 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 and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5rmtmsg.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5rmtmsg.h | |
index 4e7ed33..a890e76 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5rmtmsg.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5rmtmsg.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, Code Aurora Forum. 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 and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vdeccmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vdeccmdi.h | |
index 89af4aa..1064b17 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vdeccmdi.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vdeccmdi.h | |
@@ -15,7 +15,7 @@ REFERENCES | |
EXTERNALIZED FUNCTIONS | |
None | |
-Copyright (c) 1992-2009, The Linux Foundation. All rights reserved. | |
+Copyright (c) 1992-2009, Code Aurora Forum. All rights reserved. | |
This software is licensed under the terms of the GNU General Public | |
License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vdecmsg.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vdecmsg.h | |
index ccd129d..2d3ab89 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vdecmsg.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vdecmsg.h | |
@@ -15,7 +15,7 @@ REFERENCES | |
EXTERNALIZED FUNCTIONS | |
None | |
-Copyright (c) 1992-2009, The Linux Foundation. All rights reserved. | |
+Copyright (c) 1992-2009, Code Aurora Forum. All rights reserved. | |
This software is licensed under the terms of the GNU General Public | |
License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5venccmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5venccmdi.h | |
index 34e00a6..b3c018f 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5venccmdi.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5venccmdi.h | |
@@ -15,7 +15,7 @@ REFERENCES | |
EXTERNALIZED FUNCTIONS | |
None | |
-Copyright (c) 2008-2009, The Linux Foundation. All rights reserved. | |
+Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. | |
*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/ | |
/*=========================================================================== | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vfecmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vfecmdi.h | |
index 18ea21c..4c5d752 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vfecmdi.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vfecmdi.h | |
@@ -15,7 +15,7 @@ REFERENCES | |
EXTERNALIZED FUNCTIONS | |
None | |
-Copyright (c) 1992-2009, The Linux Foundation. All rights reserved. | |
+Copyright (c) 1992-2009, Code Aurora Forum. All rights reserved. | |
This software is licensed under the terms of the GNU General Public | |
License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vfemsg.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vfemsg.h | |
index 7d7f731..a628f92 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vfemsg.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5vfemsg.h | |
@@ -15,7 +15,7 @@ REFERENCES | |
EXTERNALIZED FUNCTIONS | |
None | |
-Copyright (c) 1992-2009, The Linux Foundation. All rights reserved. | |
+Copyright (c) 1992-2009, Code Aurora Forum. All rights reserved. | |
This software is licensed under the terms of the GNU General Public | |
License version 2, as published by the Free Software Foundation, and | |
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/snd_adie.h b/arch/arm/mach-msm/include/mach/qdsp5/snd_adie.h | |
index 2bad3b0..bf1714e 100644 | |
--- a/arch/arm/mach-msm/include/mach/qdsp5/snd_adie.h | |
+++ b/arch/arm/mach-msm/include/mach/qdsp5/snd_adie.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2009, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2009, Code Aurora Forum. 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 and | |
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c | |
index ee1440c..ccbd4c1 100644 | |
--- a/arch/arm/mach-msm/memory.c | |
+++ b/arch/arm/mach-msm/memory.c | |
@@ -1,7 +1,7 @@ | |
/* arch/arm/mach-msm/memory.c | |
* | |
* Copyright (C) 2007 Google, Inc. | |
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved. | |
* | |
* This software is licensed under the terms of the GNU General Public | |
* License version 2, as published by the Free Software Foundation, and | |
@@ -33,7 +33,6 @@ | |
#include <linux/completion.h> | |
#include <linux/err.h> | |
#endif | |
-#include <linux/android_pmem.h> | |
#include <mach/msm_iomap.h> | |
#include <mach/socinfo.h> | |
#include <linux/sched.h> | |
@@ -41,7 +40,6 @@ | |
/* fixme */ | |
#include <asm/tlbflush.h> | |
#include <../../mm/mm.h> | |
-#include <linux/fmem.h> | |
#if defined(CONFIG_ARCH_MSM7X27) | |
static void *strongly_ordered_page; | |
@@ -283,6 +281,7 @@ static void __init reserve_memory_for_mempools(void) | |
* out of multiple contiguous memory banks. | |
*/ | |
mt->start = mb->start + (size - mt->size); | |
+ | |
ret = memblock_remove(mt->start, mt->size); | |
BUG_ON(ret); | |
break; | |
@@ -365,16 +364,6 @@ void store_ttbr0(void) | |
: "=r" (msm_ttbr0)); | |
} | |
-int request_fmem_c_region(void *unused) | |
-{ | |
- return fmem_set_state(FMEM_C_STATE); | |
-} | |
- | |
-int release_fmem_c_region(void *unused) | |
-{ | |
- return fmem_set_state(FMEM_T_STATE); | |
-} | |
- | |
unsigned long get_ddr_size(void) | |
{ | |
unsigned int i; | |
diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c | |
index a2550cf..ed34a47 100644 | |
--- a/arch/arm/mach-msm/msm_dcvs.c | |
+++ b/arch/arm/mach-msm/msm_dcvs.c | |
@@ -14,7 +14,6 @@ | |
#include <linux/kernel.h> | |
#include <linux/init.h> | |
#include <linux/module.h> | |
-#include <linux/mutex.h> | |
#include <linux/kthread.h> | |
#include <linux/kobject.h> | |
#include <linux/ktime.h> | |
@@ -23,167 +22,327 @@ | |
#include <linux/spinlock.h> | |
#include <linux/stringify.h> | |
#include <linux/debugfs.h> | |
+#include <linux/msm_tsens.h> | |
+#include <linux/platform_device.h> | |
#include <asm/atomic.h> | |
#include <asm/page.h> | |
#include <mach/msm_dcvs.h> | |
+#include <trace/events/mpdcvs_trace.h> | |
#define CORE_HANDLE_OFFSET (0xA0) | |
#define __err(f, ...) pr_err("MSM_DCVS: %s: " f, __func__, __VA_ARGS__) | |
#define __info(f, ...) pr_info("MSM_DCVS: %s: " f, __func__, __VA_ARGS__) | |
#define MAX_PENDING (5) | |
-enum { | |
- MSM_DCVS_DEBUG_NOTIFIER = BIT(0), | |
- MSM_DCVS_DEBUG_IDLE_PULSE = BIT(1), | |
- MSM_DCVS_DEBUG_FREQ_CHANGE = BIT(2), | |
-}; | |
- | |
struct core_attribs { | |
- struct kobj_attribute idle_enabled; | |
- struct kobj_attribute freq_change_enabled; | |
- struct kobj_attribute actual_freq; | |
struct kobj_attribute freq_change_us; | |
- struct kobj_attribute max_time_us; | |
- | |
- struct kobj_attribute slack_time_us; | |
- struct kobj_attribute scale_slack_time; | |
- struct kobj_attribute scale_slack_time_pct; | |
struct kobj_attribute disable_pc_threshold; | |
- struct kobj_attribute em_window_size; | |
+ struct kobj_attribute em_win_size_min_us; | |
+ struct kobj_attribute em_win_size_max_us; | |
struct kobj_attribute em_max_util_pct; | |
- struct kobj_attribute ss_window_size; | |
+ struct kobj_attribute group_id; | |
+ struct kobj_attribute max_freq_chg_time_us; | |
+ struct kobj_attribute slack_mode_dynamic; | |
+ struct kobj_attribute slack_time_min_us; | |
+ struct kobj_attribute slack_time_max_us; | |
+ struct kobj_attribute slack_weight_thresh_pct; | |
+ struct kobj_attribute ss_no_corr_below_freq; | |
+ struct kobj_attribute ss_win_size_min_us; | |
+ struct kobj_attribute ss_win_size_max_us; | |
struct kobj_attribute ss_util_pct; | |
- struct kobj_attribute ss_iobusy_conv; | |
+ | |
+ struct kobj_attribute active_coeff_a; | |
+ struct kobj_attribute active_coeff_b; | |
+ struct kobj_attribute active_coeff_c; | |
+ struct kobj_attribute leakage_coeff_a; | |
+ struct kobj_attribute leakage_coeff_b; | |
+ struct kobj_attribute leakage_coeff_c; | |
+ struct kobj_attribute leakage_coeff_d; | |
+ | |
+ struct kobj_attribute thermal_poll_ms; | |
+ | |
+ struct kobj_attribute freq_tbl; | |
struct attribute_group attrib_group; | |
}; | |
+enum pending_freq_state { | |
+ /* | |
+ * used by the thread to check if pending_freq was updated while it was | |
+ * setting previous frequency - this is written to and used by the | |
+ * freq updating thread | |
+ */ | |
+ NO_OUTSTANDING_FREQ_CHANGE = 0, | |
+ | |
+ /* | |
+ * This request is set to indicate that the governor is stopped and no | |
+ * more frequency change requests are accepted untill it starts again. | |
+ * This is checked/used by the threads that want to change the freq | |
+ */ | |
+ STOP_FREQ_CHANGE = -1, | |
+ | |
+ /* | |
+ * Any other +ve value means that a freq change was requested and the | |
+ * thread has not gotten around to update it | |
+ * | |
+ * Any other -ve value means that this is the last freq change i.e. a | |
+ * freq change was requested but the thread has not run yet and | |
+ * meanwhile the governor was stopped. | |
+ */ | |
+}; | |
+ | |
struct dcvs_core { | |
+ spinlock_t idle_state_change_lock; | |
+ /* 0 when not idle (busy) 1 when idle and -1 when governor starts and | |
+ * we dont know whether the next call is going to be idle enter or exit | |
+ */ | |
+ int idle_entered; | |
+ | |
+ enum msm_dcvs_core_type type; | |
+ /* this is the number in each type for example cpu 0,1,2 and gpu 0,1 */ | |
+ int type_core_num; | |
char core_name[CORE_NAME_MAX]; | |
- uint32_t new_freq[MAX_PENDING]; | |
uint32_t actual_freq; | |
uint32_t freq_change_us; | |
uint32_t max_time_us; /* core param */ | |
struct msm_dcvs_algo_param algo_param; | |
- struct msm_dcvs_idle *idle_driver; | |
- struct msm_dcvs_freq *freq_driver; | |
+ struct msm_dcvs_energy_curve_coeffs coeffs; | |
/* private */ | |
- int64_t time_start; | |
- struct mutex lock; | |
- spinlock_t cpu_lock; | |
+ ktime_t time_start; | |
struct task_struct *task; | |
struct core_attribs attrib; | |
- uint32_t handle; | |
- uint32_t group_id; | |
- uint32_t freq_pending; | |
- struct hrtimer timer; | |
- int32_t timer_disabled; | |
- /* track if kthread for change_freq is active */ | |
- int32_t change_freq_activated; | |
+ uint32_t dcvs_core_id; | |
+ struct msm_dcvs_core_info *info; | |
+ int sensor; | |
+ wait_queue_head_t wait_q; | |
+ | |
+ int (*set_frequency)(int type_core_num, unsigned int freq); | |
+ unsigned int (*get_frequency)(int type_core_num); | |
+ int (*idle_enable)(int type_core_num, | |
+ enum msm_core_control_event event); | |
+ int (*set_floor_frequency)(int type_core_num, unsigned int freq); | |
+ | |
+ spinlock_t pending_freq_lock; | |
+ int pending_freq; | |
+ | |
+ struct hrtimer slack_timer; | |
+ struct delayed_work temperature_work; | |
}; | |
-static int msm_dcvs_debug; | |
static int msm_dcvs_enabled = 1; | |
module_param_named(enable, msm_dcvs_enabled, int, S_IRUGO | S_IWUSR | S_IWGRP); | |
-static struct dentry *debugfs_base; | |
+static struct dentry *debugfs_base; | |
static struct dcvs_core core_list[CORES_MAX]; | |
-static DEFINE_MUTEX(core_list_lock); | |
static struct kobject *cores_kobj; | |
-static struct dcvs_core *core_handles[CORES_MAX]; | |
-/* Change core frequency, called with core mutex locked */ | |
+#define DCVS_MAX_NUM_FREQS 15 | |
+static struct msm_dcvs_freq_entry cpu_freq_tbl[DCVS_MAX_NUM_FREQS]; | |
+static unsigned num_cpu_freqs; | |
+static struct msm_dcvs_platform_data *dcvs_pdata; | |
+ | |
+static void force_stop_slack_timer(struct dcvs_core *core) | |
+{ | |
+ unsigned long flags; | |
+ | |
+ spin_lock_irqsave(&core->idle_state_change_lock, flags); | |
+ hrtimer_cancel(&core->slack_timer); | |
+ spin_unlock_irqrestore(&core->idle_state_change_lock, flags); | |
+} | |
+ | |
+static void force_start_slack_timer(struct dcvs_core *core, int slack_us) | |
+{ | |
+ unsigned long flags; | |
+ int ret; | |
+ | |
+ spin_lock_irqsave(&core->idle_state_change_lock, flags); | |
+ | |
+ /* | |
+ * only start the timer if governor is not stopped | |
+ */ | |
+ if (slack_us != 0) { | |
+ ret = hrtimer_start(&core->slack_timer, | |
+ ktime_set(0, slack_us * 1000), | |
+ HRTIMER_MODE_REL_PINNED); | |
+ if (ret) { | |
+ pr_err("%s Failed to start timer ret = %d\n", | |
+ core->core_name, ret); | |
+ } | |
+ } | |
+ | |
+ spin_unlock_irqrestore(&core->idle_state_change_lock, flags); | |
+} | |
+ | |
+static void stop_slack_timer(struct dcvs_core *core) | |
+{ | |
+ unsigned long flags; | |
+ | |
+ spin_lock_irqsave(&core->idle_state_change_lock, flags); | |
+ /* err only for cpu type's GPU's can do idle exit consecutively */ | |
+ if (core->idle_entered == 1 && !(core->dcvs_core_id >= GPU_OFFSET)) | |
+ __err("%s trying to reenter idle", core->core_name); | |
+ core->idle_entered = 1; | |
+ hrtimer_cancel(&core->slack_timer); | |
+ core->idle_entered = 1; | |
+ spin_unlock_irqrestore(&core->idle_state_change_lock, flags); | |
+} | |
+ | |
+static void start_slack_timer(struct dcvs_core *core, int slack_us) | |
+{ | |
+ unsigned long flags1, flags2; | |
+ int ret; | |
+ | |
+ spin_lock_irqsave(&core->idle_state_change_lock, flags2); | |
+ | |
+ spin_lock_irqsave(&core->pending_freq_lock, flags1); | |
+ | |
+ /* err only for cpu type's GPU's can do idle enter consecutively */ | |
+ if (core->idle_entered == 0 && !(core->dcvs_core_id >= GPU_OFFSET)) | |
+ __err("%s trying to reexit idle", core->core_name); | |
+ core->idle_entered = 0; | |
+ /* | |
+ * only start the timer if governor is not stopped | |
+ */ | |
+ if (slack_us != 0 | |
+ && !(core->pending_freq < NO_OUTSTANDING_FREQ_CHANGE)) { | |
+ ret = hrtimer_start(&core->slack_timer, | |
+ ktime_set(0, slack_us * 1000), | |
+ HRTIMER_MODE_REL_PINNED); | |
+ if (ret) { | |
+ pr_err("%s Failed to start timer ret = %d\n", | |
+ core->core_name, ret); | |
+ } | |
+ } | |
+ spin_unlock_irqrestore(&core->pending_freq_lock, flags1); | |
+ | |
+ spin_unlock_irqrestore(&core->idle_state_change_lock, flags2); | |
+} | |
+ | |
+static void restart_slack_timer(struct dcvs_core *core, int slack_us) | |
+{ | |
+ unsigned long flags1, flags2; | |
+ int ret; | |
+ | |
+ spin_lock_irqsave(&core->idle_state_change_lock, flags2); | |
+ | |
+ hrtimer_cancel(&core->slack_timer); | |
+ | |
+ spin_lock_irqsave(&core->pending_freq_lock, flags1); | |
+ | |
+ /* | |
+ * only start the timer if idle is not entered | |
+ * and governor is not stopped | |
+ */ | |
+ if (slack_us != 0 && (core->idle_entered != 1) | |
+ && !(core->pending_freq < NO_OUTSTANDING_FREQ_CHANGE)) { | |
+ ret = hrtimer_start(&core->slack_timer, | |
+ ktime_set(0, slack_us * 1000), | |
+ HRTIMER_MODE_REL_PINNED); | |
+ if (ret) { | |
+ pr_err("%s Failed to start timer ret = %d\n", | |
+ core->core_name, ret); | |
+ } | |
+ } | |
+ spin_unlock_irqrestore(&core->pending_freq_lock, flags1); | |
+ spin_unlock_irqrestore(&core->idle_state_change_lock, flags2); | |
+} | |
+ | |
+static void apply_gpu_floor(int cpu_freq) | |
+{ | |
+ int i; | |
+ int gpu_floor_freq = 0; | |
+ struct dcvs_core *gpu; | |
+ | |
+ if (!dcvs_pdata) | |
+ return; | |
+ | |
+ for (i = 0; i < dcvs_pdata->num_sync_rules; i++) | |
+ if (cpu_freq > dcvs_pdata->sync_rules[i].cpu_khz) { | |
+ gpu_floor_freq = | |
+ dcvs_pdata->sync_rules[i].gpu_floor_khz; | |
+ break; | |
+ } | |
+ | |
+ if (!gpu_floor_freq) | |
+ return; | |
+ | |
+ for (i = GPU_OFFSET; i < CORES_MAX; i++) { | |
+ gpu = &core_list[i]; | |
+ if (gpu->dcvs_core_id == -1) | |
+ continue; | |
+ if (gpu->set_floor_frequency) | |
+ gpu->set_floor_frequency(gpu->type_core_num, | |
+ gpu_floor_freq); | |
+ } | |
+} | |
+ | |
static int __msm_dcvs_change_freq(struct dcvs_core *core) | |
{ | |
int ret = 0; | |
unsigned long flags = 0; | |
- unsigned int requested_freq = 0; | |
- unsigned int prev_freq = 0; | |
- int64_t time_start = 0; | |
- int64_t time_end = 0; | |
+ int requested_freq = 0; | |
+ ktime_t time_start; | |
uint32_t slack_us = 0; | |
uint32_t ret1 = 0; | |
- if (!core->freq_driver || !core->freq_driver->set_frequency) { | |
- /* Core may have unregistered or hotplugged */ | |
- return -ENODEV; | |
- } | |
+ spin_lock_irqsave(&core->pending_freq_lock, flags); | |
repeat: | |
- spin_lock_irqsave(&core->cpu_lock, flags); | |
- if (unlikely(!core->freq_pending)) { | |
- spin_unlock_irqrestore(&core->cpu_lock, flags); | |
- return ret; | |
- } | |
- requested_freq = core->new_freq[core->freq_pending - 1]; | |
- if (unlikely(core->freq_pending > 1) && | |
- (msm_dcvs_debug & MSM_DCVS_DEBUG_FREQ_CHANGE)) { | |
- int i; | |
- for (i = 0; i < core->freq_pending - 1; i++) { | |
- __info("Core %s missing freq %u\n", | |
- core->core_name, core->new_freq[i]); | |
- } | |
- } | |
+ BUG_ON(!core->pending_freq); | |
+ if (core->pending_freq == STOP_FREQ_CHANGE) | |
+ BUG(); | |
+ | |
+ requested_freq = core->pending_freq; | |
time_start = core->time_start; | |
- core->time_start = 0; | |
- core->freq_pending = 0; | |
- /** | |
- * Cancel the timers, we dont want the timer firing as we are | |
- * changing the clock rate. Dont let idle_exit and others setup | |
- * timers as well. | |
- */ | |
- hrtimer_cancel(&core->timer); | |
- core->timer_disabled = 1; | |
- spin_unlock_irqrestore(&core->cpu_lock, flags); | |
+ core->time_start = ns_to_ktime(0); | |
+ | |
+ if (requested_freq < 0) { | |
+ requested_freq = -1 * requested_freq; | |
+ core->pending_freq = STOP_FREQ_CHANGE; | |
+ } else { | |
+ core->pending_freq = NO_OUTSTANDING_FREQ_CHANGE; | |
+ } | |
if (requested_freq == core->actual_freq) | |
- return ret; | |
+ goto out; | |
+ | |
+ spin_unlock_irqrestore(&core->pending_freq_lock, flags); | |
+ | |
+ if (core->type == MSM_DCVS_CORE_TYPE_CPU && | |
+ core->type_core_num == 0) | |
+ apply_gpu_floor(requested_freq); | |
/** | |
* Call the frequency sink driver to change the frequency | |
* We will need to get back the actual frequency in KHz and | |
* the record the time taken to change it. | |
*/ | |
- ret = core->freq_driver->set_frequency(core->freq_driver, | |
- requested_freq); | |
- if (ret <= 0) { | |
+ ret = core->set_frequency(core->type_core_num, requested_freq); | |
+ if (ret <= 0) | |
__err("Core %s failed to set freq %u\n", | |
core->core_name, requested_freq); | |
/* continue to call TZ to get updated slack timer */ | |
- } else { | |
- prev_freq = core->actual_freq; | |
+ else | |
core->actual_freq = ret; | |
- } | |
- time_end = ktime_to_ns(ktime_get()); | |
- if (msm_dcvs_debug & MSM_DCVS_DEBUG_FREQ_CHANGE) | |
- __info("Core %s Time end %llu Time start: %llu\n", | |
- core->core_name, time_end, time_start); | |
- time_end -= time_start; | |
- do_div(time_end, NSEC_PER_USEC); | |
- core->freq_change_us = (uint32_t)time_end; | |
+ core->freq_change_us = (uint32_t)ktime_to_us( | |
+ ktime_sub(ktime_get(), time_start)); | |
/** | |
* Disable low power modes if the actual frequency is > | |
* disable_pc_threshold. | |
*/ | |
- if (core->actual_freq > | |
- core->algo_param.disable_pc_threshold) { | |
- core->idle_driver->enable(core->idle_driver, | |
+ if (core->actual_freq > core->algo_param.disable_pc_threshold) { | |
+ core->idle_enable(core->type_core_num, | |
MSM_DCVS_DISABLE_HIGH_LATENCY_MODES); | |
- if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE) | |
- __info("Disabling LPM for %s\n", core->core_name); | |
- } else if (core->actual_freq <= | |
- core->algo_param.disable_pc_threshold) { | |
- core->idle_driver->enable(core->idle_driver, | |
+ } else if (core->actual_freq <= core->algo_param.disable_pc_threshold) { | |
+ core->idle_enable(core->type_core_num, | |
MSM_DCVS_ENABLE_HIGH_LATENCY_MODES); | |
- if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE) | |
- __info("Enabling LPM for %s\n", core->core_name); | |
} | |
/** | |
@@ -191,108 +350,162 @@ repeat: | |
* to this frequency and that will get us the new slack | |
* timer | |
*/ | |
- ret = msm_dcvs_scm_event(core->handle, MSM_DCVS_SCM_CLOCK_FREQ_UPDATE, | |
- core->actual_freq, (uint32_t)time_end, &slack_us, &ret1); | |
- if (!ret) { | |
- /* Reset the slack timer */ | |
- if (slack_us) { | |
- core->timer_disabled = 0; | |
- ret = hrtimer_start(&core->timer, | |
- ktime_set(0, slack_us * 1000), | |
- HRTIMER_MODE_REL_PINNED); | |
- if (ret) | |
- __err("Failed to register timer for core %s\n", | |
- core->core_name); | |
- } | |
- } else { | |
- __err("Error sending core (%s) freq change (%u)\n", | |
- core->core_name, core->actual_freq); | |
+ ret = msm_dcvs_scm_event(core->dcvs_core_id, | |
+ MSM_DCVS_SCM_CLOCK_FREQ_UPDATE, | |
+ core->actual_freq, core->freq_change_us, | |
+ &slack_us, &ret1); | |
+ if (ret) { | |
+ __err("Error sending core (%s) dcvs_core_id = %d freq change (%u) reqfreq = %d slack_us=%d ret = %d\n", | |
+ core->core_name, core->dcvs_core_id, | |
+ core->actual_freq, requested_freq, | |
+ slack_us, ret); | |
} | |
- if (msm_dcvs_debug & MSM_DCVS_DEBUG_FREQ_CHANGE) | |
- __info("Freq %u requested for core %s (actual %u prev %u) " | |
- "change time %u us slack time %u us\n", | |
- requested_freq, core->core_name, | |
- core->actual_freq, prev_freq, | |
- core->freq_change_us, slack_us); | |
+ /* TODO confirm that we get a valid freq from SM even when the above | |
+ * FREQ_UPDATE fails | |
+ */ | |
+ restart_slack_timer(core, slack_us); | |
+ spin_lock_irqsave(&core->pending_freq_lock, flags); | |
/** | |
* By the time we are done with freq changes, we could be asked to | |
* change again. Check before exiting. | |
*/ | |
- if (core->freq_pending) | |
+ if (core->pending_freq != NO_OUTSTANDING_FREQ_CHANGE | |
+ && core->pending_freq != STOP_FREQ_CHANGE) { | |
goto repeat; | |
+ } | |
+ | |
+out: /* should always be jumped to with the spin_lock held */ | |
+ spin_unlock_irqrestore(&core->pending_freq_lock, flags); | |
- core->change_freq_activated = 0; | |
return ret; | |
} | |
+static void msm_dcvs_report_temp_work(struct work_struct *work) | |
+{ | |
+ struct dcvs_core *core = container_of(work, | |
+ struct dcvs_core, | |
+ temperature_work.work); | |
+ struct msm_dcvs_core_info *info = core->info; | |
+ struct tsens_device tsens_dev; | |
+ int ret; | |
+ unsigned long temp = 0; | |
+ int interval_ms; | |
+ | |
+ tsens_dev.sensor_num = core->sensor; | |
+ ret = tsens_get_temp(&tsens_dev, &temp); | |
+ if (!temp) { | |
+ tsens_dev.sensor_num = 0; | |
+ ret = tsens_get_temp(&tsens_dev, &temp); | |
+ if (!temp) | |
+ goto out; | |
+ } | |
+ | |
+ if (temp == info->power_param.current_temp) | |
+ goto out; | |
+ info->power_param.current_temp = temp; | |
+ | |
+ ret = msm_dcvs_scm_set_power_params(core->dcvs_core_id, | |
+ &info->power_param, | |
+ &info->freq_tbl[0], &core->coeffs); | |
+out: | |
+ if (info->thermal_poll_ms == 0) | |
+ interval_ms = 60000; | |
+ else if (info->thermal_poll_ms < 1000) | |
+ interval_ms = 1000; | |
+ else | |
+ interval_ms = info->thermal_poll_ms; | |
+ | |
+ schedule_delayed_work(&core->temperature_work, | |
+ msecs_to_jiffies(interval_ms)); | |
+} | |
+ | |
static int msm_dcvs_do_freq(void *data) | |
{ | |
struct dcvs_core *core = (struct dcvs_core *)data; | |
- static struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1}; | |
- | |
- sched_setscheduler(current, SCHED_FIFO, ¶m); | |
- set_current_state(TASK_UNINTERRUPTIBLE); | |
while (!kthread_should_stop()) { | |
- mutex_lock(&core->lock); | |
- __msm_dcvs_change_freq(core); | |
- mutex_unlock(&core->lock); | |
- | |
- schedule(); | |
+ wait_event(core->wait_q, !(core->pending_freq == 0 || | |
+ core->pending_freq == -1) || | |
+ kthread_should_stop()); | |
if (kthread_should_stop()) | |
break; | |
- set_current_state(TASK_UNINTERRUPTIBLE); | |
+ __msm_dcvs_change_freq(core); | |
} | |
- __set_current_state(TASK_RUNNING); | |
- | |
return 0; | |
} | |
+/* freq_pending_lock should be held */ | |
+static void request_freq_change(struct dcvs_core *core, int new_freq) | |
+{ | |
+ if (new_freq == NO_OUTSTANDING_FREQ_CHANGE) { | |
+ if (core->pending_freq != STOP_FREQ_CHANGE) { | |
+ __err("%s gov started with earlier pending freq %d\n", | |
+ core->core_name, core->pending_freq); | |
+ } | |
+ core->pending_freq = NO_OUTSTANDING_FREQ_CHANGE; | |
+ return; | |
+ } | |
+ | |
+ if (new_freq == STOP_FREQ_CHANGE) { | |
+ if (core->pending_freq == NO_OUTSTANDING_FREQ_CHANGE) | |
+ core->pending_freq = STOP_FREQ_CHANGE; | |
+ else if (core->pending_freq > 0) | |
+ core->pending_freq = -1 * core->pending_freq; | |
+ return; | |
+ } | |
+ | |
+ if (core->pending_freq < 0) { | |
+ /* a value less than 0 means that the governor has stopped | |
+ * and no more freq changes should be requested | |
+ */ | |
+ return; | |
+ } | |
+ | |
+ if (core->actual_freq != new_freq && core->pending_freq != new_freq) { | |
+ core->pending_freq = new_freq; | |
+ core->time_start = ktime_get(); | |
+ wake_up(&core->wait_q); | |
+ } | |
+} | |
+ | |
static int msm_dcvs_update_freq(struct dcvs_core *core, | |
enum msm_dcvs_scm_event event, uint32_t param0, | |
- uint32_t *ret1, int *freq_changed) | |
+ uint32_t *ret1) | |
{ | |
int ret = 0; | |
unsigned long flags = 0; | |
- uint32_t new_freq = 0; | |
+ uint32_t new_freq = -EINVAL; | |
+ | |
+ spin_lock_irqsave(&core->pending_freq_lock, flags); | |
- spin_lock_irqsave(&core->cpu_lock, flags); | |
- ret = msm_dcvs_scm_event(core->handle, event, param0, | |
+ ret = msm_dcvs_scm_event(core->dcvs_core_id, event, param0, | |
core->actual_freq, &new_freq, ret1); | |
if (ret) { | |
- __err("Error (%d) sending SCM event %d for core %s\n", | |
+ if (ret == -13) | |
+ ret = 0; | |
+ else | |
+ __err("Error (%d) sending SCM event %d for core %s\n", | |
ret, event, core->core_name); | |
- goto freq_done; | |
- } | |
- | |
- if ((core->actual_freq != new_freq) && | |
- (core->new_freq[core->freq_pending] != new_freq)) { | |
- if (core->freq_pending >= MAX_PENDING - 1) | |
- core->freq_pending = MAX_PENDING - 1; | |
- core->new_freq[core->freq_pending++] = new_freq; | |
- core->time_start = ktime_to_ns(ktime_get()); | |
- | |
- /* Schedule the frequency change */ | |
- if (!core->task) | |
- __err("Uninitialized task for core %s\n", | |
- core->core_name); | |
- else { | |
- if (freq_changed) | |
- *freq_changed = 1; | |
- core->change_freq_activated = 1; | |
- wake_up_process(core->task); | |
- } | |
- } else { | |
- if (freq_changed) | |
- *freq_changed = 0; | |
+ goto out; | |
} | |
-freq_done: | |
- spin_unlock_irqrestore(&core->cpu_lock, flags); | |
+ | |
+ if (new_freq == 0) { | |
+ /* | |
+ * sometimes TZ gives us a 0 freq back, | |
+ * do not queue up a request | |
+ */ | |
+ goto out; | |
+ } | |
+ | |
+ request_freq_change(core, new_freq); | |
+ | |
+out: | |
+ spin_unlock_irqrestore(&core->pending_freq_lock, flags); | |
return ret; | |
} | |
@@ -300,19 +513,17 @@ freq_done: | |
static enum hrtimer_restart msm_dcvs_core_slack_timer(struct hrtimer *timer) | |
{ | |
int ret = 0; | |
- struct dcvs_core *core = container_of(timer, struct dcvs_core, timer); | |
+ struct dcvs_core *core = container_of(timer, | |
+ struct dcvs_core, slack_timer); | |
uint32_t ret1; | |
- uint32_t ret2; | |
- | |
- if (msm_dcvs_debug & MSM_DCVS_DEBUG_FREQ_CHANGE) | |
- __info("Slack timer fired for core %s\n", core->core_name); | |
+ trace_printk("dcvs: Slack timer fired for core=%s\n", core->core_name); | |
/** | |
* Timer expired, notify TZ | |
* Dont care about the third arg. | |
*/ | |
ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_QOS_TIMER_EXPIRED, 0, | |
- &ret1, &ret2); | |
+ &ret1); | |
if (ret) | |
__err("Timer expired for core %s but failed to notify.\n", | |
core->core_name); | |
@@ -333,6 +544,28 @@ static ssize_t msm_dcvs_attr_##_name##_show(struct kobject *kobj, \ | |
return snprintf(buf, PAGE_SIZE, "%d\n", v); \ | |
} | |
+#define DCVS_PARAM_STORE(_name) \ | |
+static ssize_t msm_dcvs_attr_##_name##_show(struct kobject *kobj,\ | |
+ struct kobj_attribute *attr, char *buf) \ | |
+{ \ | |
+ struct dcvs_core *core = CORE_FROM_ATTRIBS(attr, _name); \ | |
+ return snprintf(buf, PAGE_SIZE, "%d\n", core->info->_name); \ | |
+} \ | |
+static ssize_t msm_dcvs_attr_##_name##_store(struct kobject *kobj, \ | |
+ struct kobj_attribute *attr, const char *buf, size_t count) \ | |
+{ \ | |
+ int ret = 0; \ | |
+ uint32_t val = 0; \ | |
+ struct dcvs_core *core = CORE_FROM_ATTRIBS(attr, _name); \ | |
+ ret = kstrtouint(buf, 10, &val); \ | |
+ if (ret) { \ | |
+ __err("Invalid input %s for %s\n", buf, __stringify(_name));\ | |
+ } else { \ | |
+ core->info->_name = val; \ | |
+ } \ | |
+ return count; \ | |
+} | |
+ | |
#define DCVS_ALGO_PARAM(_name) \ | |
static ssize_t msm_dcvs_attr_##_name##_show(struct kobject *kobj,\ | |
struct kobj_attribute *attr, char *buf) \ | |
@@ -346,14 +579,13 @@ static ssize_t msm_dcvs_attr_##_name##_store(struct kobject *kobj, \ | |
int ret = 0; \ | |
uint32_t val = 0; \ | |
struct dcvs_core *core = CORE_FROM_ATTRIBS(attr, _name); \ | |
- mutex_lock(&core->lock); \ | |
ret = kstrtouint(buf, 10, &val); \ | |
if (ret) { \ | |
__err("Invalid input %s for %s\n", buf, __stringify(_name));\ | |
} else { \ | |
uint32_t old_val = core->algo_param._name; \ | |
core->algo_param._name = val; \ | |
- ret = msm_dcvs_scm_set_algo_params(core->handle, \ | |
+ ret = msm_dcvs_scm_set_algo_params(core->dcvs_core_id, \ | |
&core->algo_param); \ | |
if (ret) { \ | |
core->algo_param._name = old_val; \ | |
@@ -361,7 +593,37 @@ static ssize_t msm_dcvs_attr_##_name##_store(struct kobject *kobj, \ | |
ret, val, __stringify(_name)); \ | |
} \ | |
} \ | |
- mutex_unlock(&core->lock); \ | |
+ return count; \ | |
+} | |
+ | |
+#define DCVS_ENERGY_PARAM(_name) \ | |
+static ssize_t msm_dcvs_attr_##_name##_show(struct kobject *kobj,\ | |
+ struct kobj_attribute *attr, char *buf) \ | |
+{ \ | |
+ struct dcvs_core *core = CORE_FROM_ATTRIBS(attr, _name); \ | |
+ return snprintf(buf, PAGE_SIZE, "%d\n", core->coeffs._name); \ | |
+} \ | |
+static ssize_t msm_dcvs_attr_##_name##_store(struct kobject *kobj, \ | |
+ struct kobj_attribute *attr, const char *buf, size_t count) \ | |
+{ \ | |
+ int ret = 0; \ | |
+ int32_t val = 0; \ | |
+ struct dcvs_core *core = CORE_FROM_ATTRIBS(attr, _name); \ | |
+ ret = kstrtoint(buf, 10, &val); \ | |
+ if (ret) { \ | |
+ __err("Invalid input %s for %s\n", buf, __stringify(_name));\ | |
+ } else { \ | |
+ int32_t old_val = core->coeffs._name; \ | |
+ core->coeffs._name = val; \ | |
+ ret = msm_dcvs_scm_set_power_params(core->dcvs_core_id, \ | |
+ &core->info->power_param, &core->info->freq_tbl[0], \ | |
+ &core->coeffs); \ | |
+ if (ret) { \ | |
+ core->coeffs._name = old_val; \ | |
+ __err("Error(%d) in setting %d for coeffs param %s\n",\ | |
+ ret, val, __stringify(_name)); \ | |
+ } \ | |
+ } \ | |
return count; \ | |
} | |
@@ -383,27 +645,110 @@ static ssize_t msm_dcvs_attr_##_name##_store(struct kobject *kobj, \ | |
* Function declarations for different attributes. | |
* Gets used when setting the attribute show and store parameters. | |
*/ | |
-DCVS_PARAM_SHOW(idle_enabled, (core->idle_driver != NULL)) | |
-DCVS_PARAM_SHOW(freq_change_enabled, (core->freq_driver != NULL)) | |
-DCVS_PARAM_SHOW(actual_freq, (core->actual_freq)) | |
DCVS_PARAM_SHOW(freq_change_us, (core->freq_change_us)) | |
-DCVS_PARAM_SHOW(max_time_us, (core->max_time_us)) | |
-DCVS_ALGO_PARAM(slack_time_us) | |
-DCVS_ALGO_PARAM(scale_slack_time) | |
-DCVS_ALGO_PARAM(scale_slack_time_pct) | |
DCVS_ALGO_PARAM(disable_pc_threshold) | |
-DCVS_ALGO_PARAM(em_window_size) | |
+DCVS_ALGO_PARAM(em_win_size_min_us) | |
+DCVS_ALGO_PARAM(em_win_size_max_us) | |
DCVS_ALGO_PARAM(em_max_util_pct) | |
-DCVS_ALGO_PARAM(ss_window_size) | |
+DCVS_ALGO_PARAM(group_id) | |
+DCVS_ALGO_PARAM(max_freq_chg_time_us) | |
+DCVS_ALGO_PARAM(slack_mode_dynamic) | |
+DCVS_ALGO_PARAM(slack_time_min_us) | |
+DCVS_ALGO_PARAM(slack_time_max_us) | |
+DCVS_ALGO_PARAM(slack_weight_thresh_pct) | |
+DCVS_ALGO_PARAM(ss_no_corr_below_freq) | |
+DCVS_ALGO_PARAM(ss_win_size_min_us) | |
+DCVS_ALGO_PARAM(ss_win_size_max_us) | |
DCVS_ALGO_PARAM(ss_util_pct) | |
-DCVS_ALGO_PARAM(ss_iobusy_conv) | |
+ | |
+DCVS_ENERGY_PARAM(active_coeff_a) | |
+DCVS_ENERGY_PARAM(active_coeff_b) | |
+DCVS_ENERGY_PARAM(active_coeff_c) | |
+DCVS_ENERGY_PARAM(leakage_coeff_a) | |
+DCVS_ENERGY_PARAM(leakage_coeff_b) | |
+DCVS_ENERGY_PARAM(leakage_coeff_c) | |
+DCVS_ENERGY_PARAM(leakage_coeff_d) | |
+ | |
+DCVS_PARAM_STORE(thermal_poll_ms) | |
+ | |
+static ssize_t msm_dcvs_attr_freq_tbl_show(struct kobject *kobj, | |
+ struct kobj_attribute *attr, | |
+ char *buf) | |
+{ | |
+ struct msm_dcvs_freq_entry *freq_tbl; | |
+ char *buf_idx = buf; | |
+ int i, len; | |
+ struct dcvs_core *core = CORE_FROM_ATTRIBS(attr, freq_tbl); | |
+ | |
+ freq_tbl = core->info->freq_tbl; | |
+ *buf_idx = '\0'; | |
+ | |
+ /* limit the number of frequencies we will print into | |
+ * the PAGE_SIZE sysfs show buffer. */ | |
+ if (core->info->power_param.num_freq > 64) | |
+ return 0; | |
+ | |
+ for (i = 0; i < core->info->power_param.num_freq; i++) { | |
+ if (freq_tbl[i].is_trans_level) { | |
+ len = snprintf(buf_idx, 10, "%7d ", freq_tbl[i].freq); | |
+ /* buf_idx always points at terminating null */ | |
+ buf_idx += len; | |
+ } | |
+ } | |
+ /* overwrite final trailing space with newline */ | |
+ if (buf_idx > buf) | |
+ *(buf_idx - 1) = '\n'; | |
+ | |
+ return buf_idx - buf; | |
+} | |
+ | |
+static ssize_t msm_dcvs_attr_freq_tbl_store(struct kobject *kobj, | |
+ struct kobj_attribute *attr, | |
+ const char *buf, | |
+ size_t count) | |
+{ | |
+ struct msm_dcvs_freq_entry *freq_tbl; | |
+ uint32_t freq; | |
+ int i, ret; | |
+ struct dcvs_core *core = CORE_FROM_ATTRIBS(attr, freq_tbl); | |
+ | |
+ freq_tbl = core->info->freq_tbl; | |
+ | |
+ ret = kstrtouint(buf, 10, &freq); | |
+ if (ret) { | |
+ __err("Invalid input %s for freq_tbl\n", buf); | |
+ return count; | |
+ } | |
+ | |
+ for (i = 0; i < core->info->power_param.num_freq; i++) | |
+ if (freq_tbl[i].freq == freq) { | |
+ freq_tbl[i].is_trans_level ^= 1; | |
+ break; | |
+ } | |
+ | |
+ if (i >= core->info->power_param.num_freq) { | |
+ __err("Invalid frequency for freq_tbl: %d\n", freq); | |
+ return count; | |
+ } | |
+ | |
+ ret = msm_dcvs_scm_set_power_params(core->dcvs_core_id, | |
+ &core->info->power_param, | |
+ &core->info->freq_tbl[0], | |
+ &core->coeffs); | |
+ if (ret) { | |
+ freq_tbl[i].is_trans_level ^= 1; | |
+ __err("Error %d in toggling freq %d (orig enable val %d)\n", | |
+ ret, freq_tbl[i].freq, freq_tbl[i].is_trans_level); | |
+ } | |
+ return count; | |
+} | |
static int msm_dcvs_setup_core_sysfs(struct dcvs_core *core) | |
{ | |
int ret = 0; | |
struct kobject *core_kobj = NULL; | |
- const int attr_count = 15; | |
+ const int attr_count = 25; | |
BUG_ON(!cores_kobj); | |
@@ -415,23 +760,35 @@ static int msm_dcvs_setup_core_sysfs(struct dcvs_core *core) | |
goto done; | |
} | |
- DCVS_RO_ATTRIB(0, idle_enabled); | |
- DCVS_RO_ATTRIB(1, freq_change_enabled); | |
- DCVS_RO_ATTRIB(2, actual_freq); | |
- DCVS_RO_ATTRIB(3, freq_change_us); | |
- DCVS_RO_ATTRIB(4, max_time_us); | |
- | |
- DCVS_RW_ATTRIB(5, slack_time_us); | |
- DCVS_RW_ATTRIB(6, scale_slack_time); | |
- DCVS_RW_ATTRIB(7, scale_slack_time_pct); | |
- DCVS_RW_ATTRIB(8, disable_pc_threshold); | |
- DCVS_RW_ATTRIB(9, em_window_size); | |
- DCVS_RW_ATTRIB(10, em_max_util_pct); | |
- DCVS_RW_ATTRIB(11, ss_window_size); | |
- DCVS_RW_ATTRIB(12, ss_util_pct); | |
- DCVS_RW_ATTRIB(13, ss_iobusy_conv); | |
- | |
- core->attrib.attrib_group.attrs[14] = NULL; | |
+ DCVS_RO_ATTRIB(0, freq_change_us); | |
+ | |
+ DCVS_RW_ATTRIB(1, disable_pc_threshold); | |
+ DCVS_RW_ATTRIB(2, em_win_size_min_us); | |
+ DCVS_RW_ATTRIB(3, em_win_size_max_us); | |
+ DCVS_RW_ATTRIB(4, em_max_util_pct); | |
+ DCVS_RW_ATTRIB(5, group_id); | |
+ DCVS_RW_ATTRIB(6, max_freq_chg_time_us); | |
+ DCVS_RW_ATTRIB(7, slack_mode_dynamic); | |
+ DCVS_RW_ATTRIB(8, slack_weight_thresh_pct); | |
+ DCVS_RW_ATTRIB(9, slack_time_min_us); | |
+ DCVS_RW_ATTRIB(10, slack_time_max_us); | |
+ DCVS_RW_ATTRIB(11, ss_no_corr_below_freq); | |
+ DCVS_RW_ATTRIB(12, ss_win_size_min_us); | |
+ DCVS_RW_ATTRIB(13, ss_win_size_max_us); | |
+ DCVS_RW_ATTRIB(14, ss_util_pct); | |
+ | |
+ DCVS_RW_ATTRIB(15, active_coeff_a); | |
+ DCVS_RW_ATTRIB(16, active_coeff_b); | |
+ DCVS_RW_ATTRIB(17, active_coeff_c); | |
+ DCVS_RW_ATTRIB(18, leakage_coeff_a); | |
+ DCVS_RW_ATTRIB(19, leakage_coeff_b); | |
+ DCVS_RW_ATTRIB(20, leakage_coeff_c); | |
+ DCVS_RW_ATTRIB(21, leakage_coeff_d); | |
+ DCVS_RW_ATTRIB(22, thermal_poll_ms); | |
+ | |
+ DCVS_RW_ATTRIB(23, freq_tbl); | |
+ | |
+ core->attrib.attrib_group.attrs[24] = NULL; | |
core_kobj = kobject_create_and_add(core->core_name, cores_kobj); | |
if (!core_kobj) { | |
@@ -442,8 +799,6 @@ static int msm_dcvs_setup_core_sysfs(struct dcvs_core *core) | |
ret = sysfs_create_group(core_kobj, &core->attrib.attrib_group); | |
if (ret) | |
__err("Cannot create core %s attr group\n", core->core_name); | |
- else if (msm_dcvs_debug & MSM_DCVS_DEBUG_NOTIFIER) | |
- __info("Setting up attributes for core %s\n", core->core_name); | |
done: | |
if (ret) { | |
@@ -454,273 +809,337 @@ done: | |
return ret; | |
} | |
-/* Return the core if found or add to list if @add_to_list is true */ | |
-static struct dcvs_core *msm_dcvs_get_core(const char *name, int add_to_list) | |
+static int get_core_offset(enum msm_dcvs_core_type type, int num) | |
+{ | |
+ int offset = -EINVAL; | |
+ | |
+ switch (type) { | |
+ case MSM_DCVS_CORE_TYPE_CPU: | |
+ offset = CPU_OFFSET + num; | |
+ BUG_ON(offset >= GPU_OFFSET); | |
+ break; | |
+ case MSM_DCVS_CORE_TYPE_GPU: | |
+ offset = GPU_OFFSET + num; | |
+ BUG_ON(offset >= CORES_MAX); | |
+ break; | |
+ default: | |
+ BUG(); | |
+ } | |
+ | |
+ return offset; | |
+} | |
+ | |
+/* Return the core and initialize non platform data specific numbers in it */ | |
+static struct dcvs_core *msm_dcvs_add_core(enum msm_dcvs_core_type type, | |
+ int num) | |
{ | |
struct dcvs_core *core = NULL; | |
int i; | |
- int empty = -1; | |
+ char name[CORE_NAME_MAX]; | |
- if (!name[0] || | |
- (strnlen(name, CORE_NAME_MAX - 1) == CORE_NAME_MAX - 1)) | |
- return core; | |
+ i = get_core_offset(type, num); | |
+ if (i < 0) | |
+ return NULL; | |
- mutex_lock(&core_list_lock); | |
- for (i = 0; i < CORES_MAX; i++) { | |
- core = &core_list[i]; | |
- if ((empty < 0) && !core->core_name[0]) { | |
- empty = i; | |
- continue; | |
- } | |
- if (!strncmp(name, core->core_name, CORE_NAME_MAX)) | |
- break; | |
- } | |
+ if (type == MSM_DCVS_CORE_TYPE_CPU) | |
+ snprintf(name, CORE_NAME_MAX, "cpu%d", num); | |
+ else | |
+ snprintf(name, CORE_NAME_MAX, "gpu%d", num); | |
+ | |
+ core = &core_list[i]; | |
+ core->dcvs_core_id = i; | |
+ strlcpy(core->core_name, name, CORE_NAME_MAX); | |
+ spin_lock_init(&core->pending_freq_lock); | |
+ spin_lock_init(&core->idle_state_change_lock); | |
+ hrtimer_init(&core->slack_timer, | |
+ CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED); | |
+ core->slack_timer.function = msm_dcvs_core_slack_timer; | |
+ return core; | |
+} | |
- /* Check for core_list full */ | |
- if ((i == CORES_MAX) && (empty < 0)) { | |
- mutex_unlock(&core_list_lock); | |
- return NULL; | |
- } | |
+/* Return the core if found or add to list if @add_to_list is true */ | |
+static struct dcvs_core *msm_dcvs_get_core(int offset) | |
+{ | |
+ /* if the handle is still not set bug */ | |
+ BUG_ON(core_list[offset].dcvs_core_id == -1); | |
+ return &core_list[offset]; | |
+} | |
- if (i == CORES_MAX && add_to_list) { | |
- core = &core_list[empty]; | |
- strlcpy(core->core_name, name, CORE_NAME_MAX); | |
- mutex_init(&core->lock); | |
- spin_lock_init(&core->cpu_lock); | |
- core->handle = empty + CORE_HANDLE_OFFSET; | |
- hrtimer_init(&core->timer, | |
- CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED); | |
- core->timer.function = msm_dcvs_core_slack_timer; | |
- } | |
- mutex_unlock(&core_list_lock); | |
+void msm_dcvs_register_cpu_freq(uint32_t freq, uint32_t voltage) | |
+{ | |
+ BUG_ON(freq == 0 || voltage == 0 || | |
+ num_cpu_freqs == DCVS_MAX_NUM_FREQS); | |
- return core; | |
+ cpu_freq_tbl[num_cpu_freqs].freq = freq; | |
+ cpu_freq_tbl[num_cpu_freqs].voltage = voltage; | |
+ | |
+ num_cpu_freqs++; | |
} | |
-int msm_dcvs_register_core(const char *core_name, uint32_t group_id, | |
- struct msm_dcvs_core_info *info) | |
+static void update_cpu_dcvs_params(struct msm_dcvs_core_info *info) | |
+{ | |
+ int i; | |
+ | |
+ BUG_ON(num_cpu_freqs == 0); | |
+ | |
+ info->freq_tbl = cpu_freq_tbl; | |
+ info->power_param.num_freq = num_cpu_freqs; | |
+ | |
+ if (!dcvs_pdata || dcvs_pdata->num_sync_rules == 0) | |
+ return; | |
+ | |
+ /* the first sync rule shows what the turbo frequencies are - | |
+ * these frequencies need energy offsets set */ | |
+ for (i = 0; i < DCVS_MAX_NUM_FREQS && cpu_freq_tbl[i].freq != 0; i++) | |
+ if (cpu_freq_tbl[i].freq > dcvs_pdata->sync_rules[0].cpu_khz) { | |
+ cpu_freq_tbl[i].active_energy_offset = 100; | |
+ cpu_freq_tbl[i].leakage_energy_offset = 100; | |
+ } | |
+} | |
+ | |
+int msm_dcvs_register_core( | |
+ enum msm_dcvs_core_type type, | |
+ int type_core_num, | |
+ struct msm_dcvs_core_info *info, | |
+ int (*set_frequency)(int type_core_num, unsigned int freq), | |
+ unsigned int (*get_frequency)(int type_core_num), | |
+ int (*idle_enable)(int type_core_num, | |
+ enum msm_core_control_event event), | |
+ int (*set_floor_frequency)(int type_core_num, unsigned int freq), | |
+ int sensor) | |
{ | |
int ret = -EINVAL; | |
+ int offset; | |
struct dcvs_core *core = NULL; | |
+ uint32_t ret1; | |
+ uint32_t ret2; | |
- if (!core_name || !core_name[0]) | |
+ offset = get_core_offset(type, type_core_num); | |
+ if (offset < 0) | |
return ret; | |
+ if (core_list[offset].dcvs_core_id != -1) | |
+ return core_list[offset].dcvs_core_id; | |
- core = msm_dcvs_get_core(core_name, true); | |
+ core = msm_dcvs_add_core(type, type_core_num); | |
if (!core) | |
return ret; | |
- mutex_lock(&core->lock); | |
- if (group_id) { | |
- /** | |
- * Create a group for cores, if this core is part of a group | |
- * if the group_id is 0, the core is not part of a group. | |
- * If the group_id already exits, it will through an error | |
- * which we will ignore. | |
- */ | |
- ret = msm_dcvs_scm_create_group(group_id); | |
- if (ret == -ENOMEM) | |
- goto bail; | |
- } | |
- core->group_id = group_id; | |
+ core->type = type; | |
+ core->type_core_num = type_core_num; | |
+ core->set_frequency = set_frequency; | |
+ core->get_frequency = get_frequency; | |
+ core->idle_enable = idle_enable; | |
+ core->set_floor_frequency = set_floor_frequency; | |
+ core->pending_freq = STOP_FREQ_CHANGE; | |
+ | |
+ core->info = info; | |
+ if (type == MSM_DCVS_CORE_TYPE_CPU) | |
+ update_cpu_dcvs_params(info); | |
- core->max_time_us = info->core_param.max_time_us; | |
memcpy(&core->algo_param, &info->algo_param, | |
sizeof(struct msm_dcvs_algo_param)); | |
- ret = msm_dcvs_scm_register_core(core->handle, group_id, | |
- &info->core_param, info->freq_tbl); | |
- if (ret) | |
+ memcpy(&core->coeffs, &info->energy_coeffs, | |
+ sizeof(struct msm_dcvs_energy_curve_coeffs)); | |
+ | |
+ /* | |
+ * The tz expects cpu0 to represent bit 0 in the mask, however the | |
+ * dcvs_core_id needs to start from 1, dcvs_core_id = 0 is used to | |
+ * indicate that this request is not associated with any core. | |
+ * mpdecision | |
+ */ | |
+ info->core_param.core_bitmask_id | |
+ = 1 << (core->dcvs_core_id - CPU_OFFSET); | |
+ core->sensor = sensor; | |
+ | |
+ ret = msm_dcvs_scm_register_core(core->dcvs_core_id, &info->core_param); | |
+ if (ret) { | |
+ __err("%s: scm register core fail handle = %d ret = %d\n", | |
+ __func__, core->dcvs_core_id, ret); | |
+ goto bail; | |
+ } | |
+ | |
+ ret = msm_dcvs_scm_set_algo_params(core->dcvs_core_id, | |
+ &info->algo_param); | |
+ if (ret) { | |
+ __err("%s: scm algo params failed ret = %d\n", __func__, ret); | |
+ goto bail; | |
+ } | |
+ | |
+ ret = msm_dcvs_scm_set_power_params(core->dcvs_core_id, | |
+ &info->power_param, | |
+ &info->freq_tbl[0], &core->coeffs); | |
+ if (ret) { | |
+ __err("%s: scm power params failed ret = %d\n", __func__, ret); | |
goto bail; | |
+ } | |
- ret = msm_dcvs_scm_set_algo_params(core->handle, &info->algo_param); | |
+ ret = msm_dcvs_scm_event(core->dcvs_core_id, MSM_DCVS_SCM_CORE_ONLINE, | |
+ core->actual_freq, 0, &ret1, &ret2); | |
if (ret) | |
goto bail; | |
ret = msm_dcvs_setup_core_sysfs(core); | |
if (ret) { | |
__err("Unable to setup core %s sysfs\n", core->core_name); | |
- core_handles[core->handle - CORE_HANDLE_OFFSET] = NULL; | |
goto bail; | |
} | |
- | |
-bail: | |
- mutex_unlock(&core->lock); | |
+ core->idle_entered = -1; | |
+ init_waitqueue_head(&core->wait_q); | |
+ core->task = kthread_run(msm_dcvs_do_freq, (void *)core, | |
+ "msm_dcvs/%d", core->dcvs_core_id); | |
+ ret = core->dcvs_core_id; | |
+ | |
+ INIT_DELAYED_WORK(&core->temperature_work, msm_dcvs_report_temp_work); | |
+ schedule_delayed_work(&core->temperature_work, | |
+ msecs_to_jiffies(info->thermal_poll_ms)); | |
return ret; | |
+bail: | |
+ core->dcvs_core_id = -1; | |
+ return -EINVAL; | |
} | |
EXPORT_SYMBOL(msm_dcvs_register_core); | |
-int msm_dcvs_freq_sink_register(struct msm_dcvs_freq *drv) | |
+void msm_dcvs_update_limits(int dcvs_core_id) | |
{ | |
- int ret = -EINVAL; | |
- struct dcvs_core *core = NULL; | |
- uint32_t ret1; | |
- uint32_t ret2; | |
- | |
- if (!drv || !drv->core_name) | |
- return ret; | |
+ struct dcvs_core *core; | |
- core = msm_dcvs_get_core(drv->core_name, true); | |
- if (!core) | |
- return ret; | |
- | |
- mutex_lock(&core->lock); | |
- if (core->freq_driver && (msm_dcvs_debug & MSM_DCVS_DEBUG_NOTIFIER)) | |
- __info("Frequency notifier for %s being replaced\n", | |
- core->core_name); | |
- core->freq_driver = drv; | |
- core->task = kthread_create(msm_dcvs_do_freq, (void *)core, | |
- "msm_dcvs/%d", core->handle); | |
- if (IS_ERR(core->task)) { | |
- mutex_unlock(&core->lock); | |
- return -EFAULT; | |
- } | |
- | |
- if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE) | |
- __info("Enabling idle pulse for %s\n", core->core_name); | |
- | |
- if (core->idle_driver) { | |
- core->actual_freq = core->freq_driver->get_frequency(drv); | |
- /* Notify TZ to start receiving idle info for the core */ | |
- ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_ENABLE_CORE, 1, | |
- &ret1, &ret2); | |
- core->idle_driver->enable(core->idle_driver, | |
- MSM_DCVS_ENABLE_IDLE_PULSE); | |
+ if (dcvs_core_id < CPU_OFFSET || dcvs_core_id > CORES_MAX) { | |
+ __err("%s invalid dcvs_core_id = %d returning -EINVAL\n", | |
+ __func__, dcvs_core_id); | |
+ return; | |
} | |
- mutex_unlock(&core->lock); | |
- | |
- return core->handle; | |
+ core = msm_dcvs_get_core(dcvs_core_id); | |
+ core->actual_freq = core->get_frequency(core->type_core_num); | |
} | |
-EXPORT_SYMBOL(msm_dcvs_freq_sink_register); | |
-int msm_dcvs_freq_sink_unregister(struct msm_dcvs_freq *drv) | |
+int msm_dcvs_freq_sink_start(int dcvs_core_id) | |
{ | |
int ret = -EINVAL; | |
struct dcvs_core *core = NULL; | |
uint32_t ret1; | |
- uint32_t ret2; | |
- | |
- if (!drv || !drv->core_name) | |
- return ret; | |
+ unsigned long flags; | |
+ int new_freq; | |
+ int timer_interval_us; | |
+ | |
+ if (dcvs_core_id < CPU_OFFSET || dcvs_core_id > CORES_MAX) { | |
+ __err("%s invalid dcvs_core_id = %d returning -EINVAL\n", | |
+ __func__, dcvs_core_id); | |
+ return -EINVAL; | |
+ } | |
- core = msm_dcvs_get_core(drv->core_name, false); | |
+ core = msm_dcvs_get_core(dcvs_core_id); | |
if (!core) | |
return ret; | |
- mutex_lock(&core->lock); | |
- if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE) | |
- __info("Disabling idle pulse for %s\n", core->core_name); | |
- if (core->idle_driver) { | |
- core->idle_driver->enable(core->idle_driver, | |
- MSM_DCVS_DISABLE_IDLE_PULSE); | |
- /* Notify TZ to stop receiving idle info for the core */ | |
- ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_ENABLE_CORE, 0, | |
- &ret1, &ret2); | |
- hrtimer_cancel(&core->timer); | |
- core->idle_driver->enable(core->idle_driver, | |
- MSM_DCVS_ENABLE_HIGH_LATENCY_MODES); | |
- if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE) | |
- __info("Enabling LPM for %s\n", core->core_name); | |
- } | |
- core->freq_pending = 0; | |
- core->freq_driver = NULL; | |
- mutex_unlock(&core->lock); | |
- kthread_stop(core->task); | |
+ core->actual_freq = core->get_frequency(core->type_core_num); | |
- return 0; | |
-} | |
-EXPORT_SYMBOL(msm_dcvs_freq_sink_unregister); | |
+ spin_lock_irqsave(&core->pending_freq_lock, flags); | |
+ /* mark that we are ready to accept new frequencies */ | |
+ request_freq_change(core, NO_OUTSTANDING_FREQ_CHANGE); | |
+ spin_unlock_irqrestore(&core->pending_freq_lock, flags); | |
-int msm_dcvs_idle_source_register(struct msm_dcvs_idle *drv) | |
-{ | |
- int ret = -EINVAL; | |
- struct dcvs_core *core = NULL; | |
+ spin_lock_irqsave(&core->idle_state_change_lock, flags); | |
+ core->idle_entered = -1; | |
+ spin_unlock_irqrestore(&core->idle_state_change_lock, flags); | |
- if (!drv || !drv->core_name) | |
- return ret; | |
+ /* Notify TZ to start receiving idle info for the core */ | |
+ ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_DCVS_ENABLE, 1, &ret1); | |
- core = msm_dcvs_get_core(drv->core_name, true); | |
- if (!core) | |
- return ret; | |
+ ret = msm_dcvs_scm_event( | |
+ core->dcvs_core_id, MSM_DCVS_SCM_CORE_ONLINE, core->actual_freq, | |
+ 0, &new_freq, &timer_interval_us); | |
+ if (ret) | |
+ __err("Error (%d) DCVS sending online for %s\n", | |
+ ret, core->core_name); | |
+ | |
+ if (new_freq != 0) { | |
+ spin_lock_irqsave(&core->pending_freq_lock, flags); | |
+ request_freq_change(core, new_freq); | |
+ spin_unlock_irqrestore(&core->pending_freq_lock, flags); | |
+ } | |
+ force_start_slack_timer(core, timer_interval_us); | |
- mutex_lock(&core->lock); | |
- if (core->idle_driver && (msm_dcvs_debug & MSM_DCVS_DEBUG_NOTIFIER)) | |
- __info("Idle notifier for %s being replaced\n", | |
- core->core_name); | |
- core->idle_driver = drv; | |
- mutex_unlock(&core->lock); | |
- return core->handle; | |
+ core->idle_enable(core->type_core_num, MSM_DCVS_ENABLE_IDLE_PULSE); | |
+ return 0; | |
} | |
-EXPORT_SYMBOL(msm_dcvs_idle_source_register); | |
+EXPORT_SYMBOL(msm_dcvs_freq_sink_start); | |
-int msm_dcvs_idle_source_unregister(struct msm_dcvs_idle *drv) | |
+int msm_dcvs_freq_sink_stop(int dcvs_core_id) | |
{ | |
int ret = -EINVAL; | |
struct dcvs_core *core = NULL; | |
+ uint32_t ret1; | |
+ uint32_t freq; | |
+ unsigned long flags; | |
- if (!drv || !drv->core_name) | |
- return ret; | |
+ if (dcvs_core_id < 0 || dcvs_core_id > CORES_MAX) { | |
+ pr_err("%s invalid dcvs_core_id = %d returning -EINVAL\n", | |
+ __func__, dcvs_core_id); | |
+ return -EINVAL; | |
+ } | |
- core = msm_dcvs_get_core(drv->core_name, false); | |
- if (!core) | |
+ core = msm_dcvs_get_core(dcvs_core_id); | |
+ if (!core) { | |
+ __err("couldn't find core for coreid = %d\n", dcvs_core_id); | |
return ret; | |
+ } | |
- mutex_lock(&core->lock); | |
- core->idle_driver = NULL; | |
- mutex_unlock(&core->lock); | |
+ core->idle_enable(core->type_core_num, MSM_DCVS_DISABLE_IDLE_PULSE); | |
+ /* Notify TZ to stop receiving idle info for the core */ | |
+ ret = msm_dcvs_scm_event(core->dcvs_core_id, MSM_DCVS_SCM_DCVS_ENABLE, | |
+ 0, core->actual_freq, &freq, &ret1); | |
+ core->idle_enable(core->type_core_num, | |
+ MSM_DCVS_ENABLE_HIGH_LATENCY_MODES); | |
+ spin_lock_irqsave(&core->pending_freq_lock, flags); | |
+ /* flush out all the pending freq changes */ | |
+ request_freq_change(core, STOP_FREQ_CHANGE); | |
+ spin_unlock_irqrestore(&core->pending_freq_lock, flags); | |
+ force_stop_slack_timer(core); | |
return 0; | |
} | |
-EXPORT_SYMBOL(msm_dcvs_idle_source_unregister); | |
+EXPORT_SYMBOL(msm_dcvs_freq_sink_stop); | |
-int msm_dcvs_idle(int handle, enum msm_core_idle_state state, uint32_t iowaited) | |
+int msm_dcvs_idle(int dcvs_core_id, enum msm_core_idle_state state, | |
+ uint32_t iowaited) | |
{ | |
int ret = 0; | |
struct dcvs_core *core = NULL; | |
uint32_t timer_interval_us = 0; | |
uint32_t r0, r1; | |
- uint32_t freq_changed = 0; | |
- if (handle >= CORE_HANDLE_OFFSET && | |
- (handle - CORE_HANDLE_OFFSET) < CORES_MAX) | |
- core = &core_list[handle - CORE_HANDLE_OFFSET]; | |
- | |
- BUG_ON(!core); | |
+ if (dcvs_core_id < CPU_OFFSET || dcvs_core_id > CORES_MAX) { | |
+ pr_err("invalid dcvs_core_id = %d ret -EINVAL\n", dcvs_core_id); | |
+ return -EINVAL; | |
+ } | |
- if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE) | |
- __info("Core %s idle state %d\n", core->core_name, state); | |
+ core = msm_dcvs_get_core(dcvs_core_id); | |
switch (state) { | |
case MSM_DCVS_IDLE_ENTER: | |
- hrtimer_cancel(&core->timer); | |
- ret = msm_dcvs_scm_event(core->handle, | |
+ stop_slack_timer(core); | |
+ ret = msm_dcvs_scm_event(core->dcvs_core_id, | |
MSM_DCVS_SCM_IDLE_ENTER, 0, 0, &r0, &r1); | |
- if (ret) | |
+ if (ret < 0 && ret != -13) | |
__err("Error (%d) sending idle enter for %s\n", | |
ret, core->core_name); | |
+ trace_msm_dcvs_idle("idle_enter_exit", core->core_name, 1); | |
break; | |
case MSM_DCVS_IDLE_EXIT: | |
- hrtimer_cancel(&core->timer); | |
ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_IDLE_EXIT, | |
- iowaited, &timer_interval_us, &freq_changed); | |
+ iowaited, &timer_interval_us); | |
if (ret) | |
__err("Error (%d) sending idle exit for %s\n", | |
ret, core->core_name); | |
- /* only start slack timer if change_freq won't */ | |
- if (freq_changed || core->change_freq_activated) | |
- break; | |
- if (timer_interval_us && !core->timer_disabled) { | |
- ret = hrtimer_start(&core->timer, | |
- ktime_set(0, timer_interval_us * 1000), | |
- HRTIMER_MODE_REL_PINNED); | |
- | |
- if (ret) | |
- __err("Failed to register timer for core %s\n", | |
- core->core_name); | |
- } | |
+ start_slack_timer(core, timer_interval_us); | |
+ trace_msm_dcvs_idle("idle_enter_exit", core->core_name, 0); | |
+ trace_msm_dcvs_iowait("iowait", core->core_name, iowaited); | |
+ trace_msm_dcvs_slack_time("slack_timer_dcvs", core->core_name, | |
+ timer_interval_us); | |
break; | |
} | |
@@ -755,13 +1174,6 @@ static int __init msm_dcvs_late_init(void) | |
goto err; | |
} | |
- if (!debugfs_create_u32("debug_mask", S_IRUGO | S_IWUSR, | |
- debugfs_base, &msm_dcvs_debug)) { | |
- __err("Cannot create debugfs entry %s\n", "debug_mask"); | |
- ret = -ENOMEM; | |
- goto err; | |
- } | |
- | |
err: | |
if (ret) { | |
kobject_del(cores_kobj); | |
@@ -773,19 +1185,45 @@ err: | |
} | |
late_initcall(msm_dcvs_late_init); | |
+static int __devinit dcvs_probe(struct platform_device *pdev) | |
+{ | |
+ if (pdev->dev.platform_data) | |
+ dcvs_pdata = pdev->dev.platform_data; | |
+ | |
+ return 0; | |
+} | |
+ | |
+static struct platform_driver dcvs_driver = { | |
+ .probe = dcvs_probe, | |
+ .driver = { | |
+ .name = "dcvs", | |
+ .owner = THIS_MODULE, | |
+ }, | |
+}; | |
+ | |
static int __init msm_dcvs_early_init(void) | |
{ | |
int ret = 0; | |
+ int i; | |
+ | |
+ platform_driver_register(&dcvs_driver); | |
if (!msm_dcvs_enabled) { | |
__info("Not enabled (%d)\n", msm_dcvs_enabled); | |
return 0; | |
} | |
- ret = msm_dcvs_scm_init(10 * 1024); | |
- if (ret) | |
+ | |
+ /* Only need about 32kBytes for normal operation */ | |
+ ret = msm_dcvs_scm_init(SZ_32K); | |
+ if (ret) { | |
__err("Unable to initialize DCVS err=%d\n", ret); | |
+ goto done; | |
+ } | |
+ for (i = 0; i < CORES_MAX; i++) | |
+ core_list[i].dcvs_core_id = -1; | |
+done: | |
return ret; | |
} | |
postcore_initcall(msm_dcvs_early_init); | |
diff --git a/arch/arm/mach-msm/msm_dcvs_scm.c b/arch/arm/mach-msm/msm_dcvs_scm.c | |
index 1ea5363..df6c44f 100644 | |
--- a/arch/arm/mach-msm/msm_dcvs_scm.c | |
+++ b/arch/arm/mach-msm/msm_dcvs_scm.c | |
@@ -21,17 +21,15 @@ | |
#include <mach/scm.h> | |
#include <mach/msm_dcvs_scm.h> | |
-#define DCVS_CMD_CREATE_GROUP 1 | |
#define DCVS_CMD_REGISTER_CORE 2 | |
#define DCVS_CMD_SET_ALGO_PARAM 3 | |
#define DCVS_CMD_EVENT 4 | |
#define DCVS_CMD_INIT 5 | |
+#define DCVS_CMD_SET_POWER_PARAM 6 | |
struct scm_register_core { | |
uint32_t core_id; | |
- uint32_t group_id; | |
phys_addr_t core_param_phy; | |
- phys_addr_t freq_phy; | |
}; | |
struct scm_algo { | |
@@ -44,6 +42,21 @@ struct scm_init { | |
uint32_t size; | |
}; | |
+struct scm_pwr_param { | |
+ uint32_t core_id; | |
+ phys_addr_t pwr_param_phy; | |
+ phys_addr_t freq_phy; | |
+ phys_addr_t coeffs_phy; | |
+}; | |
+ | |
+struct msm_algo_param { | |
+ enum msm_dcvs_algo_param_type type; | |
+ union { | |
+ struct msm_dcvs_algo_param dcvs_param; | |
+ struct msm_mpd_algo_param mpd_param; | |
+ } u; | |
+}; | |
+ | |
int msm_dcvs_scm_init(size_t size) | |
{ | |
int ret = 0; | |
@@ -69,49 +82,25 @@ int msm_dcvs_scm_init(size_t size) | |
} | |
EXPORT_SYMBOL(msm_dcvs_scm_init); | |
-int msm_dcvs_scm_create_group(uint32_t id) | |
-{ | |
- int ret = 0; | |
- | |
- ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_CREATE_GROUP, | |
- &id, sizeof(uint32_t), NULL, 0); | |
- | |
- return ret; | |
-} | |
-EXPORT_SYMBOL(msm_dcvs_scm_create_group); | |
- | |
-int msm_dcvs_scm_register_core(uint32_t core_id, uint32_t group_id, | |
- struct msm_dcvs_core_param *param, | |
- struct msm_dcvs_freq_entry *freq) | |
+int msm_dcvs_scm_register_core(uint32_t core_id, | |
+ struct msm_dcvs_core_param *param) | |
{ | |
int ret = 0; | |
struct scm_register_core reg_data; | |
struct msm_dcvs_core_param *p = NULL; | |
- struct msm_dcvs_freq_entry *f = NULL; | |
p = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_core_param)), GFP_KERNEL); | |
if (!p) | |
return -ENOMEM; | |
- f = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_freq_entry) * | |
- param->num_freq), GFP_KERNEL); | |
- if (!f) { | |
- kfree(p); | |
- return -ENOMEM; | |
- } | |
- | |
memcpy(p, param, sizeof(struct msm_dcvs_core_param)); | |
- memcpy(f, freq, sizeof(struct msm_dcvs_freq_entry) * param->num_freq); | |
reg_data.core_id = core_id; | |
- reg_data.group_id = group_id; | |
reg_data.core_param_phy = virt_to_phys(p); | |
- reg_data.freq_phy = virt_to_phys(f); | |
ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_REGISTER_CORE, | |
®_data, sizeof(reg_data), NULL, 0); | |
- kfree(f); | |
kfree(p); | |
return ret; | |
@@ -123,13 +112,14 @@ int msm_dcvs_scm_set_algo_params(uint32_t core_id, | |
{ | |
int ret = 0; | |
struct scm_algo algo; | |
- struct msm_dcvs_algo_param *p = NULL; | |
+ struct msm_algo_param *p = NULL; | |
- p = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_algo_param)), GFP_KERNEL); | |
+ p = kzalloc(PAGE_ALIGN(sizeof(struct msm_algo_param)), GFP_KERNEL); | |
if (!p) | |
return -ENOMEM; | |
- memcpy(p, param, sizeof(struct msm_dcvs_algo_param)); | |
+ p->type = MSM_DCVS_ALGO_DCVS_PARAM; | |
+ memcpy(&p->u.dcvs_param, param, sizeof(struct msm_dcvs_algo_param)); | |
algo.core_id = core_id; | |
algo.algo_phy = virt_to_phys(p); | |
@@ -143,6 +133,85 @@ int msm_dcvs_scm_set_algo_params(uint32_t core_id, | |
} | |
EXPORT_SYMBOL(msm_dcvs_scm_set_algo_params); | |
+int msm_mpd_scm_set_algo_params(struct msm_mpd_algo_param *param) | |
+{ | |
+ int ret = 0; | |
+ struct scm_algo algo; | |
+ struct msm_algo_param *p = NULL; | |
+ | |
+ p = kzalloc(PAGE_ALIGN(sizeof(struct msm_algo_param)), GFP_KERNEL); | |
+ if (!p) | |
+ return -ENOMEM; | |
+ | |
+ p->type = MSM_DCVS_ALGO_MPD_PARAM; | |
+ memcpy(&p->u.mpd_param, param, sizeof(struct msm_mpd_algo_param)); | |
+ | |
+ algo.core_id = 0; | |
+ algo.algo_phy = virt_to_phys(p); | |
+ | |
+ ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_SET_ALGO_PARAM, | |
+ &algo, sizeof(algo), NULL, 0); | |
+ | |
+ kfree(p); | |
+ | |
+ return ret; | |
+} | |
+EXPORT_SYMBOL(msm_mpd_scm_set_algo_params); | |
+ | |
+int msm_dcvs_scm_set_power_params(uint32_t core_id, | |
+ struct msm_dcvs_power_params *pwr_param, | |
+ struct msm_dcvs_freq_entry *freq_entry, | |
+ struct msm_dcvs_energy_curve_coeffs *coeffs) | |
+{ | |
+ int ret = 0; | |
+ struct scm_pwr_param pwr; | |
+ struct msm_dcvs_power_params *pwrt = NULL; | |
+ struct msm_dcvs_freq_entry *freqt = NULL; | |
+ struct msm_dcvs_energy_curve_coeffs *coefft = NULL; | |
+ | |
+ pwrt = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_power_params)), | |
+ GFP_KERNEL); | |
+ if (!pwrt) | |
+ return -ENOMEM; | |
+ | |
+ freqt = kzalloc(PAGE_ALIGN(sizeof(struct msm_dcvs_freq_entry) | |
+ * pwr_param->num_freq), | |
+ GFP_KERNEL); | |
+ if (!freqt) { | |
+ kfree(pwrt); | |
+ return -ENOMEM; | |
+ } | |
+ | |
+ coefft = kzalloc(PAGE_ALIGN( | |
+ sizeof(struct msm_dcvs_energy_curve_coeffs)), | |
+ GFP_KERNEL); | |
+ if (!coefft) { | |
+ kfree(pwrt); | |
+ kfree(freqt); | |
+ return -ENOMEM; | |
+ } | |
+ | |
+ memcpy(pwrt, pwr_param, sizeof(struct msm_dcvs_power_params)); | |
+ memcpy(freqt, freq_entry, | |
+ sizeof(struct msm_dcvs_freq_entry)*pwr_param->num_freq); | |
+ memcpy(coefft, coeffs, sizeof(struct msm_dcvs_energy_curve_coeffs)); | |
+ | |
+ pwr.core_id = core_id; | |
+ pwr.pwr_param_phy = virt_to_phys(pwrt); | |
+ pwr.freq_phy = virt_to_phys(freqt); | |
+ pwr.coeffs_phy = virt_to_phys(coefft); | |
+ | |
+ ret = scm_call(SCM_SVC_DCVS, DCVS_CMD_SET_POWER_PARAM, | |
+ &pwr, sizeof(pwr), NULL, 0); | |
+ | |
+ kfree(pwrt); | |
+ kfree(freqt); | |
+ kfree(coefft); | |
+ | |
+ return ret; | |
+} | |
+EXPORT_SYMBOL(msm_dcvs_scm_set_power_params); | |
+ | |
int msm_dcvs_scm_event(uint32_t core_id, | |
enum msm_dcvs_scm_event event_id, | |
uint32_t param0, uint32_t param1, | |
diff --git a/arch/arm/mach-msm/msm_turbo.c b/arch/arm/mach-msm/msm_turbo.c | |
new file mode 100644 | |
index 0000000..3d4d4e0 | |
--- /dev/null | |
+++ b/arch/arm/mach-msm/msm_turbo.c | |
@@ -0,0 +1,51 @@ | |
+/* arch/arm/mach-msm/msm_turbo.c | |
+ * | |
+ * MSM architecture cpufreq turbo boost driver | |
+ * | |
+ * Copyright (c) 2012-2013, Paul Reioux. All rights reserved. | |
+ * Author: Paul Reioux <faux123@gmail.com> | |
+ * | |
+ * 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/kernel.h> | |
+#include <linux/module.h> | |
+#include <linux/cpumask.h> | |
+ | |
+#ifdef CONFIG_TURBO_BOOST | |
+#define STOCK_CPU_MAX_SPEED 1209600 | |
+#endif | |
+ | |
+int msm_turbo(int cpufreq) | |
+{ | |
+ if (num_online_cpus() > 2) { | |
+ if (cpufreq > STOCK_CPU_MAX_SPEED) | |
+ cpufreq = STOCK_CPU_MAX_SPEED; | |
+ } | |
+ return cpufreq; | |
+} | |
+ | |
+static int msm_turbo_boost_init(void) | |
+{ | |
+ return 0; | |
+} | |
+ | |
+static void msm_turbo_boost_exit(void) | |
+{ | |
+ | |
+} | |
+ | |
+module_init(msm_turbo_boost_init); | |
+module_exit(msm_turbo_boost_exit); | |
+ | |
+MODULE_LICENSE("PROPRIETARY"); | |
+MODULE_AUTHOR("Paul Reioux <reioux@gmail.com>"); | |
+MODULE_DESCRIPTION("MSM turbo boost module"); | |
\ No newline at end of file | |
diff --git a/arch/arm/mach-msm/qdsp5/audio_ac3.c b/arch/arm/mach-msm/qdsp5/audio_ac3.c | |
index 2e6e812..9227a16 100644 | |
--- a/arch/arm/mach-msm/qdsp5/audio_ac3.c | |
+++ b/arch/arm/mach-msm/qdsp5/audio_ac3.c | |
@@ -1,6 +1,6 @@ | |
/* arch/arm/mach-msm/audio_ac3.c | |
* | |
- * Copyright (c) 2008-2009, 2011-2012 The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2008-2009, 2011-2013 The Linux Foundation. All rights reserved. | |
* | |
* This code also borrows from audio_aac.c, which is | |
* Copyright (C) 2008 Google, Inc. | |
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb.c b/arch/arm/mach-msm/qdsp5/audio_amrnb.c | |
index fad01db..a7f9bd8 100644 | |
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb.c | |
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb.c | |
@@ -2,7 +2,7 @@ | |
* | |
* amrnb audio decoder device | |
* | |
- * Copyright (c) 2008-2009, 2011-2012 The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2008-2009, 2011-2013 The Linux Foundation. All rights reserved. | |
* | |
* Based on the mp3 native driver in arch/arm/mach-msm/qdsp5/audio_mp3.c | |
* | |
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c | |
index a8d0821..633e067 100644 | |
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c | |
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c | |
@@ -694,6 +694,7 @@ static void audamrnb_ioport_reset(struct audio_amrnb_in *audio) | |
audamrnb_in_flush(audio); | |
mutex_unlock(&audio->write_lock); | |
wake_up(&audio->wait); | |
+ memset(&meta_field, 0, sizeof(meta_field)); | |
mutex_lock(&audio->read_lock); | |
audamrnb_out_flush(audio); | |
mutex_unlock(&audio->read_lock); | |
diff --git a/arch/arm/mach-msm/qdsp5/audio_voicememo.c b/arch/arm/mach-msm/qdsp5/audio_voicememo.c | |
index 1931a57..f88805e 100644 | |
--- a/arch/arm/mach-msm/qdsp5/audio_voicememo.c | |
+++ b/arch/arm/mach-msm/qdsp5/audio_voicememo.c | |
@@ -4,7 +4,7 @@ | |
* | |
* Copyright (C) 2008 Google, Inc. | |
* Copyright (C) 2008 HTC Corporation | |
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved. | |
* | |
* This code is based in part on arch/arm/mach-msm/qdsp5/audio_mp3.c | |
* | |
diff --git a/drivers/base/genlock.c b/drivers/base/genlock.c | |
index 8b7259a..3863f44 100644 | |
--- a/drivers/base/genlock.c | |
+++ b/drivers/base/genlock.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2011-2013, The Linux Foundation. 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 and | |
@@ -712,6 +712,40 @@ struct genlock_handle *genlock_get_handle_fd(int fd) | |
} | |
EXPORT_SYMBOL(genlock_get_handle_fd); | |
+/* | |
++ * Get a file descriptor reference to a lock suitable for sharing with | |
++ * other processes | |
++ */ | |
+ | |
+int genlock_get_fd_handle(struct genlock_handle *handle) | |
+{ | |
+ int ret; | |
+ struct genlock *lock; | |
+ | |
+ if (IS_ERR_OR_NULL(handle)) | |
+ return -EINVAL; | |
+ | |
+ lock = handle->lock; | |
+ | |
+ if (IS_ERR(lock)) | |
+ return PTR_ERR(lock); | |
+ | |
+ if (!lock->file) { | |
+ GENLOCK_LOG_ERR("No file attached to the lock\n"); | |
+ return -EINVAL; | |
+ } | |
+ | |
+ ret = get_unused_fd_flags(0); | |
+ | |
+ if (ret < 0) | |
+ return ret; | |
+ | |
+ fd_install(ret, lock->file); | |
+ | |
+ return ret; | |
+} | |
+EXPORT_SYMBOL(genlock_get_fd_handle); | |
+ | |
#ifdef CONFIG_GENLOCK_MISCDEVICE | |
static long genlock_dev_ioctl(struct file *filep, unsigned int cmd, | |
diff --git a/drivers/char/random.c b/drivers/char/random.c | |
index 817eeb6..e58a9c7 100644 | |
--- a/drivers/char/random.c | |
+++ b/drivers/char/random.c | |
@@ -283,14 +283,14 @@ | |
* The minimum number of bits of entropy before we wake up a read on | |
* /dev/random. Should be enough to do a significant reseed. | |
*/ | |
-static int random_read_wakeup_thresh = 64; | |
+static int random_read_wakeup_thresh = 256; | |
/* | |
* If the entropy count falls under this number of bits, then we | |
* should wake up processes which are selecting or polling on write | |
* access to /dev/random. | |
*/ | |
-static int random_write_wakeup_thresh = 128; | |
+static int random_write_wakeup_thresh = 512; | |
/* | |
* When the input pool goes over trickle_thresh, start dropping most | |
diff --git a/drivers/cpufreq/cpufreq_smartass2.c b/drivers/cpufreq/cpufreq_smartass2.c | |
index 11c8bcd..a51ee67 100644 | |
--- a/drivers/cpufreq/cpufreq_smartass2.c | |
+++ b/drivers/cpufreq/cpufreq_smartass2.c | |
@@ -44,7 +44,7 @@ | |
* towards the ideal frequency and slower after it has passed it. Similarly, | |
* lowering the frequency towards the ideal frequency is faster than below it. | |
*/ | |
-#define DEFAULT_AWAKE_IDEAL_FREQ 768000 | |
+#define DEFAULT_AWAKE_IDEAL_FREQ 700800 | |
static unsigned int awake_ideal_freq; | |
/* | |
@@ -53,7 +53,7 @@ static unsigned int awake_ideal_freq; | |
* that practically when sleep_ideal_freq==0 the awake_ideal_freq is used | |
* also when suspended). | |
*/ | |
-#define DEFAULT_SLEEP_IDEAL_FREQ 368640 | |
+#define DEFAULT_SLEEP_IDEAL_FREQ 122880 | |
static unsigned int sleep_ideal_freq; | |
/* | |
@@ -102,7 +102,7 @@ static unsigned long down_rate_us; | |
* The frequency to set when waking up from sleep. | |
* When sleep_ideal_freq=0 this will have no effect. | |
*/ | |
-#define DEFAULT_SLEEP_WAKEUP_FREQ 99999999 | |
+#define DEFAULT_SLEEP_WAKEUP_FREQ 1008000 | |
static unsigned int sleep_wakeup_freq; | |
/* | |
@@ -864,4 +864,4 @@ module_exit(cpufreq_smartass_exit); | |
MODULE_AUTHOR ("Erasmux"); | |
MODULE_DESCRIPTION ("'cpufreq_smartass2' - A smart cpufreq governor"); | |
-MODULE_LICENSE ("GPL"); | |
+MODULE_LICENSE ("GPL"); | |
\ No newline at end of file | |
diff --git a/drivers/crypto/msm/qce.c b/drivers/crypto/msm/qce.c | |
index ec4f747..341de30 100644 | |
--- a/drivers/crypto/msm/qce.c | |
+++ b/drivers/crypto/msm/qce.c | |
@@ -1,6 +1,6 @@ | |
/* Qualcomm Crypto Engine driver. | |
* | |
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2010-2011, Code Aurora Forum. 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 and | |
@@ -479,19 +479,6 @@ static int count_sg(struct scatterlist *sg, int nbytes) | |
return i; | |
} | |
-static int dma_map_pmem_sg(struct buf_info *pmem, unsigned entries, | |
- struct scatterlist *sg) | |
-{ | |
- int i = 0; | |
- for (i = 0; i < entries; i++) { | |
- | |
- sg->dma_address = (dma_addr_t)pmem->offset; | |
- sg++; | |
- pmem++; | |
- } | |
- return 0; | |
-} | |
- | |
static int _probe_ce_engine(struct qce_device *pce_dev) | |
{ | |
unsigned int val; | |
@@ -1058,52 +1045,6 @@ static int _ablk_cipher_complete(struct qce_device *pce_dev) | |
return 0; | |
}; | |
-static int _ablk_cipher_use_pmem_complete(struct qce_device *pce_dev) | |
-{ | |
- struct ablkcipher_request *areq; | |
- uint32_t iv_out[4]; | |
- unsigned char iv[4 * sizeof(uint32_t)]; | |
- uint32_t status; | |
- | |
- areq = (struct ablkcipher_request *) pce_dev->areq; | |
- | |
- /* check ce error status */ | |
- status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG); | |
- if (status & (1 << CRYPTO_SW_ERR)) { | |
- pce_dev->err++; | |
- dev_err(pce_dev->pdev, | |
- "Qualcomm Crypto Error at 0x%x, status%x\n", | |
- pce_dev->phy_iobase, status); | |
- _init_ce_engine(pce_dev); | |
- clk_disable(pce_dev->ce_clk); | |
- pce_dev->qce_cb(areq, NULL, NULL, -ENXIO); | |
- return 0; | |
- }; | |
- | |
- /* get iv out */ | |
- if (pce_dev->mode == QCE_MODE_ECB) { | |
- clk_disable(pce_dev->ce_clk); | |
- pce_dev->qce_cb(areq, NULL, NULL, pce_dev->chan_ce_in_status | | |
- pce_dev->chan_ce_out_status); | |
- } else { | |
- iv_out[0] = readl_relaxed(pce_dev->iobase + | |
- CRYPTO_CNTR0_IV0_REG); | |
- iv_out[1] = readl_relaxed(pce_dev->iobase + | |
- CRYPTO_CNTR1_IV1_REG); | |
- iv_out[2] = readl_relaxed(pce_dev->iobase + | |
- CRYPTO_CNTR2_IV2_REG); | |
- iv_out[3] = readl_relaxed(pce_dev->iobase + | |
- CRYPTO_CNTR3_IV3_REG); | |
- | |
- _net_words_to_byte_stream(iv_out, iv, sizeof(iv)); | |
- clk_disable(pce_dev->ce_clk); | |
- pce_dev->qce_cb(areq, NULL, iv, pce_dev->chan_ce_in_status | | |
- pce_dev->chan_ce_out_status); | |
- } | |
- | |
- return 0; | |
-}; | |
- | |
static int qce_split_and_insert_dm_desc(struct dmov_desc *pdesc, | |
unsigned int plen, unsigned int paddr, int *index) | |
{ | |
@@ -1529,53 +1470,6 @@ static void _ablk_cipher_ce_out_call_back(struct msm_dmov_cmd *cmd_ptr, | |
}; | |
-static void _ablk_cipher_ce_in_call_back_pmem(struct msm_dmov_cmd *cmd_ptr, | |
- unsigned int result, struct msm_dmov_errdata *err) | |
-{ | |
- struct qce_device *pce_dev; | |
- | |
- pce_dev = (struct qce_device *) cmd_ptr->user; | |
- if (result != ADM_STATUS_OK) { | |
- dev_err(pce_dev->pdev, "Qualcomm ADM status error %x\n", | |
- result); | |
- pce_dev->chan_ce_in_status = -1; | |
- } else | |
- pce_dev->chan_ce_in_status = 0; | |
- | |
- pce_dev->chan_ce_in_state = QCE_CHAN_STATE_COMP; | |
- if (pce_dev->chan_ce_out_state == QCE_CHAN_STATE_COMP) { | |
- pce_dev->chan_ce_in_state = QCE_CHAN_STATE_IDLE; | |
- pce_dev->chan_ce_out_state = QCE_CHAN_STATE_IDLE; | |
- | |
- /* done */ | |
- _ablk_cipher_use_pmem_complete(pce_dev); | |
- } | |
-}; | |
- | |
-static void _ablk_cipher_ce_out_call_back_pmem(struct msm_dmov_cmd *cmd_ptr, | |
- unsigned int result, struct msm_dmov_errdata *err) | |
-{ | |
- struct qce_device *pce_dev; | |
- | |
- pce_dev = (struct qce_device *) cmd_ptr->user; | |
- if (result != ADM_STATUS_OK) { | |
- dev_err(pce_dev->pdev, "Qualcomm ADM status error %x\n", | |
- result); | |
- pce_dev->chan_ce_out_status = -1; | |
- } else { | |
- pce_dev->chan_ce_out_status = 0; | |
- }; | |
- | |
- pce_dev->chan_ce_out_state = QCE_CHAN_STATE_COMP; | |
- if (pce_dev->chan_ce_in_state == QCE_CHAN_STATE_COMP) { | |
- pce_dev->chan_ce_in_state = QCE_CHAN_STATE_IDLE; | |
- pce_dev->chan_ce_out_state = QCE_CHAN_STATE_IDLE; | |
- | |
- /* done */ | |
- _ablk_cipher_use_pmem_complete(pce_dev); | |
- } | |
-}; | |
- | |
static int _setup_cmd_template(struct qce_device *pce_dev) | |
{ | |
dmov_sg *pcmd; | |
@@ -2157,13 +2051,9 @@ int qce_ablk_cipher_req(void *handle, struct qce_req *c_req) | |
/* cipher input */ | |
pce_dev->src_nents = count_sg(areq->src, areq->nbytes); | |
- if (c_req->use_pmem != 1) | |
- dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents, | |
+ qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents, | |
(areq->src == areq->dst) ? DMA_BIDIRECTIONAL : | |
DMA_TO_DEVICE); | |
- else | |
- dma_map_pmem_sg(&c_req->pmem->src[0], pce_dev->src_nents, | |
- areq->src); | |
if (_chain_sg_buffer_in(pce_dev, areq->src, areq->nbytes) < 0) { | |
rc = -ENOMEM; | |
@@ -2173,12 +2063,8 @@ int qce_ablk_cipher_req(void *handle, struct qce_req *c_req) | |
/* cipher output */ | |
if (areq->src != areq->dst) { | |
pce_dev->dst_nents = count_sg(areq->dst, areq->nbytes); | |
- if (c_req->use_pmem != 1) | |
- dma_map_sg(pce_dev->pdev, areq->dst, pce_dev->dst_nents, | |
+ qce_dma_map_sg(pce_dev->pdev, areq->dst, | |
DMA_FROM_DEVICE); | |
- else | |
- dma_map_pmem_sg(&c_req->pmem->dst[0], | |
- pce_dev->dst_nents, areq->dst); | |
}; | |
if (_chain_sg_buffer_out(pce_dev, areq->dst, areq->nbytes) < 0) { | |
rc = -ENOMEM; | |
@@ -2215,34 +2101,25 @@ int qce_ablk_cipher_req(void *handle, struct qce_req *c_req) | |
/* setup for callback, and issue command to adm */ | |
pce_dev->areq = areq; | |
pce_dev->qce_cb = c_req->qce_cb; | |
- if (c_req->use_pmem == 1) { | |
- pce_dev->chan_ce_in_cmd->complete_func = | |
- _ablk_cipher_ce_in_call_back_pmem; | |
- pce_dev->chan_ce_out_cmd->complete_func = | |
- _ablk_cipher_ce_out_call_back_pmem; | |
- } else { | |
- pce_dev->chan_ce_in_cmd->complete_func = | |
+ pce_dev->chan_ce_in_cmd->complete_func = | |
_ablk_cipher_ce_in_call_back; | |
- pce_dev->chan_ce_out_cmd->complete_func = | |
+ pce_dev->chan_ce_out_cmd->complete_func = | |
_ablk_cipher_ce_out_call_back; | |
- } | |
rc = _qce_start_dma(pce_dev, true, true); | |
if (rc == 0) | |
return 0; | |
bad: | |
- if (c_req->use_pmem != 1) { | |
- if (pce_dev->dst_nents) { | |
- dma_unmap_sg(pce_dev->pdev, areq->dst, | |
- pce_dev->dst_nents, DMA_FROM_DEVICE); | |
- } | |
- if (pce_dev->src_nents) { | |
- dma_unmap_sg(pce_dev->pdev, areq->src, | |
- pce_dev->src_nents, | |
- (areq->src == areq->dst) ? | |
- DMA_BIDIRECTIONAL : | |
- DMA_TO_DEVICE); | |
- } | |
+ if (pce_dev->dst_nents) { | |
+ qce_dma_unmap_sg(pce_dev->pdev, areq->dst, | |
+ pce_dev->dst_nents, DMA_FROM_DEVICE); | |
+ } | |
+ if (pce_dev->src_nents) { | |
+ qce_dma_unmap_sg(pce_dev->pdev, areq->src, | |
+ pce_dev->src_nents, | |
+ (areq->src == areq->dst) ? | |
+ DMA_BIDIRECTIONAL : | |
+ DMA_TO_DEVICE); | |
} | |
return rc; | |
} | |
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c | |
index a105058..1bb3e59 100644 | |
--- a/drivers/crypto/msm/qcedev.c | |
+++ b/drivers/crypto/msm/qcedev.c | |
@@ -1,6 +1,6 @@ | |
/* Qualcomm CE device driver. | |
* | |
- * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
@@ -12,7 +12,7 @@ | |
* GNU General Public License for more details. | |
*/ | |
#include <linux/mman.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <linux/types.h> | |
#include <linux/platform_device.h> | |
#include <linux/dma-mapping.h> | |
@@ -454,14 +454,12 @@ static int start_cipher_req(struct qcedev_control *podev) | |
/* start the command on the podev->active_command */ | |
qcedev_areq = podev->active_command; | |
- | |
qcedev_areq->cipher_req.cookie = qcedev_areq->handle; | |
- creq.use_pmem = qcedev_areq->cipher_op_req.use_pmem; | |
- if (qcedev_areq->cipher_op_req.use_pmem == QCEDEV_USE_PMEM) | |
- creq.pmem = &qcedev_areq->cipher_op_req.pmem; | |
- else | |
- creq.pmem = NULL; | |
- | |
+ if (qcedev_areq->cipher_op_req.use_pmem == QCEDEV_USE_PMEM) { | |
+ pr_err("%s: Use of PMEM is not supported\n", __func__); | |
+ goto unsupported; | |
+ } | |
+ creq.pmem = NULL; | |
switch (qcedev_areq->cipher_op_req.alg) { | |
case QCEDEV_ALG_DES: | |
creq.alg = CIPHER_ALG_DES; | |
@@ -1263,224 +1261,6 @@ static int qcedev_hash_final(struct qcedev_async_req *areq, | |
return qcedev_hmac_final(areq, handle); | |
} | |
-#ifdef CONFIG_ANDROID_PMEM | |
-static int qcedev_pmem_ablk_cipher_max_xfer(struct qcedev_async_req *areq, | |
- struct qcedev_handle *handle) | |
-{ | |
- int i = 0; | |
- int err = 0; | |
- struct scatterlist *sg_src = NULL; | |
- struct scatterlist *sg_dst = NULL; | |
- struct scatterlist *sg_ndex = NULL; | |
- struct file *file_src = NULL; | |
- struct file *file_dst = NULL; | |
- unsigned long paddr; | |
- unsigned long kvaddr; | |
- unsigned long len; | |
- | |
- sg_src = kmalloc((sizeof(struct scatterlist) * | |
- areq->cipher_op_req.entries), GFP_KERNEL); | |
- if (sg_src == NULL) { | |
- pr_err("%s: Can't Allocate memory:sg_src 0x%x\n", | |
- __func__, (uint32_t)sg_src); | |
- return -ENOMEM; | |
- | |
- } | |
- memset(sg_src, 0, (sizeof(struct scatterlist) * | |
- areq->cipher_op_req.entries)); | |
- sg_ndex = sg_src; | |
- areq->cipher_req.creq.src = sg_src; | |
- | |
- /* address src */ | |
- get_pmem_file(areq->cipher_op_req.pmem.fd_src, &paddr, | |
- &kvaddr, &len, &file_src); | |
- | |
- for (i = 0; i < areq->cipher_op_req.entries; i++) { | |
- sg_set_buf(sg_ndex, | |
- ((uint8_t *)(areq->cipher_op_req.pmem.src[i].offset) + kvaddr), | |
- areq->cipher_op_req.pmem.src[i].len); | |
- sg_ndex++; | |
- } | |
- sg_mark_end(--sg_ndex); | |
- | |
- for (i = 0; i < areq->cipher_op_req.entries; i++) | |
- areq->cipher_op_req.pmem.src[i].offset += (uint32_t)paddr; | |
- | |
- /* address dst */ | |
- /* If not place encryption/decryption */ | |
- if (areq->cipher_op_req.in_place_op != 1) { | |
- sg_dst = kmalloc((sizeof(struct scatterlist) * | |
- areq->cipher_op_req.entries), GFP_KERNEL); | |
- if (sg_dst == NULL) { | |
- pr_err("%s: Can't Allocate memory: sg_dst 0x%x\n", | |
- __func__, (uint32_t)sg_dst); | |
- return -ENOMEM; | |
- } | |
- memset(sg_dst, 0, (sizeof(struct scatterlist) * | |
- areq->cipher_op_req.entries)); | |
- areq->cipher_req.creq.dst = sg_dst; | |
- sg_ndex = sg_dst; | |
- | |
- get_pmem_file(areq->cipher_op_req.pmem.fd_dst, &paddr, | |
- &kvaddr, &len, &file_dst); | |
- for (i = 0; i < areq->cipher_op_req.entries; i++) | |
- sg_set_buf(sg_ndex++, | |
- ((uint8_t *)(areq->cipher_op_req.pmem.dst[i].offset) | |
- + kvaddr), areq->cipher_op_req.pmem.dst[i].len); | |
- sg_mark_end(--sg_ndex); | |
- | |
- for (i = 0; i < areq->cipher_op_req.entries; i++) | |
- areq->cipher_op_req.pmem.dst[i].offset += | |
- (uint32_t)paddr; | |
- } else { | |
- areq->cipher_req.creq.dst = sg_src; | |
- for (i = 0; i < areq->cipher_op_req.entries; i++) { | |
- areq->cipher_op_req.pmem.dst[i].offset = | |
- areq->cipher_op_req.pmem.src[i].offset; | |
- areq->cipher_op_req.pmem.dst[i].len = | |
- areq->cipher_op_req.pmem.src[i].len; | |
- } | |
- } | |
- | |
- areq->cipher_req.creq.nbytes = areq->cipher_op_req.data_len; | |
- areq->cipher_req.creq.info = areq->cipher_op_req.iv; | |
- | |
- err = submit_req(areq, handle); | |
- | |
- kfree(sg_src); | |
- kfree(sg_dst); | |
- | |
- if (file_dst) | |
- put_pmem_file(file_dst); | |
- if (file_src) | |
- put_pmem_file(file_src); | |
- | |
- return err; | |
-}; | |
- | |
- | |
-static int qcedev_pmem_ablk_cipher(struct qcedev_async_req *qcedev_areq, | |
- struct qcedev_handle *handle) | |
-{ | |
- int err = 0; | |
- int i = 0; | |
- int j = 0; | |
- int k = 0; | |
- int num_entries = 0; | |
- uint32_t total = 0; | |
- struct qcedev_cipher_op_req *saved_req; | |
- struct qcedev_cipher_op_req *creq = &qcedev_areq->cipher_op_req; | |
- | |
- saved_req = kmalloc(sizeof(struct qcedev_cipher_op_req), GFP_KERNEL); | |
- if (saved_req == NULL) { | |
- pr_err(KERN_ERR "%s:Can't Allocate mem:saved_req 0x%x\n", | |
- __func__, (uint32_t)saved_req); | |
- return -ENOMEM; | |
- } | |
- memcpy(saved_req, creq, sizeof(struct qcedev_cipher_op_req)); | |
- | |
- if (qcedev_areq->cipher_op_req.data_len > QCE_MAX_OPER_DATA) { | |
- | |
- struct qcedev_cipher_op_req req; | |
- | |
- /* save the original req structure */ | |
- memcpy(&req, creq, sizeof(struct qcedev_cipher_op_req)); | |
- | |
- i = 0; | |
- /* Address 32 KB at a time */ | |
- while ((i < req.entries) && (err == 0)) { | |
- if (creq->pmem.src[i].len > QCE_MAX_OPER_DATA) { | |
- creq->pmem.src[0].len = QCE_MAX_OPER_DATA; | |
- if (i > 0) { | |
- creq->pmem.src[0].offset = | |
- creq->pmem.src[i].offset; | |
- } | |
- | |
- creq->data_len = QCE_MAX_OPER_DATA; | |
- creq->entries = 1; | |
- | |
- err = | |
- qcedev_pmem_ablk_cipher_max_xfer(qcedev_areq, | |
- handle); | |
- | |
- creq->pmem.src[i].len = req.pmem.src[i].len - | |
- QCE_MAX_OPER_DATA; | |
- creq->pmem.src[i].offset = | |
- req.pmem.src[i].offset + | |
- QCE_MAX_OPER_DATA; | |
- req.pmem.src[i].offset = | |
- creq->pmem.src[i].offset; | |
- req.pmem.src[i].len = creq->pmem.src[i].len; | |
- } else { | |
- total = 0; | |
- for (j = i; j < req.entries; j++) { | |
- num_entries++; | |
- if ((total + creq->pmem.src[j].len) | |
- >= QCE_MAX_OPER_DATA) { | |
- creq->pmem.src[j].len = | |
- QCE_MAX_OPER_DATA - total; | |
- total = QCE_MAX_OPER_DATA; | |
- break; | |
- } | |
- total += creq->pmem.src[j].len; | |
- } | |
- | |
- creq->data_len = total; | |
- if (i > 0) | |
- for (k = 0; k < num_entries; k++) { | |
- creq->pmem.src[k].len = | |
- creq->pmem.src[i+k].len; | |
- creq->pmem.src[k].offset = | |
- creq->pmem.src[i+k].offset; | |
- } | |
- creq->entries = num_entries; | |
- | |
- i = j; | |
- err = | |
- qcedev_pmem_ablk_cipher_max_xfer(qcedev_areq, | |
- handle); | |
- num_entries = 0; | |
- | |
- creq->pmem.src[i].offset = | |
- req.pmem.src[i].offset + | |
- creq->pmem.src[i].len; | |
- creq->pmem.src[i].len = | |
- req.pmem.src[i].len - | |
- creq->pmem.src[i].len; | |
- req.pmem.src[i].offset = | |
- creq->pmem.src[i].offset; | |
- req.pmem.src[i].len = | |
- creq->pmem.src[i].len; | |
- | |
- if (creq->pmem.src[i].len == 0) | |
- i++; | |
- } | |
- | |
- } /* end of while ((i < req.entries) && (err == 0)) */ | |
- | |
- } else | |
- err = qcedev_pmem_ablk_cipher_max_xfer(qcedev_areq, handle); | |
- | |
- /* Restore the original req structure */ | |
- for (i = 0; i < saved_req->entries; i++) { | |
- creq->pmem.src[i].len = saved_req->pmem.src[i].len; | |
- creq->pmem.src[i].offset = saved_req->pmem.src[i].offset; | |
- } | |
- creq->entries = saved_req->entries; | |
- creq->data_len = saved_req->data_len; | |
- kfree(saved_req); | |
- | |
- return err; | |
- | |
-} | |
-#else | |
-static int qcedev_pmem_ablk_cipher(struct qcedev_async_req *qcedev_areq, | |
- struct qcedev_handle *handle) | |
-{ | |
- return -EPERM; | |
-} | |
-#endif/*CONFIG_ANDROID_PMEM*/ | |
- | |
static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq, | |
int *di, struct qcedev_handle *handle, | |
uint8_t *k_align_src) | |
@@ -1742,6 +1522,10 @@ static int qcedev_vbuf_ablk_cipher(struct qcedev_async_req *areq, | |
static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, | |
struct qcedev_control *podev) | |
{ | |
+ if (req->use_pmem) { | |
+ pr_err("%s: Use of PMEM is not supported\n", __func__); | |
+ goto error; | |
+ } | |
if ((req->entries == 0) || (req->data_len == 0)) | |
goto error; | |
if ((req->alg >= QCEDEV_ALG_LAST) || | |
@@ -1781,15 +1565,6 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req, | |
if (req->byteoffset) { | |
if (req->mode != QCEDEV_AES_MODE_CTR) | |
goto error; | |
- else { /* if using CTR mode make sure not using Pmem */ | |
- if (req->use_pmem) | |
- goto error; | |
- } | |
- } | |
- /* if using PMEM with non-zero byteoffset, ensure it is in_place_op */ | |
- if (req->use_pmem) { | |
- if (!req->in_place_op) | |
- goto error; | |
} | |
/* Ensure zer ivlen for ECB mode */ | |
if (req->ivlen != 0) { | |
@@ -1879,10 +1654,7 @@ static long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |
podev)) | |
return -EINVAL; | |
- if (qcedev_areq.cipher_op_req.use_pmem) | |
- err = qcedev_pmem_ablk_cipher(&qcedev_areq, handle); | |
- else | |
- err = qcedev_vbuf_ablk_cipher(&qcedev_areq, handle); | |
+ err = qcedev_vbuf_ablk_cipher(&qcedev_areq, handle); | |
if (err) | |
return err; | |
if (__copy_to_user((void __user *)arg, | |
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c | |
index 3f9fe54..20d9d2f 100644 | |
--- a/drivers/gpu/ion/ion_carveout_heap.c | |
+++ b/drivers/gpu/ion/ion_carveout_heap.c | |
@@ -23,7 +23,6 @@ | |
#include <linux/mm.h> | |
#include <linux/scatterlist.h> | |
#include <linux/slab.h> | |
-#include <linux/vmalloc.h> | |
#include <linux/iommu.h> | |
#include <linux/seq_file.h> | |
#include "ion_priv.h" | |
@@ -240,25 +239,78 @@ int ion_carveout_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer, | |
void *vaddr, unsigned int offset, unsigned int length, | |
unsigned int cmd) | |
{ | |
- void (*outer_cache_op)(phys_addr_t, phys_addr_t); | |
+ void (*outer_cache_op)(phys_addr_t, phys_addr_t) = NULL; | |
struct ion_carveout_heap *carveout_heap = | |
container_of(heap, struct ion_carveout_heap, heap); | |
- | |
- switch (cmd) { | |
- case ION_IOC_CLEAN_CACHES: | |
- dmac_clean_range(vaddr, vaddr + length); | |
- outer_cache_op = outer_clean_range; | |
- break; | |
- case ION_IOC_INV_CACHES: | |
- dmac_inv_range(vaddr, vaddr + length); | |
- outer_cache_op = outer_inv_range; | |
- break; | |
- case ION_IOC_CLEAN_INV_CACHES: | |
- dmac_flush_range(vaddr, vaddr + length); | |
- outer_cache_op = outer_flush_range; | |
- break; | |
- default: | |
- return -EINVAL; | |
+ unsigned int size_to_vmap, total_size; | |
+ int i, j; | |
+ void *ptr = NULL; | |
+ ion_phys_addr_t buff_phys = buffer->priv_phys; | |
+ | |
+ if (!vaddr) { | |
+ /* | |
+ * Split the vmalloc space into smaller regions in | |
+ * order to clean and/or invalidate the cache. | |
+ */ | |
+ size_to_vmap = ((VMALLOC_END - VMALLOC_START)/8); | |
+ total_size = buffer->size; | |
+ | |
+ for (i = 0; i < total_size; i += size_to_vmap) { | |
+ size_to_vmap = min(size_to_vmap, total_size - i); | |
+ for (j = 0; j < 10 && size_to_vmap; ++j) { | |
+ ptr = ioremap(buff_phys, size_to_vmap); | |
+ if (ptr) { | |
+ switch (cmd) { | |
+ case ION_IOC_CLEAN_CACHES: | |
+ dmac_clean_range(ptr, | |
+ ptr + size_to_vmap); | |
+ outer_cache_op = | |
+ outer_clean_range; | |
+ break; | |
+ case ION_IOC_INV_CACHES: | |
+ dmac_inv_range(ptr, | |
+ ptr + size_to_vmap); | |
+ outer_cache_op = | |
+ outer_inv_range; | |
+ break; | |
+ case ION_IOC_CLEAN_INV_CACHES: | |
+ dmac_flush_range(ptr, | |
+ ptr + size_to_vmap); | |
+ outer_cache_op = | |
+ outer_flush_range; | |
+ break; | |
+ default: | |
+ return -EINVAL; | |
+ } | |
+ buff_phys += size_to_vmap; | |
+ break; | |
+ } else { | |
+ size_to_vmap >>= 1; | |
+ } | |
+ } | |
+ if (!ptr) { | |
+ pr_err("Couldn't io-remap the memory\n"); | |
+ return -EINVAL; | |
+ } | |
+ iounmap(ptr); | |
+ } | |
+ } else { | |
+ switch (cmd) { | |
+ case ION_IOC_CLEAN_CACHES: | |
+ dmac_clean_range(vaddr, vaddr + length); | |
+ outer_cache_op = outer_clean_range; | |
+ break; | |
+ case ION_IOC_INV_CACHES: | |
+ dmac_inv_range(vaddr, vaddr + length); | |
+ outer_cache_op = outer_inv_range; | |
+ break; | |
+ case ION_IOC_CLEAN_INV_CACHES: | |
+ dmac_flush_range(vaddr, vaddr + length); | |
+ outer_cache_op = outer_flush_range; | |
+ break; | |
+ default: | |
+ return -EINVAL; | |
+ } | |
} | |
if (carveout_heap->has_outer_cache) { | |
@@ -357,7 +409,7 @@ int ion_carveout_heap_map_iommu(struct ion_buffer *buffer, | |
goto out1; | |
} | |
- sglist = vmalloc(sizeof(*sglist)); | |
+ sglist = kmalloc(sizeof(*sglist), GFP_KERNEL); | |
if (!sglist) | |
goto out1; | |
@@ -381,13 +433,13 @@ int ion_carveout_heap_map_iommu(struct ion_buffer *buffer, | |
if (ret) | |
goto out2; | |
} | |
- vfree(sglist); | |
+ kfree(sglist); | |
return ret; | |
out2: | |
iommu_unmap_range(domain, data->iova_addr, buffer->size); | |
out1: | |
- vfree(sglist); | |
+ kfree(sglist); | |
msm_free_iova_address(data->iova_addr, domain_num, partition_num, | |
data->mapped_size); | |
diff --git a/drivers/gpu/ion/ion_cma_heap.c b/drivers/gpu/ion/ion_cma_heap.c | |
index 2783afa..cbe4483 100644 | |
--- a/drivers/gpu/ion/ion_cma_heap.c | |
+++ b/drivers/gpu/ion/ion_cma_heap.c | |
@@ -21,6 +21,7 @@ | |
#include <linux/errno.h> | |
#include <linux/err.h> | |
#include <linux/dma-mapping.h> | |
+#include <linux/msm_ion.h> | |
#include <mach/iommu_domains.h> | |
#include <asm/cacheflush.h> | |
@@ -34,6 +35,7 @@ struct ion_cma_buffer_info { | |
void *cpu_addr; | |
dma_addr_t handle; | |
struct sg_table *table; | |
+ bool is_cached; | |
}; | |
static int cma_heap_has_outer_cache; | |
@@ -72,7 +74,12 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, | |
return ION_CMA_ALLOCATE_FAILED; | |
} | |
- info->cpu_addr = dma_alloc_writecombine(dev, len, &(info->handle), 0); | |
+ if (!ION_IS_CACHED(flags)) | |
+ info->cpu_addr = dma_alloc_writecombine(dev, len, | |
+ &(info->handle), 0); | |
+ else | |
+ info->cpu_addr = dma_alloc_nonconsistent(dev, len, | |
+ &(info->handle), 0); | |
if (!info->cpu_addr) { | |
dev_err(dev, "Fail to allocate buffer\n"); | |
@@ -85,6 +92,8 @@ static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer *buffer, | |
goto err; | |
} | |
+ info->is_cached = ION_IS_CACHED(flags); | |
+ | |
ion_cma_get_sgtable(dev, | |
info->table, info->cpu_addr, info->handle, len); | |
@@ -106,6 +115,7 @@ static void ion_cma_free(struct ion_buffer *buffer) | |
dev_dbg(dev, "Release buffer %p\n", buffer); | |
/* release memory */ | |
dma_free_coherent(dev, buffer->size, info->cpu_addr, info->handle); | |
+ sg_free_table(info->table); | |
/* release sg table */ | |
kfree(info->table); | |
kfree(info); | |
@@ -147,8 +157,12 @@ static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer, | |
struct device *dev = buffer->heap->priv; | |
struct ion_cma_buffer_info *info = buffer->priv_virt; | |
- return dma_mmap_writecombine(dev, vma, info->cpu_addr, info->handle, | |
- buffer->size); | |
+ if (info->is_cached) | |
+ return dma_mmap_nonconsistent(dev, vma, info->cpu_addr, | |
+ info->handle, buffer->size); | |
+ else | |
+ return dma_mmap_writecombine(dev, vma, info->cpu_addr, | |
+ info->handle, buffer->size); | |
} | |
static void *ion_cma_map_kernel(struct ion_heap *heap, | |
@@ -165,7 +179,6 @@ static void ion_cma_unmap_kernel(struct ion_heap *heap, | |
return; | |
} | |
- | |
int ion_cma_map_iommu(struct ion_buffer *buffer, | |
struct ion_iommu_map *data, | |
unsigned int domain_num, | |
@@ -182,13 +195,13 @@ int ion_cma_map_iommu(struct ion_buffer *buffer, | |
struct sg_table *table = info->table; | |
int prot = IOMMU_WRITE | IOMMU_READ; | |
+ data->mapped_size = iova_length; | |
+ | |
if (!msm_use_iommu()) { | |
data->iova_addr = info->handle; | |
- data->mapped_size = iova_length; | |
return 0; | |
} | |
- data->mapped_size = iova_length; | |
extra = iova_length - buffer->size; | |
ret = msm_allocate_iova_address(domain_num, partition_num, | |
@@ -268,15 +281,30 @@ int ion_cma_cache_ops(struct ion_heap *heap, | |
switch (cmd) { | |
case ION_IOC_CLEAN_CACHES: | |
- dmac_clean_range(vaddr, vaddr + length); | |
+ if (!vaddr) | |
+ dma_sync_sg_for_device(NULL, buffer->sg_table->sgl, | |
+ buffer->sg_table->nents, DMA_TO_DEVICE); | |
+ else | |
+ dmac_clean_range(vaddr, vaddr + length); | |
outer_cache_op = outer_clean_range; | |
break; | |
case ION_IOC_INV_CACHES: | |
- dmac_inv_range(vaddr, vaddr + length); | |
+ if (!vaddr) | |
+ dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl, | |
+ buffer->sg_table->nents, DMA_FROM_DEVICE); | |
+ else | |
+ dmac_inv_range(vaddr, vaddr + length); | |
outer_cache_op = outer_inv_range; | |
break; | |
case ION_IOC_CLEAN_INV_CACHES: | |
- dmac_flush_range(vaddr, vaddr + length); | |
+ if (!vaddr) { | |
+ dma_sync_sg_for_device(NULL, buffer->sg_table->sgl, | |
+ buffer->sg_table->nents, DMA_TO_DEVICE); | |
+ dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl, | |
+ buffer->sg_table->nents, DMA_FROM_DEVICE); | |
+ } else { | |
+ dmac_flush_range(vaddr, vaddr + length); | |
+ } | |
outer_cache_op = outer_flush_range; | |
break; | |
default: | |
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c | |
index 84ad9b0..2598144 100644 | |
--- a/drivers/gpu/ion/ion_cp_heap.c | |
+++ b/drivers/gpu/ion/ion_cp_heap.c | |
@@ -2,7 +2,7 @@ | |
* drivers/gpu/ion/ion_cp_heap.c | |
* | |
* Copyright (C) 2011 Google, Inc. | |
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. | |
* | |
* This software is licensed under the terms of the GNU General Public | |
* License version 2, as published by the Free Software Foundation, and | |
@@ -15,20 +15,16 @@ | |
* | |
*/ | |
#include <linux/spinlock.h> | |
-#include <linux/delay.h> | |
+ | |
#include <linux/err.h> | |
#include <linux/genalloc.h> | |
#include <linux/io.h> | |
-#include <linux/ion.h> | |
#include <linux/mm.h> | |
#include <linux/scatterlist.h> | |
#include <linux/slab.h> | |
-#include <linux/vmalloc.h> | |
#include <linux/memory_alloc.h> | |
#include <linux/seq_file.h> | |
-#include <linux/fmem.h> | |
#include <linux/iommu.h> | |
-#include <linux/dma-mapping.h> | |
#include <asm/mach/map.h> | |
@@ -69,8 +65,6 @@ | |
* user space. | |
* @iommu_iova: saved iova when mapping full heap at once. | |
* @iommu_partition: partition used to map full heap. | |
- * @reusable: indicates if the memory should be reused via fmem. | |
- * @reserved_vrange: reserved virtual address range for use with fmem | |
* @iommu_map_all: Indicates whether we should map whole heap into IOMMU. | |
* @iommu_2x_map_domain: Indicates the domain to use for overmapping. | |
* @has_outer_cache: set to 1 if outer cache is used, 0 otherwise. | |
@@ -94,16 +88,11 @@ struct ion_cp_heap { | |
unsigned long umap_count; | |
unsigned long iommu_iova[MAX_DOMAINS]; | |
unsigned long iommu_partition[MAX_DOMAINS]; | |
- int reusable; | |
- void *reserved_vrange; | |
int iommu_map_all; | |
int iommu_2x_map_domain; | |
unsigned int has_outer_cache; | |
atomic_t protect_cnt; | |
- void *cpu_addr; | |
- size_t heap_size; | |
- dma_addr_t handle; | |
- int cma; | |
+ int disallow_non_secure_allocation; | |
}; | |
enum { | |
@@ -119,68 +108,6 @@ static int ion_cp_unprotect_mem(unsigned int phy_base, unsigned int size, | |
unsigned int permission_type, int version, | |
void *data); | |
-static int allocate_heap_memory(struct ion_heap *heap) | |
-{ | |
- struct device *dev = heap->priv; | |
- struct ion_cp_heap *cp_heap = | |
- container_of(heap, struct ion_cp_heap, heap); | |
- int ret; | |
- int tries = 0; | |
- | |
- | |
- if (cp_heap->cpu_addr) | |
- return 0; | |
- | |
- while (!cp_heap->cpu_addr && (++tries < 500)) { | |
- cp_heap->cpu_addr = dma_alloc_writecombine(dev, | |
- cp_heap->heap_size, | |
- &(cp_heap->handle), | |
- 0); | |
- if (!cp_heap->cpu_addr) | |
- msleep(20); | |
- } | |
- | |
- if (!cp_heap->cpu_addr) | |
- goto out; | |
- | |
- cp_heap->base = cp_heap->handle; | |
- | |
- cp_heap->pool = gen_pool_create(12, -1); | |
- if (!cp_heap->pool) | |
- goto out_free; | |
- | |
- ret = gen_pool_add(cp_heap->pool, cp_heap->base, | |
- cp_heap->heap_size, -1); | |
- if (ret < 0) | |
- goto out_pool; | |
- | |
- return 0; | |
- | |
-out_pool: | |
- gen_pool_destroy(cp_heap->pool); | |
-out_free: | |
- dma_free_coherent(dev, cp_heap->heap_size, cp_heap->cpu_addr, | |
- cp_heap->handle); | |
-out: | |
- return ION_CP_ALLOCATE_FAIL; | |
-} | |
- | |
-static void free_heap_memory(struct ion_heap *heap) | |
-{ | |
- struct device *dev = heap->priv; | |
- struct ion_cp_heap *cp_heap = | |
- container_of(heap, struct ion_cp_heap, heap); | |
- | |
- /* release memory */ | |
- dma_free_coherent(dev, cp_heap->heap_size, cp_heap->cpu_addr, | |
- cp_heap->handle); | |
- gen_pool_destroy(cp_heap->pool); | |
- cp_heap->pool = NULL; | |
- cp_heap->cpu_addr = 0; | |
-} | |
- | |
- | |
- | |
/** | |
* Get the total number of kernel mappings. | |
* Must be called with heap->lock locked. | |
@@ -193,41 +120,16 @@ static unsigned long ion_cp_get_total_kmap_count( | |
static int ion_on_first_alloc(struct ion_heap *heap) | |
{ | |
- struct ion_cp_heap *cp_heap = | |
- container_of(heap, struct ion_cp_heap, heap); | |
- int ret_value; | |
- | |
- if (cp_heap->reusable) { | |
- ret_value = fmem_set_state(FMEM_C_STATE); | |
- if (ret_value) | |
- return 1; | |
- } | |
- | |
- if (cp_heap->cma) { | |
- ret_value = allocate_heap_memory(heap); | |
- if (ret_value) | |
- return 1; | |
- } | |
return 0; | |
} | |
static void ion_on_last_free(struct ion_heap *heap) | |
{ | |
- struct ion_cp_heap *cp_heap = | |
- container_of(heap, struct ion_cp_heap, heap); | |
- | |
- if (cp_heap->reusable) | |
- if (fmem_set_state(FMEM_T_STATE) != 0) | |
- pr_err("%s: unable to transition heap to T-state\n", | |
- __func__); | |
- | |
- if (cp_heap->cma) | |
- free_heap_memory(heap); | |
} | |
+ | |
/** | |
- * Protects memory if heap is unsecured heap. Also ensures that we are in | |
- * the correct FMEM state if this heap is a reusable heap. | |
+ * Protects memory if heap is unsecured heap. | |
* Must be called with heap->lock locked. | |
*/ | |
static int ion_cp_protect(struct ion_heap *heap, int version, void *data) | |
@@ -238,9 +140,13 @@ static int ion_cp_protect(struct ion_heap *heap, int version, void *data) | |
if (atomic_inc_return(&cp_heap->protect_cnt) == 1) { | |
/* Make sure we are in C state when the heap is protected. */ | |
- if (!cp_heap->allocated_bytes) | |
- if (ion_on_first_alloc(heap)) | |
+ if (!cp_heap->allocated_bytes) { | |
+ ret_value = ion_on_first_alloc(heap); | |
+ if (ret_value) { | |
+ atomic_dec(&cp_heap->protect_cnt); | |
goto out; | |
+ } | |
+ } | |
ret_value = ion_cp_protect_mem(cp_heap->secure_base, | |
cp_heap->secure_size, cp_heap->permission_type, | |
@@ -262,13 +168,12 @@ static int ion_cp_protect(struct ion_heap *heap, int version, void *data) | |
out: | |
pr_debug("%s: protect count is %d\n", __func__, | |
atomic_read(&cp_heap->protect_cnt)); | |
- WARN_ON(atomic_read(&cp_heap->protect_cnt) < 0); | |
+ BUG_ON(atomic_read(&cp_heap->protect_cnt) < 0); | |
return ret_value; | |
} | |
/** | |
- * Unprotects memory if heap is secure heap. Also ensures that we are in | |
- * the correct FMEM state if this heap is a reusable heap. | |
+ * Unprotects memory if heap is secure heap. | |
* Must be called with heap->lock locked. | |
*/ | |
static void ion_cp_unprotect(struct ion_heap *heap, int version, void *data) | |
@@ -294,7 +199,7 @@ static void ion_cp_unprotect(struct ion_heap *heap, int version, void *data) | |
} | |
pr_debug("%s: protect count is %d\n", __func__, | |
atomic_read(&cp_heap->protect_cnt)); | |
- WARN_ON(atomic_read(&cp_heap->protect_cnt) < 0); | |
+ BUG_ON(atomic_read(&cp_heap->protect_cnt) < 0); | |
} | |
ion_phys_addr_t ion_cp_allocate(struct ion_heap *heap, | |
@@ -304,6 +209,7 @@ ion_phys_addr_t ion_cp_allocate(struct ion_heap *heap, | |
{ | |
unsigned long offset; | |
unsigned long secure_allocation = flags & ION_SECURE; | |
+ unsigned long force_contig = flags & ION_FORCE_CONTIGUOUS; | |
struct ion_cp_heap *cp_heap = | |
container_of(heap, struct ion_cp_heap, heap); | |
@@ -316,6 +222,14 @@ ion_phys_addr_t ion_cp_allocate(struct ion_heap *heap, | |
return ION_CP_ALLOCATE_FAIL; | |
} | |
+ if (!force_contig && !secure_allocation && | |
+ cp_heap->disallow_non_secure_allocation) { | |
+ mutex_unlock(&cp_heap->lock); | |
+ pr_debug("%s: non-secure allocation disallowed from this heap\n", | |
+ __func__); | |
+ return ION_CP_ALLOCATE_FAIL; | |
+ } | |
+ | |
if (secure_allocation && | |
(cp_heap->umap_count > 0 || cp_heap->kmap_cached_count > 0)) { | |
mutex_unlock(&cp_heap->lock); | |
@@ -500,7 +414,6 @@ static int ion_cp_request_region(struct ion_cp_heap *cp_heap) | |
if (cp_heap->heap_request_region) | |
ret_value = cp_heap->heap_request_region( | |
cp_heap->bus_id); | |
- | |
return ret_value; | |
} | |
@@ -517,34 +430,11 @@ static int ion_cp_release_region(struct ion_cp_heap *cp_heap) | |
return ret_value; | |
} | |
-void *ion_map_fmem_buffer(struct ion_buffer *buffer, unsigned long phys_base, | |
- void *virt_base, unsigned long flags) | |
-{ | |
- int ret; | |
- unsigned int offset = buffer->priv_phys - phys_base; | |
- unsigned long start = ((unsigned long)virt_base) + offset; | |
- const struct mem_type *type = ION_IS_CACHED(flags) ? | |
- get_mem_type(MT_DEVICE_CACHED) : | |
- get_mem_type(MT_DEVICE); | |
- | |
- if (phys_base > buffer->priv_phys) | |
- return NULL; | |
- | |
- | |
- ret = ioremap_pages(start, buffer->priv_phys, buffer->size, type); | |
- | |
- if (!ret) | |
- return (void *)start; | |
- else | |
- return NULL; | |
-} | |
- | |
void *ion_cp_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer) | |
{ | |
struct ion_cp_heap *cp_heap = | |
container_of(heap, struct ion_cp_heap, heap); | |
void *ret_value = NULL; | |
- unsigned long start_phys = cp_heap->base; | |
mutex_lock(&cp_heap->lock); | |
if ((cp_heap->heap_protected == HEAP_NOT_PROTECTED) || | |
@@ -556,20 +446,12 @@ void *ion_cp_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer) | |
return NULL; | |
} | |
- if (cp_heap->reusable) { | |
- ret_value = ion_map_fmem_buffer(buffer, cp_heap->base, | |
- cp_heap->reserved_vrange, buffer->flags); | |
- } else if (cp_heap->cma) { | |
- ret_value = cp_heap->cpu_addr + | |
- (buffer->priv_phys - start_phys); | |
- } else { | |
if (ION_IS_CACHED(buffer->flags)) | |
ret_value = ioremap_cached(buffer->priv_phys, | |
buffer->size); | |
else | |
ret_value = ioremap(buffer->priv_phys, | |
buffer->size); | |
- } | |
if (!ret_value) { | |
ion_cp_release_region(cp_heap); | |
@@ -580,7 +462,6 @@ void *ion_cp_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer) | |
++cp_heap->kmap_uncached_count; | |
} | |
} | |
- | |
mutex_unlock(&cp_heap->lock); | |
return ret_value; | |
} | |
@@ -591,9 +472,6 @@ void ion_cp_heap_unmap_kernel(struct ion_heap *heap, | |
struct ion_cp_heap *cp_heap = | |
container_of(heap, struct ion_cp_heap, heap); | |
- if (cp_heap->reusable) | |
- unmap_kernel_range((unsigned long)buffer->vaddr, buffer->size); | |
- else if (!cp_heap->cma) | |
__arm_iounmap(buffer->vaddr); | |
buffer->vaddr = NULL; | |
@@ -657,25 +535,77 @@ int ion_cp_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer, | |
void *vaddr, unsigned int offset, unsigned int length, | |
unsigned int cmd) | |
{ | |
- void (*outer_cache_op)(phys_addr_t, phys_addr_t); | |
+ void (*outer_cache_op)(phys_addr_t, phys_addr_t) = NULL; | |
struct ion_cp_heap *cp_heap = | |
- container_of(heap, struct ion_cp_heap, heap); | |
- | |
- switch (cmd) { | |
- case ION_IOC_CLEAN_CACHES: | |
- dmac_clean_range(vaddr, vaddr + length); | |
- outer_cache_op = outer_clean_range; | |
- break; | |
- case ION_IOC_INV_CACHES: | |
- dmac_inv_range(vaddr, vaddr + length); | |
- outer_cache_op = outer_inv_range; | |
- break; | |
- case ION_IOC_CLEAN_INV_CACHES: | |
- dmac_flush_range(vaddr, vaddr + length); | |
- outer_cache_op = outer_flush_range; | |
- break; | |
- default: | |
- return -EINVAL; | |
+ container_of(heap, struct ion_cp_heap, heap); | |
+ unsigned int size_to_vmap, total_size; | |
+ int i, j; | |
+ void *ptr = NULL; | |
+ ion_phys_addr_t buff_phys = buffer->priv_phys; | |
+ | |
+ if (!vaddr) { | |
+ /* | |
+ * Split the vmalloc space into smaller regions in | |
+ * order to clean and/or invalidate the cache. | |
+ */ | |
+ size_to_vmap = (VMALLOC_END - VMALLOC_START)/8; | |
+ total_size = buffer->size; | |
+ for (i = 0; i < total_size; i += size_to_vmap) { | |
+ size_to_vmap = min(size_to_vmap, total_size - i); | |
+ for (j = 0; j < 10 && size_to_vmap; ++j) { | |
+ ptr = ioremap(buff_phys, size_to_vmap); | |
+ if (ptr) { | |
+ switch (cmd) { | |
+ case ION_IOC_CLEAN_CACHES: | |
+ dmac_clean_range(ptr, | |
+ ptr + size_to_vmap); | |
+ outer_cache_op = | |
+ outer_clean_range; | |
+ break; | |
+ case ION_IOC_INV_CACHES: | |
+ dmac_inv_range(ptr, | |
+ ptr + size_to_vmap); | |
+ outer_cache_op = | |
+ outer_inv_range; | |
+ break; | |
+ case ION_IOC_CLEAN_INV_CACHES: | |
+ dmac_flush_range(ptr, | |
+ ptr + size_to_vmap); | |
+ outer_cache_op = | |
+ outer_flush_range; | |
+ break; | |
+ default: | |
+ return -EINVAL; | |
+ } | |
+ buff_phys += size_to_vmap; | |
+ break; | |
+ } else { | |
+ size_to_vmap >>= 1; | |
+ } | |
+ } | |
+ if (!ptr) { | |
+ pr_err("Couldn't io-remap the memory\n"); | |
+ return -EINVAL; | |
+ } | |
+ iounmap(ptr); | |
+ } | |
+ } else { | |
+ switch (cmd) { | |
+ case ION_IOC_CLEAN_CACHES: | |
+ dmac_clean_range(vaddr, vaddr + length); | |
+ outer_cache_op = outer_clean_range; | |
+ break; | |
+ case ION_IOC_INV_CACHES: | |
+ dmac_inv_range(vaddr, vaddr + length); | |
+ outer_cache_op = outer_inv_range; | |
+ break; | |
+ case ION_IOC_CLEAN_INV_CACHES: | |
+ dmac_flush_range(vaddr, vaddr + length); | |
+ outer_cache_op = outer_flush_range; | |
+ break; | |
+ default: | |
+ return -EINVAL; | |
+ } | |
} | |
if (cp_heap->has_outer_cache) { | |
@@ -709,7 +639,6 @@ static int ion_cp_print_debug(struct ion_heap *heap, struct seq_file *s, | |
seq_printf(s, "umapping count: %lx\n", umap_count); | |
seq_printf(s, "kmapping count: %lx\n", kmap_count); | |
seq_printf(s, "heap protected: %s\n", heap_protected ? "Yes" : "No"); | |
- seq_printf(s, "reusable: %s\n", cp_heap->reusable ? "Yes" : "No"); | |
if (mem_map) { | |
unsigned long base = cp_heap->base; | |
@@ -1008,6 +937,14 @@ struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *heap_data) | |
mutex_init(&cp_heap->lock); | |
+ cp_heap->pool = gen_pool_create(12, -1); | |
+ if (!cp_heap->pool) | |
+ goto free_heap; | |
+ | |
+ cp_heap->base = heap_data->base; | |
+ ret = gen_pool_add(cp_heap->pool, cp_heap->base, heap_data->size, -1); | |
+ if (ret < 0) | |
+ goto destroy_pool; | |
cp_heap->allocated_bytes = 0; | |
cp_heap->umap_count = 0; | |
@@ -1015,19 +952,15 @@ struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *heap_data) | |
cp_heap->kmap_uncached_count = 0; | |
cp_heap->total_size = heap_data->size; | |
cp_heap->heap.ops = &cp_heap_ops; | |
- cp_heap->heap.type = ION_HEAP_TYPE_CP; | |
+ cp_heap->heap.type = (enum ion_heap_type) ION_HEAP_TYPE_CP; | |
cp_heap->heap_protected = HEAP_NOT_PROTECTED; | |
- cp_heap->secure_base = heap_data->base; | |
+ cp_heap->secure_base = cp_heap->base; | |
cp_heap->secure_size = heap_data->size; | |
cp_heap->has_outer_cache = heap_data->has_outer_cache; | |
- cp_heap->heap_size = heap_data->size; | |
- | |
atomic_set(&cp_heap->protect_cnt, 0); | |
if (heap_data->extra_data) { | |
struct ion_cp_heap_pdata *extra_data = | |
heap_data->extra_data; | |
- cp_heap->reusable = extra_data->reusable; | |
- cp_heap->reserved_vrange = extra_data->virt_addr; | |
cp_heap->permission_type = extra_data->permission_type; | |
if (extra_data->secure_size) { | |
cp_heap->secure_base = extra_data->secure_base; | |
@@ -1045,25 +978,11 @@ struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *heap_data) | |
extra_data->iommu_map_all; | |
cp_heap->iommu_2x_map_domain = | |
extra_data->iommu_2x_map_domain; | |
- cp_heap->cma = extra_data->is_cma; | |
- } | |
- | |
- if (cp_heap->cma) { | |
- cp_heap->pool = NULL; | |
- cp_heap->cpu_addr = 0; | |
- cp_heap->heap.priv = heap_data->priv; | |
- } else { | |
- cp_heap->pool = gen_pool_create(12, -1); | |
- if (!cp_heap->pool) | |
- goto free_heap; | |
- | |
- cp_heap->base = heap_data->base; | |
- ret = gen_pool_add(cp_heap->pool, cp_heap->base, | |
- heap_data->size, -1); | |
- if (ret < 0) | |
- goto destroy_pool; | |
+ cp_heap->disallow_non_secure_allocation = | |
+ extra_data->no_nonsecure_alloc; | |
} | |
+ | |
return &cp_heap->heap; | |
destroy_pool: | |
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c | |
index 2b5d24c..065c9c2 100644 | |
--- a/drivers/gpu/ion/ion_heap.c | |
+++ b/drivers/gpu/ion/ion_heap.c | |
@@ -18,6 +18,7 @@ | |
#include <linux/err.h> | |
#include <linux/ion.h> | |
#include "ion_priv.h" | |
+#include <linux/msm_ion.h> | |
struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data) | |
{ | |
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c | |
index b94f1f5..f5be5d1 100644 | |
--- a/drivers/gpu/ion/ion_iommu_heap.c | |
+++ b/drivers/gpu/ion/ion_iommu_heap.c | |
@@ -1,5 +1,5 @@ | |
/* | |
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2011-2013, The Linux Foundation. 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 and | |
@@ -12,56 +12,153 @@ | |
*/ | |
#include <linux/err.h> | |
#include <linux/io.h> | |
-#include <linux/ion.h> | |
#include <linux/mm.h> | |
+#include <linux/highmem.h> | |
#include <linux/scatterlist.h> | |
#include <linux/slab.h> | |
#include <linux/vmalloc.h> | |
#include <linux/iommu.h> | |
#include <linux/pfn.h> | |
+#include <linux/dma-mapping.h> | |
#include "ion_priv.h" | |
#include <asm/mach/map.h> | |
#include <asm/page.h> | |
#include <asm/cacheflush.h> | |
#include <mach/iommu_domains.h> | |
-#include <linux/dma-mapping.h> | |
struct ion_iommu_heap { | |
struct ion_heap heap; | |
unsigned int has_outer_cache; | |
}; | |
+/* | |
+ * We will attempt to allocate high-order pages and store those in an | |
+ * sg_list. However, some APIs expect an array of struct page * where | |
+ * each page is of size PAGE_SIZE. We use this extra structure to | |
+ * carry around an array of such pages (derived from the high-order | |
+ * pages with nth_page). | |
+*/ | |
+ | |
struct ion_iommu_priv_data { | |
struct page **pages; | |
+ unsigned int pages_uses_vmalloc; | |
int nrpages; | |
unsigned long size; | |
}; | |
+#define MAX_VMAP_RETRIES 10 | |
+ | |
+static const unsigned int orders[] = {8, 4, 0}; | |
+static const int num_orders = ARRAY_SIZE(orders); | |
+ | |
+struct page_info { | |
+ struct page *page; | |
+ unsigned int order; | |
+ struct list_head list; | |
+}; | |
+ | |
+static unsigned int order_to_size(int order) | |
+{ | |
+ return PAGE_SIZE << order; | |
+} | |
+ | |
+static struct page_info *alloc_largest_available(unsigned long size, | |
+ unsigned int max_order) | |
+{ | |
+ struct page *page; | |
+ struct page_info *info; | |
+ int i; | |
+ | |
+ for (i = 0; i < num_orders; i++) { | |
+ gfp_t gfp; | |
+ if (size < order_to_size(orders[i])) | |
+ continue; | |
+ if (max_order < orders[i]) | |
+ continue; | |
+ | |
+ gfp = __GFP_HIGHMEM; | |
+ | |
+ if (orders[i]) { | |
+ gfp |= __GFP_COMP | __GFP_NORETRY | | |
+ __GFP_NO_KSWAPD | __GFP_NOWARN; | |
+ } else { | |
+ gfp |= GFP_KERNEL; | |
+ } | |
+ page = alloc_pages(gfp, orders[i]); | |
+ if (!page) | |
+ continue; | |
+ | |
+ info = kmalloc(sizeof(struct page_info), GFP_KERNEL); | |
+ info->page = page; | |
+ info->order = orders[i]; | |
+ return info; | |
+ } | |
+ return NULL; | |
+} | |
+ | |
static int ion_iommu_heap_allocate(struct ion_heap *heap, | |
struct ion_buffer *buffer, | |
unsigned long size, unsigned long align, | |
unsigned long flags) | |
{ | |
int ret, i; | |
+ struct list_head pages_list; | |
+ struct page_info *info, *tmp_info; | |
struct ion_iommu_priv_data *data = NULL; | |
if (msm_use_iommu()) { | |
struct scatterlist *sg; | |
struct sg_table *table; | |
- unsigned int i; | |
+ int j; | |
+ void *ptr = NULL; | |
+ unsigned int npages_to_vmap, total_pages, num_large_pages = 0; | |
+ unsigned long size_remaining = PAGE_ALIGN(size); | |
+ unsigned int max_order = orders[0]; | |
+ unsigned int page_tbl_size; | |
data = kmalloc(sizeof(*data), GFP_KERNEL); | |
if (!data) | |
return -ENOMEM; | |
+ INIT_LIST_HEAD(&pages_list); | |
+ while (size_remaining > 0) { | |
+ info = alloc_largest_available(size_remaining, | |
+ max_order); | |
+ if (!info) { | |
+ ret = -ENOMEM; | |
+ goto err_free_data; | |
+ } | |
+ list_add_tail(&info->list, &pages_list); | |
+ size_remaining -= order_to_size(info->order); | |
+ max_order = info->order; | |
+ num_large_pages++; | |
+ } | |
+ | |
data->size = PFN_ALIGN(size); | |
data->nrpages = data->size >> PAGE_SHIFT; | |
- data->pages = kzalloc(sizeof(struct page *)*data->nrpages, | |
- GFP_KERNEL); | |
+ data->pages_uses_vmalloc = 0; | |
+ page_tbl_size = sizeof(struct page *) * data->nrpages; | |
+ | |
+ if (page_tbl_size > SZ_8K) { | |
+ /* | |
+ * Do fallback to ensure we have a balance between | |
+ * performance and availability. | |
+ */ | |
+ data->pages = kmalloc(page_tbl_size, | |
+ __GFP_COMP | __GFP_NORETRY | | |
+ __GFP_NO_KSWAPD | __GFP_NOWARN); | |
+ if (!data->pages) { | |
+ data->pages = vmalloc(page_tbl_size); | |
+ data->pages_uses_vmalloc = 1; | |
+ } | |
+ } else { | |
+ data->pages = kmalloc(page_tbl_size, GFP_KERNEL); | |
+ } | |
+ | |
if (!data->pages) { | |
ret = -ENOMEM; | |
- goto err1; | |
+ goto err_free_data; | |
} | |
table = buffer->sg_table = | |
@@ -71,17 +168,55 @@ static int ion_iommu_heap_allocate(struct ion_heap *heap, | |
ret = -ENOMEM; | |
goto err1; | |
} | |
- ret = sg_alloc_table(table, data->nrpages, GFP_KERNEL); | |
+ ret = sg_alloc_table(table, num_large_pages, GFP_KERNEL); | |
if (ret) | |
goto err2; | |
- for_each_sg(table->sgl, sg, table->nents, i) { | |
- data->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO); | |
- if (!data->pages[i]) | |
- goto err3; | |
- | |
- sg_set_page(sg, data->pages[i], PAGE_SIZE, 0); | |
+ i = 0; | |
+ sg = table->sgl; | |
+ list_for_each_entry_safe(info, tmp_info, &pages_list, list) { | |
+ struct page *page = info->page; | |
+ sg_set_page(sg, page, order_to_size(info->order), 0); | |
sg_dma_address(sg) = sg_phys(sg); | |
+ sg = sg_next(sg); | |
+ for (j = 0; j < (1 << info->order); ++j) | |
+ data->pages[i++] = nth_page(page, j); | |
+ list_del(&info->list); | |
+ kfree(info); | |
+ } | |
+ | |
+ /* | |
+ * As an optimization, we omit __GFP_ZERO from | |
+ * alloc_page above and manually zero out all of the | |
+ * pages in one fell swoop here. To safeguard against | |
+ * insufficient vmalloc space, we only vmap | |
+ * `npages_to_vmap' at a time, starting with a | |
+ * conservative estimate of 1/8 of the total number of | |
+ * vmalloc pages available. Note that the `pages' | |
+ * array is composed of all 4K pages, irrespective of | |
+ * the size of the pages on the sg list. | |
+ */ | |
+ npages_to_vmap = ((VMALLOC_END - VMALLOC_START)/8) | |
+ >> PAGE_SHIFT; | |
+ total_pages = data->nrpages; | |
+ for (i = 0; i < total_pages; i += npages_to_vmap) { | |
+ npages_to_vmap = min(npages_to_vmap, total_pages - i); | |
+ for (j = 0; j < MAX_VMAP_RETRIES && npages_to_vmap; | |
+ ++j) { | |
+ ptr = vmap(&data->pages[i], npages_to_vmap, | |
+ VM_IOREMAP, pgprot_kernel); | |
+ if (ptr) | |
+ break; | |
+ else | |
+ npages_to_vmap >>= 1; | |
+ } | |
+ if (!ptr) { | |
+ pr_err("Couldn't vmap the pages for zeroing\n"); | |
+ ret = -ENOMEM; | |
+ goto err3; | |
+ } | |
+ memset(ptr, 0, npages_to_vmap * PAGE_SIZE); | |
+ vunmap(ptr); | |
} | |
if (!ION_IS_CACHED(flags)) | |
@@ -101,29 +236,45 @@ err3: | |
err2: | |
kfree(buffer->sg_table); | |
buffer->sg_table = 0; | |
- | |
- for (i = 0; i < data->nrpages; i++) { | |
- if (data->pages[i]) | |
- __free_page(data->pages[i]); | |
- } | |
- kfree(data->pages); | |
err1: | |
+ if (data->pages_uses_vmalloc) | |
+ vfree(data->pages); | |
+ else | |
+ kfree(data->pages); | |
+err_free_data: | |
kfree(data); | |
+ | |
+ list_for_each_entry_safe(info, tmp_info, &pages_list, list) { | |
+ if (info->page) | |
+ __free_pages(info->page, info->order); | |
+ list_del(&info->list); | |
+ kfree(info); | |
+ } | |
return ret; | |
} | |
static void ion_iommu_heap_free(struct ion_buffer *buffer) | |
{ | |
- struct ion_iommu_priv_data *data = buffer->priv_virt; | |
int i; | |
+ struct scatterlist *sg; | |
+ struct sg_table *table = buffer->sg_table; | |
+ struct ion_iommu_priv_data *data = buffer->priv_virt; | |
+ if (!table) | |
+ return; | |
if (!data) | |
return; | |
- for (i = 0; i < data->nrpages; i++) | |
- __free_page(data->pages[i]); | |
+ for_each_sg(table->sgl, sg, table->nents, i) | |
+ __free_pages(sg_page(sg), get_order(sg_dma_len(sg))); | |
- kfree(data->pages); | |
+ sg_free_table(table); | |
+ kfree(table); | |
+ table = 0; | |
+ if (data->pages_uses_vmalloc) | |
+ vfree(data->pages); | |
+ else | |
+ kfree(data->pages); | |
kfree(data); | |
} | |
@@ -137,7 +288,7 @@ void *ion_iommu_heap_map_kernel(struct ion_heap *heap, | |
return NULL; | |
if (!ION_IS_CACHED(buffer->flags)) | |
- page_prot = pgprot_noncached(page_prot); | |
+ page_prot = pgprot_writecombine(page_prot); | |
buffer->vaddr = vmap(data->pages, data->nrpages, VM_IOREMAP, page_prot); | |
@@ -157,25 +308,34 @@ void ion_iommu_heap_unmap_kernel(struct ion_heap *heap, | |
int ion_iommu_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer, | |
struct vm_area_struct *vma) | |
{ | |
- struct ion_iommu_priv_data *data = buffer->priv_virt; | |
+ struct sg_table *table = buffer->sg_table; | |
+ unsigned long addr = vma->vm_start; | |
+ unsigned long offset = vma->vm_pgoff * PAGE_SIZE; | |
+ struct scatterlist *sg; | |
int i; | |
- unsigned long curr_addr; | |
- if (!data) | |
- return -EINVAL; | |
if (!ION_IS_CACHED(buffer->flags)) | |
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); | |
- curr_addr = vma->vm_start; | |
- for (i = 0; i < data->nrpages && curr_addr < vma->vm_end; i++) { | |
- if (vm_insert_page(vma, curr_addr, data->pages[i])) { | |
- /* | |
- * This will fail the mmap which will | |
- * clean up the vma space properly. | |
- */ | |
- return -EINVAL; | |
+ for_each_sg(table->sgl, sg, table->nents, i) { | |
+ struct page *page = sg_page(sg); | |
+ unsigned long remainder = vma->vm_end - addr; | |
+ unsigned long len = sg_dma_len(sg); | |
+ | |
+ if (offset >= sg_dma_len(sg)) { | |
+ offset -= sg_dma_len(sg); | |
+ continue; | |
+ } else if (offset) { | |
+ page += offset / PAGE_SIZE; | |
+ len = sg_dma_len(sg) - offset; | |
+ offset = 0; | |
} | |
- curr_addr += PAGE_SIZE; | |
+ len = min(len, remainder); | |
+ remap_pfn_range(vma, addr, page_to_pfn(page), len, | |
+ vma->vm_page_prot); | |
+ addr += len; | |
+ if (addr >= vma->vm_end) | |
+ return 0; | |
} | |
return 0; | |
} | |
@@ -199,6 +359,14 @@ int ion_iommu_heap_map_iommu(struct ion_buffer *buffer, | |
data->mapped_size = iova_length; | |
extra = iova_length - buffer->size; | |
+ /* Use the biggest alignment to allow bigger IOMMU mappings. | |
+ * Use the first entry since the first entry will always be the | |
+ * biggest entry. To take advantage of bigger mapping sizes both the | |
+ * VA and PA addresses have to be aligned to the biggest size. | |
+ */ | |
+ if (buffer->sg_table->sgl->length > align) | |
+ align = buffer->sg_table->sgl->length; | |
+ | |
ret = msm_allocate_iova_address(domain_num, partition_num, | |
data->mapped_size, align, | |
&data->iova_addr); | |
@@ -277,15 +445,30 @@ static int ion_iommu_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer, | |
switch (cmd) { | |
case ION_IOC_CLEAN_CACHES: | |
- dmac_clean_range(vaddr, vaddr + length); | |
+ if (!vaddr) | |
+ dma_sync_sg_for_device(NULL, buffer->sg_table->sgl, | |
+ buffer->sg_table->nents, DMA_TO_DEVICE); | |
+ else | |
+ dmac_clean_range(vaddr, vaddr + length); | |
outer_cache_op = outer_clean_range; | |
break; | |
case ION_IOC_INV_CACHES: | |
- dmac_inv_range(vaddr, vaddr + length); | |
+ if (!vaddr) | |
+ dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl, | |
+ buffer->sg_table->nents, DMA_FROM_DEVICE); | |
+ else | |
+ dmac_inv_range(vaddr, vaddr + length); | |
outer_cache_op = outer_inv_range; | |
break; | |
case ION_IOC_CLEAN_INV_CACHES: | |
- dmac_flush_range(vaddr, vaddr + length); | |
+ if (!vaddr) { | |
+ dma_sync_sg_for_device(NULL, buffer->sg_table->sgl, | |
+ buffer->sg_table->nents, DMA_TO_DEVICE); | |
+ dma_sync_sg_for_cpu(NULL, buffer->sg_table->sgl, | |
+ buffer->sg_table->nents, DMA_FROM_DEVICE); | |
+ } else { | |
+ dmac_flush_range(vaddr, vaddr + length); | |
+ } | |
outer_cache_op = outer_flush_range; | |
break; | |
default: | |
@@ -316,10 +499,6 @@ static struct sg_table *ion_iommu_heap_map_dma(struct ion_heap *heap, | |
static void ion_iommu_heap_unmap_dma(struct ion_heap *heap, | |
struct ion_buffer *buffer) | |
{ | |
- if (buffer->sg_table) | |
- sg_free_table(buffer->sg_table); | |
- kfree(buffer->sg_table); | |
- buffer->sg_table = 0; | |
} | |
static struct ion_heap_ops iommu_heap_ops = { | |
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c | |
index 0507dcd..5fc65f6 100644 | |
--- a/drivers/gpu/ion/msm/msm_ion.c | |
+++ b/drivers/gpu/ion/msm/msm_ion.c | |
@@ -17,7 +17,6 @@ | |
#include <linux/platform_device.h> | |
#include <linux/slab.h> | |
#include <linux/memory_alloc.h> | |
-#include <linux/fmem.h> | |
#include <mach/ion.h> | |
#include <mach/msm_memtypes.h> | |
#include "../ion_priv.h" | |
@@ -101,22 +100,9 @@ static void ion_set_base_address(struct ion_platform_heap *heap, | |
struct ion_co_heap_pdata *co_heap_data, | |
struct ion_cp_heap_pdata *cp_data) | |
{ | |
- if (cp_data->reusable) { | |
- const struct fmem_data *fmem_info = fmem_get_info(); | |
- | |
- if (!fmem_info) { | |
- pr_err("fmem info pointer NULL!\n"); | |
- BUG(); | |
- } | |
- | |
- heap->base = fmem_info->phys - fmem_info->reserved_size_low; | |
- cp_data->virt_addr = fmem_info->virt; | |
- pr_info("ION heap %s using FMEM\n", shared_heap->name); | |
- } else { | |
- heap->base = msm_ion_get_base(heap->size + shared_heap->size, | |
- shared_heap->memory_type, | |
- co_heap_data->align); | |
- } | |
+ heap->base = msm_ion_get_base(heap->size + shared_heap->size, | |
+ shared_heap->memory_type, | |
+ co_heap_data->align); | |
if (heap->base) { | |
shared_heap->base = heap->base + heap->size; | |
cp_data->secure_base = heap->base; | |
@@ -142,15 +128,6 @@ static void allocate_co_memory(struct ion_platform_heap *heap, | |
struct ion_cp_heap_pdata *cp_data = | |
(struct ion_cp_heap_pdata *) shared_heap->extra_data; | |
if (cp_data->fixed_position == FIXED_MIDDLE) { | |
- const struct fmem_data *fmem_info = | |
- fmem_get_info(); | |
- | |
- if (!fmem_info) { | |
- pr_err("fmem info pointer NULL!\n"); | |
- BUG(); | |
- } | |
- | |
- cp_data->virt_addr = fmem_info->virt; | |
if (!cp_data->secure_base) { | |
cp_data->secure_base = heap->base; | |
cp_data->secure_size = | |
@@ -202,17 +179,6 @@ static void msm_ion_allocate(struct ion_platform_heap *heap) | |
struct ion_cp_heap_pdata *data = | |
(struct ion_cp_heap_pdata *) | |
heap->extra_data; | |
- if (data->reusable) { | |
- const struct fmem_data *fmem_info = | |
- fmem_get_info(); | |
- heap->base = fmem_info->phys; | |
- data->virt_addr = fmem_info->virt; | |
- pr_info("ION heap %s using FMEM\n", heap->name); | |
- } else if (data->mem_is_fmem) { | |
- const struct fmem_data *fmem_info = | |
- fmem_get_info(); | |
- heap->base = fmem_info->phys + fmem_info->size; | |
- } | |
align = data->align; | |
break; | |
} | |
diff --git a/drivers/gpu/msm/a2xx_reg.h b/drivers/gpu/msm/a2xx_reg.h | |
index 49037c4..3fdb024 100644 | |
--- a/drivers/gpu/msm/a2xx_reg.h | |
+++ b/drivers/gpu/msm/a2xx_reg.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2007-2012,2014 The Linux Foundation. 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 and | |
@@ -341,7 +341,6 @@ union reg_cp_rb_cntl { | |
#define REG_RB_MODECONTROL 0x2208 | |
#define REG_RB_SURFACE_INFO 0x2000 | |
#define REG_RB_SAMPLE_POS 0x220a | |
-#define REG_RB_BC_CONTROL 0x0F01 | |
#define REG_SCRATCH_ADDR 0x01DD | |
#define REG_SCRATCH_REG0 0x0578 | |
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h | |
index 1030045..a6d69db 100644 | |
--- a/drivers/gpu/msm/a3xx_reg.h | |
+++ b/drivers/gpu/msm/a3xx_reg.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c | |
index 0207aab..c339232 100644 | |
--- a/drivers/gpu/msm/adreno.c | |
+++ b/drivers/gpu/msm/adreno.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2007-2014, The Linux Foundation. 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 and | |
@@ -1318,7 +1318,7 @@ static int adreno_ringbuffer_drain(struct kgsl_device *device, | |
/* | |
* The first time into the loop, wait for 100 msecs and kick wptr again | |
* to ensure that the hardware has updated correctly. After that, kick | |
- * it periodically every KGSL_TIMEOUT_PART msecs until the timeout | |
+ * it periodically every KGSL_TIMEOUT_HANG_DETECT msecs until the timeout | |
* expires | |
*/ | |
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h | |
index b4b051d..3f7b5c8 100644 | |
--- a/drivers/gpu/msm/adreno.h | |
+++ b/drivers/gpu/msm/adreno.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2008-2012,2014 The Linux Foundation. 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 and | |
@@ -116,8 +116,8 @@ struct adreno_gpudev { | |
}; | |
/* | |
- * struct adreno_recovery_data - Structure that contains all information to | |
- * perform gpu recovery from hangs | |
+ * struct adreno_ft_data - Structure that contains all information to | |
+ * perform gpu fault tolerance | |
* @ib1 - IB1 that the GPU was executing when hang happened | |
* @context_id - Context which caused the hang | |
* @global_eop - eoptimestamp at time of hang | |
@@ -125,8 +125,17 @@ struct adreno_gpudev { | |
* @rb_size - Number of valid dwords in rb_buffer | |
* @bad_rb_buffer - Buffer that holds commands from the hanging context | |
* bad_rb_size - Number of valid dwords in bad_rb_buffer | |
+ * @good_rb_buffer - Buffer that holds commands from good contexts | |
+ * good_rb_size - Number of valid dwords in good_rb_buffer | |
* @last_valid_ctx_id - The last context from which commands were placed in | |
* ringbuffer before the GPU hung | |
+ * @step - Current fault tolerance step being executed | |
+ * @err_code - Fault tolerance error code | |
+ * @fault - Indicates whether the hang was caused due to a pagefault | |
+ * @start_of_replay_cmds - Offset in ringbuffer from where commands can be | |
+ * replayed during fault tolerance | |
+ * @replay_for_snapshot - Offset in ringbuffer where IB's can be saved for | |
+ * replaying with snapshot | |
*/ | |
struct adreno_recovery_data { | |
unsigned int ib1; | |
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c | |
index 93109a6..16e7380 100644 | |
--- a/drivers/gpu/msm/adreno_a2xx.c | |
+++ b/drivers/gpu/msm/adreno_a2xx.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2007-2014, The Linux Foundation. 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 and | |
@@ -617,12 +617,6 @@ static void build_regsave_cmds(struct adreno_device *adreno_dev, | |
*cmd++ = REG_TP0_CHICKEN; | |
*cmd++ = tmp_ctx.reg_values[1]; | |
- if (adreno_is_a20x(adreno_dev)) { | |
- *cmd++ = cp_type3_packet(CP_REG_TO_MEM, 2); | |
- *cmd++ = REG_RB_BC_CONTROL; | |
- *cmd++ = tmp_ctx.reg_values[2]; | |
- } | |
- | |
if (adreno_is_a22x(adreno_dev)) { | |
unsigned int i; | |
unsigned int j = 2; | |
@@ -1143,12 +1137,6 @@ static void build_regrestore_cmds(struct adreno_device *adreno_dev, | |
tmp_ctx.reg_values[1] = virt2gpu(cmd, &drawctxt->gpustate); | |
*cmd++ = 0x00000000; | |
- if (adreno_is_a20x(adreno_dev)) { | |
- *cmd++ = cp_type0_packet(REG_RB_BC_CONTROL, 1); | |
- tmp_ctx.reg_values[2] = virt2gpu(cmd, &drawctxt->gpustate); | |
- *cmd++ = 0x00000000; | |
- } | |
- | |
if (adreno_is_a22x(adreno_dev)) { | |
unsigned int i; | |
unsigned int j = 2; | |
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c | |
index 3f7abdf..eb3f0ff 100644 | |
--- a/drivers/gpu/msm/adreno_a3xx.c | |
+++ b/drivers/gpu/msm/adreno_a3xx.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012-2014, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c | |
index 00e0575..bf7d967 100644 | |
--- a/drivers/gpu/msm/adreno_a3xx_snapshot.c | |
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012,2014 The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c | |
index 6893ff2..c5e0d5f 100644 | |
--- a/drivers/gpu/msm/adreno_drawctxt.c | |
+++ b/drivers/gpu/msm/adreno_drawctxt.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h | |
index 7c65aaf..dee8287 100644 | |
--- a/drivers/gpu/msm/adreno_drawctxt.h | |
+++ b/drivers/gpu/msm/adreno_drawctxt.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c | |
index 24c7303..6434d40 100755 | |
--- a/drivers/gpu/msm/adreno_ringbuffer.c | |
+++ b/drivers/gpu/msm/adreno_ringbuffer.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2007-2014, The Linux Foundation. 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 and | |
@@ -578,8 +578,8 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, | |
if (adreno_is_a3xx(adreno_dev)) { | |
/* | |
- * FLush HLSQ lazy updates to make sure there are no | |
- * rsources pending for indirect loads after the timestamp | |
+ * Flush HLSQ lazy updates to make sure there are no | |
+ * resources pending for indirect loads after the timestamp | |
*/ | |
GSL_RB_WRITE(ringcmds, rcmd_gpu, | |
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h | |
index 0d9b6a7..e27747f 100644 | |
--- a/drivers/gpu/msm/adreno_ringbuffer.h | |
+++ b/drivers/gpu/msm/adreno_ringbuffer.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c | |
index 8029864..b24f4c0 100644 | |
--- a/drivers/gpu/msm/adreno_snapshot.c | |
+++ b/drivers/gpu/msm/adreno_snapshot.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c | |
index 2f957c5..32050d3 100644 | |
--- a/drivers/gpu/msm/kgsl.c | |
+++ b/drivers/gpu/msm/kgsl.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2008-2012,2014 The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h | |
index 018c56d..08d8569 100644 | |
--- a/drivers/gpu/msm/kgsl.h | |
+++ b/drivers/gpu/msm/kgsl.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2008-2014, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c | |
index bae1565..abce08c 100644 | |
--- a/drivers/gpu/msm/kgsl_debugfs.c | |
+++ b/drivers/gpu/msm/kgsl_debugfs.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2008-2011, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2008-2012,2014, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl_debugfs.h b/drivers/gpu/msm/kgsl_debugfs.h | |
index b13e7fd..696b1d1 100644 | |
--- a/drivers/gpu/msm/kgsl_debugfs.h | |
+++ b/drivers/gpu/msm/kgsl_debugfs.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2008-2011, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2008-2011,2013, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h | |
index d41f0d7..126b6e2 100644 | |
--- a/drivers/gpu/msm/kgsl_device.h | |
+++ b/drivers/gpu/msm/kgsl_device.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2007-2012,2014 The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c | |
index c6d25a2..b75fdc6 100644 | |
--- a/drivers/gpu/msm/kgsl_iommu.c | |
+++ b/drivers/gpu/msm/kgsl_iommu.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2011-2014, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h | |
index f7bae7e..e57fc59 100644 | |
--- a/drivers/gpu/msm/kgsl_iommu.h | |
+++ b/drivers/gpu/msm/kgsl_iommu.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c | |
index aa175b2..b958973 100644 | |
--- a/drivers/gpu/msm/kgsl_mmu.c | |
+++ b/drivers/gpu/msm/kgsl_mmu.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2007-2014, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c | |
index 869731f..48fe0b3 100644 | |
--- a/drivers/gpu/msm/kgsl_pwrctrl.c | |
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012,2014 The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h | |
index 4161f37..3aaf824 100644 | |
--- a/drivers/gpu/msm/kgsl_pwrctrl.h | |
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, The Linux Foundation. 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 and | |
@@ -60,8 +60,6 @@ struct kgsl_clk_stats { | |
* @irq_name - resource name for the IRQ | |
* @restore_slumber - Flag to indicate that we are in a suspend/restore sequence | |
* @clk_stats - structure of clock statistics | |
- * @pm_qos_req_dma - the power management quality of service structure | |
- * @pm_qos_latency - allowed CPU latency in microseconds | |
*/ | |
struct kgsl_pwrctrl { | |
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c | |
index dda443a..49a6e6b 100644 | |
--- a/drivers/gpu/msm/kgsl_pwrscale.c | |
+++ b/drivers/gpu/msm/kgsl_pwrscale.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c | |
index 62e9832..d611574 100644 | |
--- a/drivers/gpu/msm/kgsl_sharedmem.c | |
+++ b/drivers/gpu/msm/kgsl_sharedmem.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2007-2012,2014, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h | |
index e6fff45..e62b9f8 100644 | |
--- a/drivers/gpu/msm/kgsl_sharedmem.h | |
+++ b/drivers/gpu/msm/kgsl_sharedmem.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c | |
index f402f16..3dd5ba4 100644 | |
--- a/drivers/gpu/msm/kgsl_snapshot.c | |
+++ b/drivers/gpu/msm/kgsl_snapshot.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h | |
index ff81741..d34d9b3 100644 | |
--- a/drivers/gpu/msm/kgsl_trace.h | |
+++ b/drivers/gpu/msm/kgsl_trace.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2011-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c | |
index b1459e5..53001f2 100644 | |
--- a/drivers/gpu/msm/z180.c | |
+++ b/drivers/gpu/msm/z180.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2007-2014, The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/z180.h b/drivers/gpu/msm/z180.h | |
index 3433845..a84bfd9 100644 | |
--- a/drivers/gpu/msm/z180.h | |
+++ b/drivers/gpu/msm/z180.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2008-2011, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2008-2012,2014 The Linux Foundation. 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 and | |
diff --git a/drivers/gpu/msm/z180_reg.h b/drivers/gpu/msm/z180_reg.h | |
index 41a17ce..9ce4221 100644 | |
--- a/drivers/gpu/msm/z180_reg.h | |
+++ b/drivers/gpu/msm/z180_reg.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2002,2007-2011, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2002,2007-2012, The Linux Foundation. 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 and | |
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h | |
index c000fa4..893273d 100644 | |
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h | |
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_common.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
@@ -13,7 +13,7 @@ | |
#ifndef _MPQ_DMX_PLUGIN_COMMON_H | |
#define _MPQ_DMX_PLUGIN_COMMON_H | |
-#include <linux/ion.h> | |
+#include <linux/msm_ion.h> | |
#include "dvbdev.h" | |
#include "dmxdev.h" | |
diff --git a/drivers/media/video/msm/gemini/msm_gemini_platform.c b/drivers/media/video/msm/gemini/msm_gemini_platform.c | |
index 6550c92..1c1d47c 100644 | |
--- a/drivers/media/video/msm/gemini/msm_gemini_platform.c | |
+++ b/drivers/media/video/msm/gemini/msm_gemini_platform.c | |
@@ -15,7 +15,6 @@ | |
#include <linux/clk.h> | |
#include <mach/clk.h> | |
#include <linux/io.h> | |
-#include <linux/android_pmem.h> | |
#include <mach/camera.h> | |
#include <mach/iommu_domains.h> | |
@@ -35,8 +34,6 @@ void msm_gemini_platform_p2v(struct file *file, | |
ion_unmap_iommu(gemini_client, *ionhandle, CAMERA_DOMAIN, GEN_POOL); | |
ion_free(gemini_client, *ionhandle); | |
*ionhandle = NULL; | |
-#elif CONFIG_ANDROID_PMEM | |
- put_pmem_file(file); | |
#endif | |
} | |
@@ -53,9 +50,6 @@ uint32_t msm_gemini_platform_v2p(int fd, uint32_t len, struct file **file_p, | |
rc = ion_map_iommu(gemini_client, *ionhandle, CAMERA_DOMAIN, GEN_POOL, | |
SZ_4K, 0, &paddr, (unsigned long *)&size, UNCACHED, 0); | |
-#elif CONFIG_ANDROID_PMEM | |
- unsigned long kvstart; | |
- rc = get_pmem_file(fd, &paddr, &kvstart, &size, file_p); | |
#else | |
rc = 0; | |
paddr = 0; | |
diff --git a/drivers/media/video/msm/msm_camera.c b/drivers/media/video/msm/msm_camera.c | |
index 656630a..4b0fe92 100644 | |
--- a/drivers/media/video/msm/msm_camera.c | |
+++ b/drivers/media/video/msm/msm_camera.c | |
@@ -28,7 +28,6 @@ | |
#include <linux/fs.h> | |
#include <linux/list.h> | |
#include <linux/uaccess.h> | |
-#include <linux/android_pmem.h> | |
#include <linux/poll.h> | |
#include <media/msm_camera.h> | |
#include <mach/camera.h> | |
@@ -318,15 +317,6 @@ static int msm_pmem_table_add(struct hlist_head *ptype, | |
goto out1; | |
ion_phys(client_for_ion, region->handle, | |
&paddr, (size_t *)&len); | |
-#else | |
- rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file); | |
- if (rc < 0) { | |
- pr_err("%s: get_pmem_file fd %d error %d\n", | |
- __func__, | |
- info->fd, rc); | |
- goto out1; | |
- } | |
- region->file = file; | |
#endif | |
if (!info->len) | |
info->len = len; | |
@@ -363,8 +353,6 @@ static int msm_pmem_table_add(struct hlist_head *ptype, | |
out2: | |
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
ion_free(client_for_ion, region->handle); | |
-#else | |
- put_pmem_file(region->file); | |
#endif | |
out1: | |
kfree(region); | |
@@ -648,8 +636,6 @@ static int __msm_pmem_table_del(struct msm_sync *sync, | |
hlist_del(node); | |
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
ion_free(client_for_ion, region->handle); | |
-#else | |
- put_pmem_file(region->file); | |
#endif | |
kfree(region); | |
CDBG("%s: type %d, vaddr 0x%p\n", | |
@@ -672,8 +658,7 @@ static int __msm_pmem_table_del(struct msm_sync *sync, | |
hlist_del(node); | |
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
ion_free(client_for_ion, region->handle); | |
-#else | |
- put_pmem_file(region->file); | |
+ | |
#endif | |
kfree(region); | |
CDBG("%s: type %d, vaddr 0x%p\n", | |
@@ -695,8 +680,7 @@ static int __msm_pmem_table_del(struct msm_sync *sync, | |
hlist_del(node); | |
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
ion_free(client_for_ion, region->handle); | |
-#else | |
- put_pmem_file(region->file); | |
+ | |
#endif | |
kfree(region); | |
CDBG("%s: type %d, vaddr 0x%p\n", | |
@@ -3066,8 +3050,7 @@ static int __msm_release(struct msm_sync *sync) | |
hlist_del(hnode); | |
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
ion_free(client_for_ion, region->handle); | |
-#else | |
- put_pmem_file(region->file); | |
+ | |
#endif | |
kfree(region); | |
} | |
@@ -3077,8 +3060,7 @@ static int __msm_release(struct msm_sync *sync) | |
hlist_del(hnode); | |
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
ion_free(client_for_ion, region->handle); | |
-#else | |
- put_pmem_file(region->file); | |
+ | |
#endif | |
kfree(region); | |
} | |
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c | |
index 3a86fd0..e7245aa 100644 | |
--- a/drivers/media/video/msm/msm_isp.c | |
+++ b/drivers/media/video/msm/msm_isp.c | |
@@ -21,7 +21,6 @@ | |
#include <linux/videodev2.h> | |
#include <linux/proc_fs.h> | |
#include <linux/vmalloc.h> | |
-#include <linux/android_pmem.h> | |
#include <media/v4l2-dev.h> | |
#include <media/v4l2-ioctl.h> | |
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c | |
index 3beaf70..6c78c14 100644 | |
--- a/drivers/media/video/msm/msm_mctl.c | |
+++ b/drivers/media/video/msm/msm_mctl.c | |
@@ -25,7 +25,6 @@ | |
#include <media/v4l2-ioctl.h> | |
#include <media/v4l2-device.h> | |
-#include <linux/android_pmem.h> | |
#include <mach/cpuidle.h> | |
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c | |
index e89c28c..58482f3 100644 | |
--- a/drivers/media/video/msm/msm_mctl_buf.c | |
+++ b/drivers/media/video/msm/msm_mctl_buf.c | |
@@ -23,7 +23,6 @@ | |
#include <media/v4l2-ioctl.h> | |
#include <media/v4l2-device.h> | |
-#include <linux/android_pmem.h> | |
#include "msm.h" | |
#include "msm_ispif.h" | |
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c | |
index 2af95df..5c231c5 100644 | |
--- a/drivers/media/video/msm/msm_mctl_pp.c | |
+++ b/drivers/media/video/msm/msm_mctl_pp.c | |
@@ -25,7 +25,6 @@ | |
#include <media/v4l2-ioctl.h> | |
#include <media/v4l2-device.h> | |
-#include <linux/android_pmem.h> | |
#include "msm.h" | |
#include "msm_vpe.h" | |
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c | |
index 938b5cd..669f138 100644 | |
--- a/drivers/media/video/msm/msm_mem.c | |
+++ b/drivers/media/video/msm/msm_mem.c | |
@@ -26,7 +26,6 @@ | |
#include <media/v4l2-ioctl.h> | |
#include <media/v4l2-device.h> | |
-#include <linux/android_pmem.h> | |
#include "msm.h" | |
@@ -72,26 +71,6 @@ | |
static DEFINE_MUTEX(hlist_mut); | |
-#ifdef CONFIG_ANDROID_PMEM | |
-static int check_pmem_info(struct msm_pmem_info *info, int len) | |
-{ | |
- if (info->offset < len && | |
- info->offset + info->len <= len && | |
- info->planar0_off < len && | |
- info->planar1_off < len) | |
- return 0; | |
- | |
- pr_err("%s: check failed: off %d len %d y %d cbcr %d (total len %d)\n", | |
- __func__, | |
- info->offset, | |
- info->len, | |
- info->planar0_off, | |
- info->planar1_off, | |
- len); | |
- return -EINVAL; | |
-} | |
-#endif | |
- | |
static int check_overlap(struct hlist_head *ptype, | |
unsigned long paddr, | |
unsigned long len) | |
@@ -139,14 +118,6 @@ static int msm_pmem_table_add(struct hlist_head *ptype, | |
if (ion_map_iommu(client, region->handle, CAMERA_DOMAIN, GEN_POOL, | |
SZ_4K, 0, &paddr, &len, UNCACHED, 0) < 0) | |
goto out2; | |
-#elif CONFIG_ANDROID_PMEM | |
- rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file); | |
- if (rc < 0) { | |
- pr_err("%s: get_pmem_file fd %d error %d\n", | |
- __func__, info->fd, rc); | |
- goto out1; | |
- } | |
- region->file = file; | |
#else | |
paddr = 0; | |
file = NULL; | |
@@ -154,9 +125,6 @@ static int msm_pmem_table_add(struct hlist_head *ptype, | |
#endif | |
if (!info->len) | |
info->len = len; | |
- rc = check_pmem_info(info, len); | |
- if (rc < 0) | |
- goto out3; | |
paddr += info->offset; | |
len = info->len; | |
@@ -186,8 +154,6 @@ out3: | |
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
out2: | |
ion_free(client, region->handle); | |
-#elif CONFIG_ANDROID_PMEM | |
- put_pmem_file(region->file); | |
#endif | |
out1: | |
kfree(region); | |
@@ -247,8 +213,7 @@ static int __msm_pmem_table_del(struct hlist_head *ptype, | |
ion_unmap_iommu(client, region->handle, | |
CAMERA_DOMAIN, GEN_POOL); | |
ion_free(client, region->handle); | |
-#else | |
- put_pmem_file(region->file); | |
+ | |
#endif | |
kfree(region); | |
} | |
diff --git a/drivers/media/video/msm/msm_v4l2_video.c b/drivers/media/video/msm/msm_v4l2_video.c | |
index fb46cc1..cadbfb0 100644 | |
--- a/drivers/media/video/msm/msm_v4l2_video.c | |
+++ b/drivers/media/video/msm/msm_v4l2_video.c | |
@@ -22,7 +22,7 @@ | |
#include <linux/msm_mdp.h> | |
#include <linux/sched.h> | |
#include <linux/capability.h> | |
- | |
+#include <linux/module.h> | |
#include <media/v4l2-ioctl.h> | |
#include <media/videobuf-dma-sg.h> | |
#include <media/v4l2-dev.h> | |
@@ -723,6 +723,9 @@ msm_v4l2_overlay_mmap(struct file *filp, struct vm_area_struct * vma) | |
unsigned long off = vma->vm_pgoff << PAGE_SHIFT; | |
u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + v4l2_ram_size); | |
+ if (!start) | |
+ return -EINVAL; | |
+ | |
/* | |
* This is probably unnecessary now - the last PAGE_SHIFT | |
* bits of start should be 0 now, since we are page aligning | |
@@ -730,16 +733,21 @@ msm_v4l2_overlay_mmap(struct file *filp, struct vm_area_struct * vma) | |
*/ | |
start &= PAGE_MASK; | |
+ if ((vma->vm_end <= vma->vm_start) || | |
+ (off >= len) || | |
+ ((vma->vm_end - vma->vm_start) > (len - off))) { | |
+ pr_err("v4l2 map request, memory requested out of bounds\n"); | |
+ return -EINVAL; | |
+ } | |
+ | |
pr_debug("v4l2 map req for phys(%p,%p) offset %u to virt (%p,%p)\n", | |
(void *)(start+off), (void *)(start+off+(vma->vm_end - vma->vm_start)), | |
(unsigned int)off, (void *)vma->vm_start, (void *)vma->vm_end); | |
- if ((vma->vm_end - vma->vm_start + off) > len) { | |
- pr_err("v4l2 map request, memory requested too big\n"); | |
- return -EINVAL; | |
- } | |
- | |
start += off; | |
+ if (start < off) | |
+ return -EINVAL; | |
+ | |
vma->vm_pgoff = start >> PAGE_SHIFT; | |
/* This is an IO map - tell maydump to skip this VMA */ | |
vma->vm_flags |= VM_IO | VM_RESERVED; | |
diff --git a/drivers/media/video/msm/msm_vfe7x.c b/drivers/media/video/msm/msm_vfe7x.c | |
index bbf9d1b..d7ec547 100644 | |
--- a/drivers/media/video/msm/msm_vfe7x.c | |
+++ b/drivers/media/video/msm/msm_vfe7x.c | |
@@ -14,7 +14,7 @@ | |
#include <linux/msm_adsp.h> | |
#include <linux/uaccess.h> | |
#include <linux/fs.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <linux/slab.h> | |
#include <mach/msm_adsp.h> | |
#include <mach/clk.h> | |
diff --git a/drivers/media/video/msm/msm_vfe7x27a.c b/drivers/media/video/msm/msm_vfe7x27a.c | |
index 0279c78..dae2b6e 100644 | |
--- a/drivers/media/video/msm/msm_vfe7x27a.c | |
+++ b/drivers/media/video/msm/msm_vfe7x27a.c | |
@@ -13,7 +13,6 @@ | |
#include <linux/msm_adsp.h> | |
#include <linux/uaccess.h> | |
#include <linux/fs.h> | |
-#include <linux/android_pmem.h> | |
#include <linux/slab.h> | |
#include <linux/pm_qos.h> | |
#include <linux/delay.h> | |
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c | |
index ef11e4b..2489b99 100755 | |
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c | |
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c | |
@@ -14,7 +14,7 @@ | |
#include <linux/msm_adsp.h> | |
#include <linux/uaccess.h> | |
#include <linux/fs.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <linux/slab.h> | |
#include <linux/pm_qos.h> | |
#include <linux/delay.h> | |
diff --git a/drivers/media/video/msm/msm_vfe_stats_buf.c b/drivers/media/video/msm/msm_vfe_stats_buf.c | |
index c21664b..e1ae162 100644 | |
--- a/drivers/media/video/msm/msm_vfe_stats_buf.c | |
+++ b/drivers/media/video/msm/msm_vfe_stats_buf.c | |
@@ -25,7 +25,7 @@ | |
#include <media/v4l2-ioctl.h> | |
#include <media/v4l2-device.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <media/msm_camera.h> | |
#include <media/msm_isp.h> | |
#include "msm.h" | |
@@ -162,25 +162,6 @@ static int msm_stats_deinit(struct msm_stats_bufq_ctrl *stats_ctrl) | |
return rc; | |
} | |
-#ifdef CONFIG_ANDROID_PMEM | |
-static int msm_stats_check_pmem_info(struct msm_stats_buf_info *info, int len) | |
-{ | |
- if (info->offset < len && | |
- info->offset + info->len <= len && | |
- info->planar0_off < len && info->planar1_off < len) | |
- return 0; | |
- | |
- pr_err("%s: check failed: off %d len %d y %d cbcr %d (total len %d)\n", | |
- __func__, | |
- info->offset, | |
- info->len, | |
- info->planar0_off, | |
- info->planar1_off, | |
- len); | |
- return -EINVAL; | |
-} | |
-#endif | |
- | |
static int msm_stats_buf_prepare(struct msm_stats_bufq_ctrl *stats_ctrl, | |
struct msm_stats_buf_info *info, struct ion_client *client) | |
{ | |
@@ -225,14 +206,6 @@ static int msm_stats_buf_prepare(struct msm_stats_bufq_ctrl *stats_ctrl, | |
pr_err("%s: cannot map address", __func__); | |
goto out2; | |
} | |
-#elif CONFIG_ANDROID_PMEM | |
- rc = get_pmem_file(info->fd, &paddr, &kvstart, &len, &file); | |
- if (rc < 0) { | |
- pr_err("%s: get_pmem_file fd %d error %d\n", | |
- __func__, info->fd, rc); | |
- goto out1; | |
- } | |
- stats_buf->file = file; | |
#else | |
paddr = 0; | |
file = NULL; | |
@@ -240,11 +213,6 @@ static int msm_stats_buf_prepare(struct msm_stats_bufq_ctrl *stats_ctrl, | |
#endif | |
if (!info->len) | |
info->len = len; | |
- rc = msm_stats_check_pmem_info(info, len); | |
- if (rc < 0) { | |
- pr_err("%s: msm_stats_check_pmem_info err = %d", __func__, rc); | |
- goto out3; | |
- } | |
paddr += info->offset; | |
len = info->len; | |
stats_buf->paddr = paddr; | |
@@ -255,15 +223,14 @@ static int msm_stats_buf_prepare(struct msm_stats_bufq_ctrl *stats_ctrl, | |
D("%s pmem_stats address is 0x%ld\n", __func__, paddr); | |
stats_buf->state = MSM_STATS_BUFFER_STATE_PREPARED; | |
return 0; | |
-out3: | |
+ | |
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
ion_unmap_iommu(client, stats_buf->handle, CAMERA_DOMAIN, GEN_POOL); | |
#endif | |
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
out2: | |
ion_free(client, stats_buf->handle); | |
-#elif CONFIG_ANDROID_PMEM | |
- put_pmem_file(stats_buf->file); | |
+ | |
#endif | |
out1: | |
return rc; | |
@@ -294,8 +261,7 @@ static int msm_stats_buf_unprepare(struct msm_stats_bufq_ctrl *stats_ctrl, | |
ion_unmap_iommu(client, stats_buf->handle, | |
CAMERA_DOMAIN, GEN_POOL); | |
ion_free(client, stats_buf->handle); | |
-#else | |
- put_pmem_file(stats_buf->file); | |
+ | |
#endif | |
if (stats_buf->state == MSM_STATS_BUFFER_STATE_QUEUED) { | |
/* buf queued need delete from list */ | |
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c | |
index 887af95..4b60970 100644 | |
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c | |
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c | |
@@ -18,8 +18,6 @@ | |
#include <linux/spinlock.h> | |
#include <linux/init.h> | |
#include <linux/version.h> | |
-#include <linux/platform_device.h> | |
-#include <linux/android_pmem.h> | |
#include <linux/sched.h> | |
#include <linux/kthread.h> | |
#include <linux/time.h> | |
diff --git a/drivers/media/video/videobuf-msm-mem.c b/drivers/media/video/videobuf-msm-mem.c | |
index 9e2cc22..eeda13a 100644 | |
--- a/drivers/media/video/videobuf-msm-mem.c | |
+++ b/drivers/media/video/videobuf-msm-mem.c | |
@@ -24,7 +24,7 @@ | |
#include <linux/pagemap.h> | |
#include <linux/sched.h> | |
#include <linux/io.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <linux/memory_alloc.h> | |
#include <media/videobuf-msm-mem.h> | |
#include <media/msm_camera.h> | |
@@ -140,55 +140,6 @@ static const struct vm_operations_struct videobuf_vm_ops = { | |
.close = videobuf_vm_close, | |
}; | |
-/** | |
- * videobuf_pmem_contig_user_put() - reset pointer to user space buffer | |
- * @mem: per-buffer private videobuf-contig-pmem data | |
- * | |
- * This function resets the user space pointer | |
- */ | |
-static void videobuf_pmem_contig_user_put(struct videobuf_contig_pmem *mem) | |
-{ | |
- if (mem->phyaddr) { | |
- put_pmem_file(mem->file); | |
- mem->is_userptr = 0; | |
- mem->phyaddr = 0; | |
- mem->size = 0; | |
- } | |
-} | |
- | |
-/** | |
- * videobuf_pmem_contig_user_get() - setup user space memory pointer | |
- * @mem: per-buffer private videobuf-contig-pmem data | |
- * @vb: video buffer to map | |
- * | |
- * This function validates and sets up a pointer to user space memory. | |
- * Only physically contiguous pfn-mapped memory is accepted. | |
- * | |
- * Returns 0 if successful. | |
- */ | |
-static int videobuf_pmem_contig_user_get(struct videobuf_contig_pmem *mem, | |
- struct videobuf_buffer *vb) | |
-{ | |
- unsigned long kvstart; | |
- unsigned long len; | |
- int rc; | |
- | |
- mem->size = PAGE_ALIGN(vb->size); | |
- rc = get_pmem_file(vb->baddr, (unsigned long *)&mem->phyaddr, | |
- &kvstart, &len, &mem->file); | |
- if (rc < 0) { | |
- pr_err("%s: get_pmem_file fd %lu error %d\n", | |
- __func__, vb->baddr, | |
- rc); | |
- return rc; | |
- } | |
- mem->phyaddr += vb->boff; | |
- mem->y_off = 0; | |
- mem->cbcr_off = (vb->size)*2/3; | |
- mem->is_userptr = 1; | |
- return rc; | |
-} | |
- | |
static struct videobuf_buffer *__videobuf_alloc(size_t size) | |
{ | |
struct videobuf_contig_pmem *mem; | |
@@ -229,12 +180,6 @@ static int __videobuf_iolock(struct videobuf_queue *q, | |
/* All handling should be done by __videobuf_mmap_mapper() */ | |
break; | |
- case V4L2_MEMORY_USERPTR: | |
- D("%s memory method USERPTR\n", __func__); | |
- | |
- /* handle pointer from user space */ | |
- rc = videobuf_pmem_contig_user_get(mem, vb); | |
- break; | |
case V4L2_MEMORY_OVERLAY: | |
default: | |
pr_err("%s memory method OVERLAY/unknown\n", __func__); | |
@@ -383,7 +328,6 @@ int videobuf_pmem_contig_free(struct videobuf_queue *q, | |
/* handle user space pointer case */ | |
if (buf->baddr) { | |
- videobuf_pmem_contig_user_put(mem); | |
return 0; | |
} else { | |
/* don't support read() method */ | |
diff --git a/drivers/media/video/videobuf2-msm-mem.c b/drivers/media/video/videobuf2-msm-mem.c | |
index 8114d7a..76333d5 100644 | |
--- a/drivers/media/video/videobuf2-msm-mem.c | |
+++ b/drivers/media/video/videobuf2-msm-mem.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. | |
* | |
* Based on videobuf-dma-contig.c, | |
* (c) 2008 Magnus Damm | |
@@ -24,7 +24,7 @@ | |
#include <linux/pagemap.h> | |
#include <linux/sched.h> | |
#include <linux/io.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <linux/memory_alloc.h> | |
#include <media/videobuf2-msm-mem.h> | |
#include <media/msm_camera.h> | |
@@ -176,15 +176,14 @@ int videobuf2_pmem_contig_user_get(struct videobuf2_contig_pmem *mem, | |
uint32_t addr_offset, int path, | |
struct ion_client *client) | |
{ | |
- unsigned long len; | |
int rc = 0; | |
-#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION | |
- unsigned long kvstart; | |
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
+ unsigned long len; | |
#endif | |
unsigned long paddr = 0; | |
if (mem->phyaddr != 0) | |
return 0; | |
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
+#if defined(CONFIG_MSM_MULTIMEDIA_USE_ION) | |
mem->ion_handle = ion_import_dma_buf(client, (int)mem->vaddr); | |
if (IS_ERR_OR_NULL(mem->ion_handle)) { | |
pr_err("%s ION import failed\n", __func__); | |
@@ -194,17 +193,8 @@ int videobuf2_pmem_contig_user_get(struct videobuf2_contig_pmem *mem, | |
SZ_4K, 0, (unsigned long *)&mem->phyaddr, &len, UNCACHED, 0); | |
if (rc < 0) | |
ion_free(client, mem->ion_handle); | |
-#elif CONFIG_ANDROID_PMEM | |
- rc = get_pmem_file((int)mem->vaddr, (unsigned long *)&mem->phyaddr, | |
- &kvstart, &len, &mem->file); | |
- if (rc < 0) { | |
- pr_err("%s: get_pmem_file fd %d error %d\n", | |
- __func__, (int)mem->vaddr, rc); | |
- return rc; | |
- } | |
#else | |
paddr = 0; | |
- kvstart = 0; | |
#endif | |
if (offset) | |
mem->offset = *offset; | |
@@ -223,12 +213,10 @@ void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem, | |
struct ion_client *client) | |
{ | |
if (mem->is_userptr) { | |
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION | |
+#if defined(CONFIG_MSM_MULTIMEDIA_USE_ION) | |
ion_unmap_iommu(client, mem->ion_handle, | |
CAMERA_DOMAIN, GEN_POOL); | |
ion_free(client, mem->ion_handle); | |
-#elif CONFIG_ANDROID_PMEM | |
- put_pmem_file(mem->file); | |
#endif | |
} | |
mem->is_userptr = 0; | |
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c | |
index 5df8afb..fd41c10 100644 | |
--- a/drivers/misc/qseecom.c | |
+++ b/drivers/misc/qseecom.c | |
@@ -2,7 +2,7 @@ | |
/* Qualcomm Secure Execution Environment Communicator (QSEECOM) driver | |
* | |
- * Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2012, Code Aurora Forum. 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 and | |
@@ -28,7 +28,7 @@ | |
#include <linux/list.h> | |
#include <linux/mutex.h> | |
#include <linux/io.h> | |
-#include <linux/ion.h> | |
+#include <linux/msm_ion.h> | |
#include <linux/types.h> | |
#include <linux/clk.h> | |
#include <linux/qseecom.h> | |
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig | |
index bcec934..3b51c30 100644 | |
--- a/drivers/staging/Kconfig | |
+++ b/drivers/staging/Kconfig | |
@@ -84,7 +84,6 @@ source "drivers/staging/zram/Kconfig" | |
source "drivers/staging/zcache/Kconfig" | |
-source "drivers/staging/qcache/Kconfig" | |
source "drivers/staging/zsmalloc/Kconfig" | |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile | |
index c31f2ec..f70393c 100644 | |
--- a/drivers/staging/Makefile | |
+++ b/drivers/staging/Makefile | |
@@ -34,7 +34,7 @@ obj-$(CONFIG_DX_SEP) += sep/ | |
obj-$(CONFIG_IIO) += iio/ | |
obj-$(CONFIG_ZRAM) += zram/ | |
obj-$(CONFIG_ZCACHE) += zcache/ | |
-obj-$(CONFIG_QCACHE) += qcache/ | |
+# obj-$(CONFIG_QCACHE) += qcache/ | |
obj-$(CONFIG_ZSMALLOC) += zsmalloc/ | |
obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ | |
obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ | |
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c | |
index d2bc646..9d0c520 100644 | |
--- a/drivers/staging/android/binder.c | |
+++ b/drivers/staging/android/binder.c | |
@@ -35,7 +35,6 @@ | |
#include <linux/vmalloc.h> | |
#include <linux/slab.h> | |
#include <linux/security.h> | |
- | |
#include "binder.h" | |
static DEFINE_MUTEX(binder_lock); | |
@@ -1639,10 +1638,11 @@ static void binder_transaction(struct binder_proc *proc, | |
fp->cookie, node->cookie); | |
goto err_binder_get_ref_for_node_failed; | |
} | |
- if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { | |
+ if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { | |
return_error = BR_FAILED_REPLY; | |
goto err_binder_get_ref_for_node_failed; | |
} | |
+ | |
ref = binder_get_ref_for_node(target_proc, node); | |
if (ref == NULL) { | |
return_error = BR_FAILED_REPLY; | |
@@ -1672,10 +1672,11 @@ static void binder_transaction(struct binder_proc *proc, | |
return_error = BR_FAILED_REPLY; | |
goto err_binder_get_ref_failed; | |
} | |
- if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { | |
+ if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) { | |
return_error = BR_FAILED_REPLY; | |
goto err_binder_get_ref_failed; | |
} | |
+ | |
if (ref->node->proc == target_proc) { | |
if (fp->type == BINDER_TYPE_HANDLE) | |
fp->type = BINDER_TYPE_BINDER; | |
@@ -1729,7 +1730,7 @@ static void binder_transaction(struct binder_proc *proc, | |
return_error = BR_FAILED_REPLY; | |
goto err_fget_failed; | |
} | |
- if (security_binder_transfer_file(proc->tsk, target_proc->tsk, file) < 0) { | |
+ if (security_binder_transfer_file(proc->tsk, target_proc->tsk, file) < 0) { | |
fput(file); | |
return_error = BR_FAILED_REPLY; | |
goto err_get_unused_fd_failed; | |
diff --git a/drivers/staging/qcache/Kconfig b/drivers/staging/qcache/Kconfig | |
deleted file mode 100644 | |
index 389341c..0000000 | |
--- a/drivers/staging/qcache/Kconfig | |
+++ /dev/null | |
@@ -1,8 +0,0 @@ | |
-config QCACHE | |
- tristate "Dynamic compression of clean pagecache pages" | |
- depends on CLEANCACHE | |
- select LZO_COMPRESS | |
- select LZO_DECOMPRESS | |
- default n | |
- help | |
- Qcache is the backend for fmem | |
diff --git a/drivers/staging/qcache/Makefile b/drivers/staging/qcache/Makefile | |
deleted file mode 100644 | |
index 4fdf05c..0000000 | |
--- a/drivers/staging/qcache/Makefile | |
+++ /dev/null | |
@@ -1,3 +0,0 @@ | |
-qcache-y := qcache-main.o tmem.o fmem.o | |
- | |
-obj-$(CONFIG_QCACHE) += qcache.o | |
diff --git a/drivers/staging/qcache/fmem.c b/drivers/staging/qcache/fmem.c | |
deleted file mode 100644 | |
index 0609f4a..0000000 | |
--- a/drivers/staging/qcache/fmem.c | |
+++ /dev/null | |
@@ -1,344 +0,0 @@ | |
-/* | |
- * | |
- * Copyright (c) 2011-2012, The Linux Foundation. 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 and | |
- * only 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. | |
- * | |
- */ | |
- | |
-#include <linux/export.h> | |
-#include <linux/fmem.h> | |
-#include <linux/platform_device.h> | |
-#include <linux/io.h> | |
-#ifdef CONFIG_MEMORY_HOTPLUG | |
-#include <linux/memory.h> | |
-#include <linux/memory_hotplug.h> | |
-#endif | |
-#include "tmem.h" | |
-#include <asm/mach/map.h> | |
- | |
-struct fmem_data fmem_data; | |
-enum fmem_state fmem_state; | |
-static spinlock_t fmem_state_lock; | |
- | |
-#ifdef CONFIG_MEMORY_HOTPLUG | |
-static unsigned int section_powered_off[NR_MEM_SECTIONS]; | |
-static unsigned int fmem_section_start, fmem_section_end; | |
-#endif | |
- | |
-void *fmem_map_virtual_area(int cacheability) | |
-{ | |
- unsigned long addr; | |
- const struct mem_type *type; | |
- int ret; | |
- | |
- addr = (unsigned long) fmem_data.area->addr; | |
- type = get_mem_type(cacheability); | |
- ret = ioremap_pages(addr, fmem_data.phys, fmem_data.size, type); | |
- if (ret) | |
- return ERR_PTR(ret); | |
- | |
- fmem_data.virt = fmem_data.area->addr; | |
- | |
- return fmem_data.virt; | |
-} | |
- | |
-void fmem_unmap_virtual_area(void) | |
-{ | |
- unmap_kernel_range((unsigned long)fmem_data.virt, fmem_data.size); | |
- fmem_data.virt = NULL; | |
-} | |
- | |
-static int fmem_probe(struct platform_device *pdev) | |
-{ | |
- struct fmem_platform_data *pdata = pdev->dev.platform_data; | |
- | |
- if (!pdata->phys) | |
- pdata->phys = allocate_contiguous_ebi_nomap(pdata->size, | |
- pdata->align); | |
- | |
-#ifdef CONFIG_MEMORY_HOTPLUG | |
- fmem_section_start = pdata->phys >> PA_SECTION_SHIFT; | |
- fmem_section_end = (pdata->phys - 1 + pdata->size) >> PA_SECTION_SHIFT; | |
-#endif | |
- fmem_data.phys = pdata->phys + pdata->reserved_size_low; | |
- fmem_data.size = pdata->size - pdata->reserved_size_low - | |
- pdata->reserved_size_high; | |
- fmem_data.reserved_size_low = pdata->reserved_size_low; | |
- fmem_data.reserved_size_high = pdata->reserved_size_high; | |
- | |
- if (!fmem_data.size) | |
- return -ENODEV; | |
- | |
- fmem_data.area = get_vm_area(fmem_data.size, VM_IOREMAP); | |
- if (!fmem_data.area) | |
- return -ENOMEM; | |
- | |
- if (!fmem_map_virtual_area(MT_DEVICE_CACHED)) { | |
- remove_vm_area(fmem_data.area->addr); | |
- return -ENOMEM; | |
- } | |
- pr_info("fmem phys %lx virt %p size %lx\n", | |
- fmem_data.phys, fmem_data.virt, fmem_data.size); | |
- | |
- spin_lock_init(&fmem_state_lock); | |
- | |
- return 0; | |
-} | |
- | |
-static int fmem_remove(struct platform_device *pdev) | |
-{ | |
- return 0; | |
-} | |
- | |
-static struct platform_driver fmem_driver = { | |
- .probe = fmem_probe, | |
- .remove = fmem_remove, | |
- .driver = { .name = "fmem" } | |
-}; | |
- | |
-#ifdef CONFIG_SYSFS | |
-static ssize_t fmem_state_show(struct kobject *kobj, | |
- struct kobj_attribute *attr, | |
- char *buf) | |
-{ | |
- if (fmem_state == FMEM_T_STATE) | |
- return snprintf(buf, 3, "t\n"); | |
- else if (fmem_state == FMEM_C_STATE) | |
- return snprintf(buf, 3, "c\n"); | |
-#ifdef CONFIG_MEMORY_HOTPLUG | |
- else if (fmem_state == FMEM_O_STATE) | |
- return snprintf(buf, 3, "o\n"); | |
-#endif | |
- else if (fmem_state == FMEM_UNINITIALIZED) | |
- return snprintf(buf, 15, "uninitialized\n"); | |
- return snprintf(buf, 3, "?\n"); | |
-} | |
- | |
-static ssize_t fmem_state_store(struct kobject *kobj, | |
- struct kobj_attribute *attr, | |
- const char *buf, size_t count) | |
-{ | |
- int ret = -EINVAL; | |
- | |
- if (!strncmp(buf, "t", 1)) | |
- ret = fmem_set_state(FMEM_T_STATE); | |
- else if (!strncmp(buf, "c", 1)) | |
- ret = fmem_set_state(FMEM_C_STATE); | |
-#ifdef CONFIG_MEMORY_HOTPLUG | |
- else if (!strncmp(buf, "o", 1)) | |
- ret = fmem_set_state(FMEM_O_STATE); | |
-#endif | |
- if (ret) | |
- return ret; | |
- return 1; | |
-} | |
- | |
-static struct kobj_attribute fmem_state_attr = { | |
- .attr = { .name = "state", .mode = 0644 }, | |
- .show = fmem_state_show, | |
- .store = fmem_state_store, | |
-}; | |
- | |
-static struct attribute *fmem_attrs[] = { | |
- &fmem_state_attr.attr, | |
- NULL, | |
-}; | |
- | |
-static struct attribute_group fmem_attr_group = { | |
- .attrs = fmem_attrs, | |
- .name = "fmem", | |
-}; | |
- | |
-static int fmem_create_sysfs(void) | |
-{ | |
- int ret = 0; | |
- | |
- ret = sysfs_create_group(mm_kobj, &fmem_attr_group); | |
- if (ret) | |
- pr_err("fmem: can't create sysfs\n"); | |
- return ret; | |
-} | |
- | |
-#endif | |
- | |
-#ifdef CONFIG_MEMORY_HOTPLUG | |
-bool fmem_is_disjoint(unsigned long start_pfn, unsigned long nr_pages) | |
-{ | |
- unsigned long fmem_start_pfn, fmem_end_pfn; | |
- unsigned long unstable_end_pfn; | |
- unsigned long highest_start_pfn, lowest_end_pfn; | |
- | |
- fmem_start_pfn = (fmem_data.phys - fmem_data.reserved_size_low) | |
- >> PAGE_SHIFT; | |
- fmem_end_pfn = (fmem_data.phys + fmem_data.size + | |
- fmem_data.reserved_size_high - 1) >> PAGE_SHIFT; | |
- unstable_end_pfn = start_pfn + nr_pages - 1; | |
- | |
- highest_start_pfn = max(fmem_start_pfn, start_pfn); | |
- lowest_end_pfn = min(fmem_end_pfn, unstable_end_pfn); | |
- | |
- return lowest_end_pfn < highest_start_pfn; | |
-} | |
- | |
-static int fmem_mem_going_offline_callback(void *arg) | |
-{ | |
- struct memory_notify *marg = arg; | |
- | |
- if (fmem_is_disjoint(marg->start_pfn, marg->nr_pages)) | |
- return 0; | |
- return fmem_set_state(FMEM_O_STATE); | |
-} | |
- | |
-static void fmem_mem_online_callback(void *arg) | |
-{ | |
- struct memory_notify *marg = arg; | |
- int i; | |
- | |
- section_powered_off[marg->start_pfn >> PFN_SECTION_SHIFT] = 0; | |
- | |
- if (fmem_state != FMEM_O_STATE) | |
- return; | |
- | |
- for (i = fmem_section_start; i <= fmem_section_end; i++) { | |
- if (section_powered_off[i]) | |
- return; | |
- } | |
- | |
- fmem_set_state(FMEM_T_STATE); | |
-} | |
- | |
-static void fmem_mem_offline_callback(void *arg) | |
-{ | |
- struct memory_notify *marg = arg; | |
- | |
- section_powered_off[marg->start_pfn >> PFN_SECTION_SHIFT] = 1; | |
-} | |
- | |
-static int fmem_memory_callback(struct notifier_block *self, | |
- unsigned long action, void *arg) | |
-{ | |
- int ret = 0; | |
- | |
- if (fmem_state == FMEM_UNINITIALIZED) | |
- return NOTIFY_OK; | |
- | |
- switch (action) { | |
- case MEM_ONLINE: | |
- fmem_mem_online_callback(arg); | |
- break; | |
- case MEM_GOING_OFFLINE: | |
- ret = fmem_mem_going_offline_callback(arg); | |
- break; | |
- case MEM_OFFLINE: | |
- fmem_mem_offline_callback(arg); | |
- break; | |
- case MEM_GOING_ONLINE: | |
- case MEM_CANCEL_ONLINE: | |
- case MEM_CANCEL_OFFLINE: | |
- break; | |
- } | |
- if (ret) | |
- ret = notifier_from_errno(ret); | |
- else | |
- ret = NOTIFY_OK; | |
- return ret; | |
-} | |
-#endif | |
- | |
-static int __init fmem_init(void) | |
-{ | |
-#ifdef CONFIG_MEMORY_HOTPLUG | |
- hotplug_memory_notifier(fmem_memory_callback, 0); | |
-#endif | |
- return platform_driver_register(&fmem_driver); | |
-} | |
- | |
-static void __exit fmem_exit(void) | |
-{ | |
- platform_driver_unregister(&fmem_driver); | |
-} | |
- | |
-struct fmem_data *fmem_get_info(void) | |
-{ | |
- return &fmem_data; | |
-} | |
-EXPORT_SYMBOL(fmem_get_info); | |
- | |
-void lock_fmem_state(void) | |
-{ | |
- spin_lock(&fmem_state_lock); | |
-} | |
- | |
-void unlock_fmem_state(void) | |
-{ | |
- spin_unlock(&fmem_state_lock); | |
-} | |
- | |
-int fmem_set_state(enum fmem_state new_state) | |
-{ | |
- int ret = 0; | |
- int create_sysfs = 0; | |
- | |
- lock_fmem_state(); | |
- if (fmem_state == new_state) | |
- goto out; | |
- | |
- if (fmem_state == FMEM_UNINITIALIZED) { | |
- if (new_state == FMEM_T_STATE) { | |
- tmem_enable(); | |
- create_sysfs = 1; | |
- goto out_set; | |
- } else { | |
- ret = -EINVAL; | |
- goto out; | |
- } | |
- } | |
- | |
-#ifdef CONFIG_MEMORY_HOTPLUG | |
- if (fmem_state == FMEM_C_STATE && new_state == FMEM_O_STATE) { | |
- ret = -EAGAIN; | |
- goto out; | |
- } | |
- | |
- if (fmem_state == FMEM_O_STATE && new_state == FMEM_C_STATE) { | |
- pr_warn("attempting to use powered off memory as fmem\n"); | |
- ret = -EAGAIN; | |
- goto out; | |
- } | |
-#endif | |
- | |
- if (new_state == FMEM_T_STATE) { | |
- void *v; | |
- v = fmem_map_virtual_area(MT_DEVICE_CACHED); | |
- if (IS_ERR_OR_NULL(v)) { | |
- ret = PTR_ERR(v); | |
- goto out; | |
- } | |
- tmem_enable(); | |
- } else { | |
- tmem_disable(); | |
- fmem_unmap_virtual_area(); | |
- } | |
- | |
-out_set: | |
- fmem_state = new_state; | |
-out: | |
- unlock_fmem_state(); | |
-#ifdef CONFIG_SYSFS | |
- if (create_sysfs) | |
- fmem_create_sysfs(); | |
-#endif | |
- return ret; | |
-} | |
-EXPORT_SYMBOL(fmem_set_state); | |
- | |
-arch_initcall(fmem_init); | |
-module_exit(fmem_exit); | |
diff --git a/drivers/staging/qcache/qcache-main.c b/drivers/staging/qcache/qcache-main.c | |
deleted file mode 100644 | |
index f416cfc..0000000 | |
--- a/drivers/staging/qcache/qcache-main.c | |
+++ /dev/null | |
@@ -1,1358 +0,0 @@ | |
-/* | |
- * Copyright (c) 2010,2011, Dan Magenheimer, Oracle Corp. | |
- * Copyright (c) 2010,2011, Nitin Gupta | |
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. | |
- * | |
- * Qcache provides an in-kernel "host implementation" for transcendent memory | |
- * and, thus indirectly, for cleancache and frontswap. Qcache includes a | |
- * page-accessible memory [1] interface, utilizing lzo1x compression: | |
- * 1) "compression buddies" ("zbud") is used for ephemeral pages | |
- * Zbud allows pairs (and potentially, | |
- * in the future, more than a pair of) compressed pages to be closely linked | |
- * so that reclaiming can be done via the kernel's physical-page-oriented | |
- * "shrinker" interface. | |
- * | |
- * [1] For a definition of page-accessible memory (aka PAM), see: | |
- * 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/bitmap.h> | |
-#include <linux/fmem.h> | |
-#include "tmem.h" | |
- | |
-#if !defined(CONFIG_CLEANCACHE) | |
-#error "qcache is useless without CONFIG_CLEANCACHE" | |
-#endif | |
-#include <linux/cleancache.h> | |
- | |
-#define ZCACHE_GFP_MASK \ | |
- (__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC) | |
- | |
-#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 xv_pool *xvpool; | |
- bool allocated; | |
- atomic_t refcount; | |
-}; | |
- | |
-struct qcache_info { | |
- void *addr; | |
- unsigned long *bitmap; | |
- spinlock_t lock; | |
- unsigned pages; | |
-}; | |
-static struct qcache_info qcache_info; | |
-static unsigned long zcache_qc_allocated; | |
-static unsigned long zcache_qc_freed; | |
-static unsigned long zcache_qc_used; | |
-static unsigned long zcache_qc_max_used; | |
- | |
-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; | |
-} | |
- | |
-/********** | |
- * Compression buddies ("zbud") provides for packing two (or, possibly | |
- * in the future, more) compressed ephemeral pages into a single "raw" | |
- * (physical) page and tracking them with data structures so that | |
- * the raw pages can be easily reclaimed. | |
- * | |
- * A zbud page ("zbpg") is an aligned page containing a list_head, | |
- * a lock, and two "zbud headers". The remainder of the physical | |
- * page is divided up into aligned 64-byte "chunks" which contain | |
- * the compressed data for zero, one, or two zbuds. Each zbpg | |
- * resides on: (1) an "unused list" if it has no zbuds; (2) a | |
- * "buddied" list if it is fully populated with two zbuds; or | |
- * (3) one of PAGE_SIZE/64 "unbuddied" lists indexed by how many chunks | |
- * the one unbuddied zbud uses. The data inside a zbpg cannot be | |
- * read or written unless the zbpg's lock is held. | |
- */ | |
- | |
-#define ZBH_SENTINEL 0x43214321 | |
-#define ZBPG_SENTINEL 0xdeadbeef | |
- | |
-#define ZBUD_MAX_BUDS 2 | |
- | |
-struct zbud_hdr { | |
- 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 */ | |
- DECL_SENTINEL | |
-}; | |
- | |
-struct zbud_page { | |
- struct list_head bud_list; | |
- spinlock_t lock; | |
- struct zbud_hdr buddy[ZBUD_MAX_BUDS]; | |
- DECL_SENTINEL | |
- /* followed by NUM_CHUNK aligned CHUNK_SIZE-byte chunks */ | |
-}; | |
- | |
-#define CHUNK_SHIFT 6 | |
-#define CHUNK_SIZE (1 << CHUNK_SHIFT) | |
-#define CHUNK_MASK (~(CHUNK_SIZE-1)) | |
-#define NCHUNKS (((PAGE_SIZE - sizeof(struct zbud_page)) & \ | |
- CHUNK_MASK) >> CHUNK_SHIFT) | |
-#define MAX_CHUNK (NCHUNKS-1) | |
- | |
-static struct { | |
- struct list_head list; | |
- unsigned count; | |
-} zbud_unbuddied[NCHUNKS]; | |
-/* list N contains pages with N chunks USED and NCHUNKS-N unused */ | |
-/* element 0 is never used but optimizing that isn't worth it */ | |
-static unsigned long zbud_cumul_chunk_counts[NCHUNKS]; | |
- | |
-struct list_head zbud_buddied_list; | |
-static unsigned long zcache_zbud_buddied_count; | |
- | |
-/* protects the buddied list and all unbuddied lists */ | |
-static DEFINE_SPINLOCK(zbud_budlists_spinlock); | |
- | |
-static atomic_t zcache_zbud_curr_raw_pages; | |
-static atomic_t zcache_zbud_curr_zpages; | |
-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); | |
- | |
-static void *qcache_alloc(void) | |
-{ | |
- void *addr; | |
- unsigned long flags; | |
- int offset; | |
- struct qcache_info *qc = &qcache_info; | |
- | |
- spin_lock_irqsave(&qc->lock, flags); | |
- offset = bitmap_find_free_region(qc->bitmap, qc->pages, 0); | |
- | |
- if (offset < 0) { | |
- spin_unlock_irqrestore(&qc->lock, flags); | |
- return NULL; | |
- } | |
- | |
- zcache_qc_allocated++; | |
- zcache_qc_used++; | |
- zcache_qc_max_used = max(zcache_qc_max_used, zcache_qc_used); | |
- spin_unlock_irqrestore(&qc->lock, flags); | |
- | |
- addr = qc->addr + offset * PAGE_SIZE; | |
- | |
- return addr; | |
-} | |
- | |
-static void qcache_free(void *addr) | |
-{ | |
- unsigned long flags; | |
- int offset; | |
- struct qcache_info *qc = &qcache_info; | |
- | |
- offset = (addr - qc->addr) / PAGE_SIZE; | |
- | |
- spin_lock_irqsave(&qc->lock, flags); | |
- bitmap_release_region(qc->bitmap, offset, 0); | |
- | |
- zcache_qc_freed++; | |
- zcache_qc_used--; | |
- spin_unlock_irqrestore(&qc->lock, flags); | |
-} | |
- | |
-/* | |
- * zbud helper functions | |
- */ | |
- | |
-static inline unsigned zbud_max_buddy_size(void) | |
-{ | |
- return MAX_CHUNK << CHUNK_SHIFT; | |
-} | |
- | |
-static inline unsigned zbud_size_to_chunks(unsigned size) | |
-{ | |
- BUG_ON(size == 0 || size > zbud_max_buddy_size()); | |
- return (size + CHUNK_SIZE - 1) >> CHUNK_SHIFT; | |
-} | |
- | |
-static inline int zbud_budnum(struct zbud_hdr *zh) | |
-{ | |
- unsigned offset = (unsigned long)zh & (PAGE_SIZE - 1); | |
- struct zbud_page *zbpg = NULL; | |
- unsigned budnum = -1U; | |
- int i; | |
- | |
- for (i = 0; i < ZBUD_MAX_BUDS; i++) | |
- if (offset == offsetof(typeof(*zbpg), buddy[i])) { | |
- budnum = i; | |
- break; | |
- } | |
- BUG_ON(budnum == -1U); | |
- return budnum; | |
-} | |
- | |
-static char *zbud_data(struct zbud_hdr *zh, unsigned size) | |
-{ | |
- struct zbud_page *zbpg; | |
- char *p; | |
- unsigned budnum; | |
- | |
- ASSERT_SENTINEL(zh, ZBH); | |
- budnum = zbud_budnum(zh); | |
- BUG_ON(size == 0 || size > zbud_max_buddy_size()); | |
- zbpg = container_of(zh, struct zbud_page, buddy[budnum]); | |
- p = (char *)zbpg; | |
- if (budnum == 0) | |
- p += ((sizeof(struct zbud_page) + CHUNK_SIZE - 1) & | |
- CHUNK_MASK); | |
- else if (budnum == 1) | |
- p += PAGE_SIZE - ((size + CHUNK_SIZE - 1) & CHUNK_MASK); | |
- return p; | |
-} | |
- | |
-/* | |
- * zbud raw page management | |
- */ | |
- | |
-static struct zbud_page *zbud_alloc_raw_page(void) | |
-{ | |
- struct zbud_page *zbpg = NULL; | |
- struct zbud_hdr *zh0, *zh1; | |
- | |
- zbpg = zcache_get_free_page(); | |
- if (likely(zbpg != NULL)) { | |
- INIT_LIST_HEAD(&zbpg->bud_list); | |
- zh0 = &zbpg->buddy[0]; zh1 = &zbpg->buddy[1]; | |
- spin_lock_init(&zbpg->lock); | |
- atomic_inc(&zcache_zbud_curr_raw_pages); | |
- INIT_LIST_HEAD(&zbpg->bud_list); | |
- SET_SENTINEL(zbpg, ZBPG); | |
- zh0->size = 0; zh1->size = 0; | |
- tmem_oid_set_invalid(&zh0->oid); | |
- tmem_oid_set_invalid(&zh1->oid); | |
- } | |
- return zbpg; | |
-} | |
- | |
-static void zbud_free_raw_page(struct zbud_page *zbpg) | |
-{ | |
- struct zbud_hdr *zh0 = &zbpg->buddy[0], *zh1 = &zbpg->buddy[1]; | |
- | |
- ASSERT_SENTINEL(zbpg, ZBPG); | |
- BUG_ON(!list_empty(&zbpg->bud_list)); | |
- BUG_ON(zh0->size != 0 || tmem_oid_valid(&zh0->oid)); | |
- BUG_ON(zh1->size != 0 || tmem_oid_valid(&zh1->oid)); | |
- INVERT_SENTINEL(zbpg, ZBPG); | |
- spin_unlock(&zbpg->lock); | |
- qcache_free(zbpg); | |
-} | |
- | |
-/* | |
- * core zbud handling routines | |
- */ | |
- | |
-static unsigned zbud_free(struct zbud_hdr *zh) | |
-{ | |
- unsigned size; | |
- | |
- ASSERT_SENTINEL(zh, ZBH); | |
- BUG_ON(!tmem_oid_valid(&zh->oid)); | |
- size = zh->size; | |
- BUG_ON(zh->size == 0 || zh->size > zbud_max_buddy_size()); | |
- zh->size = 0; | |
- tmem_oid_set_invalid(&zh->oid); | |
- INVERT_SENTINEL(zh, ZBH); | |
- zcache_zbud_curr_zbytes -= size; | |
- atomic_dec(&zcache_zbud_curr_zpages); | |
- return size; | |
-} | |
- | |
-static void zbud_free_and_delist(struct zbud_hdr *zh) | |
-{ | |
- unsigned chunks; | |
- struct zbud_hdr *zh_other; | |
- unsigned budnum = zbud_budnum(zh), size; | |
- struct zbud_page *zbpg = | |
- container_of(zh, struct zbud_page, buddy[budnum]); | |
- | |
- spin_lock(&zbpg->lock); | |
- if (list_empty(&zbpg->bud_list)) { | |
- spin_unlock(&zbpg->lock); | |
- return; | |
- } | |
- size = zbud_free(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--; | |
- spin_unlock(&zbud_budlists_spinlock); | |
- 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); | |
- zbud_unbuddied[chunks].count++; | |
- spin_unlock(&zbud_budlists_spinlock); | |
- spin_unlock(&zbpg->lock); | |
- } | |
-} | |
- | |
-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) | |
-{ | |
- struct zbud_hdr *zh0, *zh1, *zh = NULL; | |
- struct zbud_page *zbpg = NULL, *ztmp; | |
- unsigned nchunks; | |
- char *to; | |
- int i, found_good_buddy = 0; | |
- | |
- nchunks = zbud_size_to_chunks(size) ; | |
- for (i = MAX_CHUNK - nchunks + 1; i > 0; i--) { | |
- spin_lock(&zbud_budlists_spinlock); | |
- if (!list_empty(&zbud_unbuddied[i].list)) { | |
- list_for_each_entry_safe(zbpg, ztmp, | |
- &zbud_unbuddied[i].list, bud_list) { | |
- if (spin_trylock(&zbpg->lock)) { | |
- found_good_buddy = i; | |
- goto found_unbuddied; | |
- } | |
- } | |
- } | |
- spin_unlock(&zbud_budlists_spinlock); | |
- } | |
- /* didn't find a good buddy, try allocating a new page */ | |
- zbpg = zbud_alloc_raw_page(); | |
- 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); | |
- list_add_tail(&zbpg->bud_list, &zbud_unbuddied[nchunks].list); | |
- zbud_unbuddied[nchunks].count++; | |
- zh = &zbpg->buddy[0]; | |
- goto init_zh; | |
- | |
-found_unbuddied: | |
- zh0 = &zbpg->buddy[0]; zh1 = &zbpg->buddy[1]; | |
- BUG_ON(!((zh0->size == 0) ^ (zh1->size == 0))); | |
- if (zh0->size != 0) { /* buddy0 in use, buddy1 is vacant */ | |
- ASSERT_SENTINEL(zh0, ZBH); | |
- zh = zh1; | |
- } else if (zh1->size != 0) { /* buddy1 in use, buddy0 is vacant */ | |
- ASSERT_SENTINEL(zh1, ZBH); | |
- zh = zh0; | |
- } else | |
- BUG(); | |
- list_del_init(&zbpg->bud_list); | |
- zbud_unbuddied[found_good_buddy].count--; | |
- list_add_tail(&zbpg->bud_list, &zbud_buddied_list); | |
- zcache_zbud_buddied_count++; | |
- | |
-init_zh: | |
- SET_SENTINEL(zh, ZBH); | |
- zh->size = size; | |
- zh->index = index; | |
- zh->oid = *oid; | |
- zh->pool_id = pool_id; | |
- zh->client_id = client_id; | |
- /* can wait to copy the data until the list locks are dropped */ | |
- spin_unlock(&zbud_budlists_spinlock); | |
- | |
- to = zbud_data(zh, size); | |
- memcpy(to, cdata, size); | |
- spin_unlock(&zbpg->lock); | |
- zbud_cumul_chunk_counts[nchunks]++; | |
- atomic_inc(&zcache_zbud_curr_zpages); | |
- zcache_zbud_cumul_zpages++; | |
- zcache_zbud_curr_zbytes += size; | |
- zcache_zbud_cumul_zbytes += size; | |
-out: | |
- return zh; | |
-} | |
- | |
-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; | |
- char *to_va, *from_va; | |
- unsigned size; | |
- int ret = 0; | |
- | |
- zbpg = container_of(zh, struct zbud_page, buddy[budnum]); | |
- spin_lock(&zbpg->lock); | |
- if (list_empty(&zbpg->bud_list)) { | |
- ret = -EINVAL; | |
- goto out; | |
- } | |
- ASSERT_SENTINEL(zh, ZBH); | |
- BUG_ON(zh->size == 0 || zh->size > zbud_max_buddy_size()); | |
- to_va = kmap_atomic(page); | |
- 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); | |
- BUG_ON(out_len != PAGE_SIZE); | |
- kunmap_atomic(to_va); | |
-out: | |
- spin_unlock(&zbpg->lock); | |
- return ret; | |
-} | |
- | |
-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); | |
- | |
-static void zbud_init(void) | |
-{ | |
- int i; | |
- | |
- INIT_LIST_HEAD(&zbud_buddied_list); | |
- zcache_zbud_buddied_count = 0; | |
- for (i = 0; i < NCHUNKS; i++) { | |
- INIT_LIST_HEAD(&zbud_unbuddied[i].list); | |
- zbud_unbuddied[i].count = 0; | |
- } | |
-} | |
- | |
-#ifdef CONFIG_SYSFS | |
-/* | |
- * These sysfs routines show a nice distribution of how many zbpg's are | |
- * currently (and have ever been placed) in each unbuddied list. It's fun | |
- * to watch but can probably go away before final merge. | |
- */ | |
-static int zbud_show_unbuddied_list_counts(char *buf) | |
-{ | |
- int i; | |
- char *p = buf; | |
- | |
- for (i = 0; i < NCHUNKS; i++) | |
- p += sprintf(p, "%u ", zbud_unbuddied[i].count); | |
- return p - buf; | |
-} | |
- | |
-static int zbud_show_cumul_chunk_counts(char *buf) | |
-{ | |
- unsigned long i, chunks = 0, total_chunks = 0, sum_total_chunks = 0; | |
- unsigned long total_chunks_lte_21 = 0, total_chunks_lte_32 = 0; | |
- unsigned long total_chunks_lte_42 = 0; | |
- char *p = buf; | |
- | |
- for (i = 0; i < NCHUNKS; i++) { | |
- p += sprintf(p, "%lu ", zbud_cumul_chunk_counts[i]); | |
- chunks += zbud_cumul_chunk_counts[i]; | |
- total_chunks += zbud_cumul_chunk_counts[i]; | |
- sum_total_chunks += i * zbud_cumul_chunk_counts[i]; | |
- if (i == 21) | |
- total_chunks_lte_21 = total_chunks; | |
- if (i == 32) | |
- total_chunks_lte_32 = total_chunks; | |
- if (i == 42) | |
- total_chunks_lte_42 = total_chunks; | |
- } | |
- p += sprintf(p, "<=21:%lu <=32:%lu <=42:%lu, mean:%lu\n", | |
- total_chunks_lte_21, total_chunks_lte_32, total_chunks_lte_42, | |
- chunks == 0 ? 0 : sum_total_chunks / chunks); | |
- return p - buf; | |
-} | |
-#endif | |
- | |
-/* | |
- * zcache core code starts here | |
- */ | |
- | |
-/* useful stats not collected by cleancache or frontswap */ | |
-static unsigned long zcache_flush_total; | |
-static unsigned long zcache_flush_found; | |
-static unsigned long zcache_flobj_total; | |
-static unsigned long zcache_flobj_found; | |
-static unsigned long zcache_failed_eph_puts; | |
- | |
-/* | |
- * Tmem operations assume the poolid implies the invoking client. | |
- * 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(uint16_t cli_id, uint16_t poolid) | |
-{ | |
- struct tmem_pool *pool = NULL; | |
- struct zcache_client *cli = NULL; | |
- | |
- 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) | |
-{ | |
- 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; | |
- 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 | |
- * either just use kmalloc, or perhaps add a slab-like allocator | |
- * to more carefully manage total memory utilization | |
- */ | |
-static struct kmem_cache *zcache_objnode_cache; | |
-static struct kmem_cache *zcache_obj_cache; | |
-static atomic_t zcache_curr_obj_count = ATOMIC_INIT(0); | |
-static unsigned long zcache_curr_obj_count_max; | |
-static atomic_t zcache_curr_objnode_count = ATOMIC_INIT(0); | |
-static unsigned long zcache_curr_objnode_count_max; | |
- | |
-/* | |
- * to avoid memory allocation recursion (e.g. due to direct reclaim), we | |
- * preload all necessary data structures so the hostops callbacks never | |
- * actually do a malloc | |
- */ | |
-struct zcache_preload { | |
- void *page; | |
- struct tmem_obj *obj; | |
- int nr; | |
- struct tmem_objnode *objnodes[OBJNODE_TREE_MAX_PATH]; | |
-}; | |
-static DEFINE_PER_CPU(struct zcache_preload, zcache_preloads) = { 0, }; | |
- | |
-static int zcache_do_preload(struct tmem_pool *pool) | |
-{ | |
- struct zcache_preload *kp; | |
- struct tmem_objnode *objnode; | |
- struct tmem_obj *obj; | |
- void *page; | |
- int ret = -ENOMEM; | |
- | |
- if (unlikely(zcache_objnode_cache == NULL)) | |
- 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)) { | |
- preempt_enable_no_resched(); | |
- objnode = kmem_cache_alloc(zcache_objnode_cache, | |
- ZCACHE_GFP_MASK); | |
- if (unlikely(objnode == NULL)) { | |
- zcache_failed_alloc++; | |
- goto unlock_out; | |
- } | |
- preempt_disable(); | |
- kp = &__get_cpu_var(zcache_preloads); | |
- if (kp->nr < ARRAY_SIZE(kp->objnodes)) | |
- kp->objnodes[kp->nr++] = objnode; | |
- else | |
- kmem_cache_free(zcache_objnode_cache, objnode); | |
- } | |
- preempt_enable_no_resched(); | |
- obj = kmem_cache_alloc(zcache_obj_cache, ZCACHE_GFP_MASK); | |
- if (unlikely(obj == NULL)) { | |
- zcache_failed_alloc++; | |
- goto unlock_out; | |
- } | |
- page = qcache_alloc(); | |
- if (unlikely(page == NULL)) { | |
- zcache_failed_get_free_pages++; | |
- kmem_cache_free(zcache_obj_cache, obj); | |
- goto unlock_out; | |
- } | |
- preempt_disable(); | |
- kp = &__get_cpu_var(zcache_preloads); | |
- if (kp->obj == NULL) | |
- kp->obj = obj; | |
- else | |
- kmem_cache_free(zcache_obj_cache, obj); | |
- if (kp->page == NULL) | |
- kp->page = page; | |
- else | |
- qcache_free(page); | |
- ret = 0; | |
-unlock_out: | |
- spin_unlock(&zcache_direct_reclaim_lock); | |
-out: | |
- return ret; | |
-} | |
- | |
-static void *zcache_get_free_page(void) | |
-{ | |
- struct zcache_preload *kp; | |
- void *page; | |
- | |
- kp = &__get_cpu_var(zcache_preloads); | |
- page = kp->page; | |
- BUG_ON(page == NULL); | |
- kp->page = NULL; | |
- return page; | |
-} | |
- | |
-/* | |
- * zcache implementation for tmem host ops | |
- */ | |
- | |
-static struct tmem_objnode *zcache_objnode_alloc(struct tmem_pool *pool) | |
-{ | |
- struct tmem_objnode *objnode = NULL; | |
- unsigned long count; | |
- struct zcache_preload *kp; | |
- | |
- kp = &__get_cpu_var(zcache_preloads); | |
- if (kp->nr <= 0) | |
- goto out; | |
- objnode = kp->objnodes[kp->nr - 1]; | |
- BUG_ON(objnode == NULL); | |
- kp->objnodes[kp->nr - 1] = NULL; | |
- kp->nr--; | |
- count = atomic_inc_return(&zcache_curr_objnode_count); | |
- if (count > zcache_curr_objnode_count_max) | |
- zcache_curr_objnode_count_max = count; | |
-out: | |
- return objnode; | |
-} | |
- | |
-static void zcache_objnode_free(struct tmem_objnode *objnode, | |
- struct tmem_pool *pool) | |
-{ | |
- atomic_dec(&zcache_curr_objnode_count); | |
- BUG_ON(atomic_read(&zcache_curr_objnode_count) < 0); | |
- kmem_cache_free(zcache_objnode_cache, objnode); | |
-} | |
- | |
-static struct tmem_obj *zcache_obj_alloc(struct tmem_pool *pool) | |
-{ | |
- struct tmem_obj *obj = NULL; | |
- unsigned long count; | |
- struct zcache_preload *kp; | |
- | |
- kp = &__get_cpu_var(zcache_preloads); | |
- obj = kp->obj; | |
- BUG_ON(obj == NULL); | |
- kp->obj = NULL; | |
- count = atomic_inc_return(&zcache_curr_obj_count); | |
- if (count > zcache_curr_obj_count_max) | |
- zcache_curr_obj_count_max = count; | |
- return obj; | |
-} | |
- | |
-static void zcache_obj_free(struct tmem_obj *obj, struct tmem_pool *pool) | |
-{ | |
- atomic_dec(&zcache_curr_obj_count); | |
- BUG_ON(atomic_read(&zcache_curr_obj_count) < 0); | |
- kmem_cache_free(zcache_obj_cache, obj); | |
-} | |
- | |
-static void zcache_flush_all_obj(void) | |
-{ | |
- struct tmem_pool *pool; | |
- int pool_id; | |
- struct zcache_preload *kp; | |
- | |
- kp = &__get_cpu_var(zcache_preloads); | |
- | |
- for (pool_id = 0; pool_id < MAX_POOLS_PER_CLIENT; pool_id++) { | |
- pool = zcache_get_pool_by_id(LOCAL_CLIENT, pool_id); | |
- tmem_flush_pool(pool); | |
- if (pool) | |
- zcache_put_pool(pool); | |
- } | |
- if (kp->page) { | |
- qcache_free(kp->page); | |
- kp->page = NULL; | |
- } | |
- if (zcache_qc_used) | |
- pr_warn("pages used not 0 after qcache flush all, is %ld\n", | |
- zcache_qc_used); | |
-} | |
- | |
-/* | |
- * When zcache is disabled ("frozen"), pools can be created and destroyed, | |
- * but all puts (and thus all other operations that require memory allocation) | |
- * must fail. If zcache is unfrozen, accepts puts, then frozen again, | |
- * data consistency requires all puts while frozen to be converted into | |
- * flushes. | |
- */ | |
-static bool zcache_freeze; | |
- | |
-static void zcache_control(bool freeze) | |
-{ | |
- zcache_freeze = freeze; | |
-} | |
- | |
-static struct tmem_hostops zcache_hostops = { | |
- .obj_alloc = zcache_obj_alloc, | |
- .obj_free = zcache_obj_free, | |
- .objnode_alloc = zcache_objnode_alloc, | |
- .objnode_free = zcache_objnode_free, | |
- .flush_all_obj = zcache_flush_all_obj, | |
- .control = zcache_control, | |
-}; | |
- | |
-/* | |
- * zcache implementations for PAM page descriptor ops | |
- */ | |
- | |
-static atomic_t zcache_curr_eph_pampd_count = ATOMIC_INIT(0); | |
-static unsigned long zcache_curr_eph_pampd_count_max; | |
- | |
-/* forward reference */ | |
-static int zcache_compress(struct page *from, void **out_va, size_t *out_len); | |
- | |
-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; | |
- int ret; | |
- unsigned long count; | |
- struct page *page = (struct page *)(data); | |
- struct zcache_client *cli = pool->client; | |
- uint16_t client_id = get_client_id_from_client(cli); | |
- | |
- 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(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; | |
- } | |
-out: | |
- return pampd; | |
-} | |
- | |
-/* | |
- * fill the pageframe corresponding to the struct page with the data | |
- * from the passed pampd | |
- */ | |
-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) | |
-{ | |
- BUG(); | |
- return 0; | |
-} | |
- | |
-/* | |
- * 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) | |
-{ | |
- int ret = 0; | |
- | |
- zbud_decompress((struct page *)(data), pampd); | |
- zbud_free_and_delist((struct zbud_hdr *)pampd); | |
- atomic_dec(&zcache_curr_eph_pampd_count); | |
- return ret; | |
-} | |
- | |
-/* | |
- * 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, | |
- struct tmem_oid *oid, uint32_t index) | |
-{ | |
- 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); | |
-} | |
- | |
-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); | |
- | |
-static int zcache_compress(struct page *from, void **out_va, size_t *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 */ | |
- from_va = kmap_atomic(from); | |
- mb(); | |
- ret = lzo1x_1_compress(from_va, PAGE_SIZE, dmem, out_len, wmem); | |
- BUG_ON(ret != LZO_E_OK); | |
- *out_va = dmem; | |
- kunmap_atomic(from_va); | |
- ret = 1; | |
-out: | |
- return ret; | |
-} | |
- | |
-#ifdef CONFIG_SYSFS | |
-#define ZCACHE_SYSFS_RO(_name) \ | |
- static ssize_t zcache_##_name##_show(struct kobject *kobj, \ | |
- struct kobj_attribute *attr, char *buf) \ | |
- { \ | |
- return sprintf(buf, "%lu\n", zcache_##_name); \ | |
- } \ | |
- static struct kobj_attribute zcache_##_name##_attr = { \ | |
- .attr = { .name = __stringify(_name), .mode = 0444 }, \ | |
- .show = zcache_##_name##_show, \ | |
- } | |
- | |
-#define ZCACHE_SYSFS_RO_ATOMIC(_name) \ | |
- static ssize_t zcache_##_name##_show(struct kobject *kobj, \ | |
- struct kobj_attribute *attr, char *buf) \ | |
- { \ | |
- return sprintf(buf, "%d\n", atomic_read(&zcache_##_name)); \ | |
- } \ | |
- static struct kobj_attribute zcache_##_name##_attr = { \ | |
- .attr = { .name = __stringify(_name), .mode = 0444 }, \ | |
- .show = zcache_##_name##_show, \ | |
- } | |
- | |
-#define ZCACHE_SYSFS_RO_CUSTOM(_name, _func) \ | |
- static ssize_t zcache_##_name##_show(struct kobject *kobj, \ | |
- struct kobj_attribute *attr, char *buf) \ | |
- { \ | |
- return _func(buf); \ | |
- } \ | |
- static struct kobj_attribute zcache_##_name##_attr = { \ | |
- .attr = { .name = __stringify(_name), .mode = 0444 }, \ | |
- .show = zcache_##_name##_show, \ | |
- } | |
- | |
-ZCACHE_SYSFS_RO(curr_obj_count_max); | |
-ZCACHE_SYSFS_RO(curr_objnode_count_max); | |
-ZCACHE_SYSFS_RO(flush_total); | |
-ZCACHE_SYSFS_RO(flush_found); | |
-ZCACHE_SYSFS_RO(flobj_total); | |
-ZCACHE_SYSFS_RO(flobj_found); | |
-ZCACHE_SYSFS_RO(failed_eph_puts); | |
-ZCACHE_SYSFS_RO(zbud_curr_zbytes); | |
-ZCACHE_SYSFS_RO(zbud_cumul_zpages); | |
-ZCACHE_SYSFS_RO(zbud_cumul_zbytes); | |
-ZCACHE_SYSFS_RO(zbud_buddied_count); | |
-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(qc_allocated); | |
-ZCACHE_SYSFS_RO(qc_freed); | |
-ZCACHE_SYSFS_RO(qc_used); | |
-ZCACHE_SYSFS_RO(qc_max_used); | |
-ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_raw_pages); | |
-ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_zpages); | |
-ZCACHE_SYSFS_RO_ATOMIC(curr_obj_count); | |
-ZCACHE_SYSFS_RO_ATOMIC(curr_objnode_count); | |
-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); | |
- | |
-static struct attribute *qcache_attrs[] = { | |
- &zcache_curr_obj_count_attr.attr, | |
- &zcache_curr_obj_count_max_attr.attr, | |
- &zcache_curr_objnode_count_attr.attr, | |
- &zcache_curr_objnode_count_max_attr.attr, | |
- &zcache_flush_total_attr.attr, | |
- &zcache_flobj_total_attr.attr, | |
- &zcache_flush_found_attr.attr, | |
- &zcache_flobj_found_attr.attr, | |
- &zcache_failed_eph_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, | |
- &zcache_zbud_cumul_zpages_attr.attr, | |
- &zcache_zbud_cumul_zbytes_attr.attr, | |
- &zcache_zbud_buddied_count_attr.attr, | |
- &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_qc_allocated_attr.attr, | |
- &zcache_qc_freed_attr.attr, | |
- &zcache_qc_used_attr.attr, | |
- &zcache_qc_max_used_attr.attr, | |
- NULL, | |
-}; | |
- | |
-static struct attribute_group qcache_attr_group = { | |
- .attrs = qcache_attrs, | |
- .name = "qcache", | |
-}; | |
- | |
-#endif /* CONFIG_SYSFS */ | |
- | |
-/* | |
- * zcache shims between cleancache ops and tmem | |
- */ | |
- | |
-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(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, (char *)(page), | |
- PAGE_SIZE, 0, is_ephemeral(pool)); | |
- if (ret < 0) { | |
- zcache_failed_eph_puts++; | |
- } | |
- zcache_put_pool(pool); | |
- preempt_enable_no_resched(); | |
- } else { | |
- zcache_put_to_flush++; | |
- if (atomic_read(&pool->obj_count) > 0) | |
- /* the put fails whether the flush succeeds or not */ | |
- (void)tmem_flush_page(pool, oidp, index); | |
- zcache_put_pool(pool); | |
- } | |
-out: | |
- return ret; | |
-} | |
- | |
-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(cli_id, pool_id); | |
- if (likely(pool != NULL)) { | |
- if (atomic_read(&pool->obj_count) > 0) | |
- 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 cli_id, int pool_id, | |
- struct tmem_oid *oidp, uint32_t index) | |
-{ | |
- struct tmem_pool *pool; | |
- int ret = -1; | |
- unsigned long flags; | |
- | |
- local_irq_save(flags); | |
- zcache_flush_total++; | |
- 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); | |
- zcache_put_pool(pool); | |
- } | |
- if (ret >= 0) | |
- zcache_flush_found++; | |
- local_irq_restore(flags); | |
- return ret; | |
-} | |
- | |
-static int zcache_flush_object(int cli_id, int pool_id, | |
- struct tmem_oid *oidp) | |
-{ | |
- struct tmem_pool *pool; | |
- int ret = -1; | |
- unsigned long flags; | |
- | |
- local_irq_save(flags); | |
- zcache_flobj_total++; | |
- 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); | |
- zcache_put_pool(pool); | |
- } | |
- if (ret >= 0) | |
- zcache_flobj_found++; | |
- local_irq_restore(flags); | |
- return ret; | |
-} | |
- | |
-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; | |
- 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; | |
- 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("qcache: destroyed pool id=%d, cli_id=%d\n", | |
- pool_id, cli_id); | |
-out: | |
- return ret; | |
-} | |
- | |
-static int zcache_new_pool(uint16_t cli_id, uint32_t flags) | |
-{ | |
- int poolid = -1; | |
- struct tmem_pool *pool; | |
- struct zcache_client *cli = NULL; | |
- | |
- 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_KERNEL); | |
- if (pool == NULL) { | |
- pr_info("qcache: pool creation failed: out of memory\n"); | |
- goto out; | |
- } | |
- | |
- for (poolid = 0; poolid < MAX_POOLS_PER_CLIENT; poolid++) | |
- if (cli->tmem_pools[poolid] == NULL) | |
- break; | |
- if (poolid >= MAX_POOLS_PER_CLIENT) { | |
- pr_info("qcache: pool creation failed: max exceeded\n"); | |
- kfree(pool); | |
- poolid = -1; | |
- goto out; | |
- } | |
- atomic_set(&pool->refcount, 0); | |
- pool->client = cli; | |
- pool->pool_id = poolid; | |
- tmem_new_pool(pool, flags); | |
- cli->tmem_pools[poolid] = pool; | |
- pr_info("qcache: created %s tmem pool, id=%d, client=%d\n", | |
- flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral", | |
- poolid, cli_id); | |
-out: | |
- if (cli != NULL) | |
- atomic_dec(&cli->refcount); | |
- return poolid; | |
-} | |
- | |
-/********** | |
- * Two kernel functionalities currently can be layered on top of tmem. | |
- * These are "cleancache" which is used as a second-chance cache for clean | |
- * page cache pages; and "frontswap" which is used for swap pages | |
- * to avoid writes to disk. A generic "shim" is provided here for each | |
- * to translate in-kernel semantics to zcache semantics. | |
- */ | |
- | |
-static void zcache_cleancache_put_page(int pool_id, | |
- struct cleancache_filekey key, | |
- pgoff_t index, struct page *page) | |
-{ | |
- u32 ind = (u32) index; | |
- struct tmem_oid oid = *(struct tmem_oid *)&key; | |
- | |
- if (likely(ind == index)) | |
- (void)zcache_put_page(LOCAL_CLIENT, pool_id, &oid, index, page); | |
-} | |
- | |
-static int zcache_cleancache_get_page(int pool_id, | |
- struct cleancache_filekey key, | |
- pgoff_t index, struct page *page) | |
-{ | |
- u32 ind = (u32) index; | |
- struct tmem_oid oid = *(struct tmem_oid *)&key; | |
- int ret = -1; | |
- | |
- if (likely(ind == index)) | |
- ret = zcache_get_page(LOCAL_CLIENT, pool_id, &oid, index, page); | |
- return ret; | |
-} | |
- | |
-static void zcache_cleancache_flush_page(int pool_id, | |
- struct cleancache_filekey key, | |
- pgoff_t index) | |
-{ | |
- u32 ind = (u32) index; | |
- struct tmem_oid oid = *(struct tmem_oid *)&key; | |
- | |
- if (likely(ind == index)) | |
- (void)zcache_flush_page(LOCAL_CLIENT, pool_id, &oid, ind); | |
-} | |
- | |
-static void zcache_cleancache_flush_inode(int pool_id, | |
- struct cleancache_filekey key) | |
-{ | |
- struct tmem_oid oid = *(struct tmem_oid *)&key; | |
- | |
- (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(LOCAL_CLIENT, pool_id); | |
-} | |
- | |
-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(LOCAL_CLIENT, 0); | |
-} | |
- | |
-static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize) | |
-{ | |
- /* shared pools are unsupported and map to private */ | |
- BUG_ON(sizeof(struct cleancache_filekey) != | |
- sizeof(struct tmem_oid)); | |
- BUG_ON(pagesize != PAGE_SIZE); | |
- 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, | |
- .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 | |
-}; | |
- | |
-struct cleancache_ops zcache_cleancache_register_ops(void) | |
-{ | |
- struct cleancache_ops old_ops = | |
- cleancache_register_ops(&zcache_cleancache_ops); | |
- | |
- return old_ops; | |
-} | |
- | |
-static int __init qcache_init(void) | |
-{ | |
- int ret = 0; | |
- struct qcache_info *qc = &qcache_info; | |
- struct fmem_data *fdp; | |
- int bitmap_size; | |
- unsigned int cpu; | |
- struct cleancache_ops old_ops; | |
- | |
-#ifdef CONFIG_SYSFS | |
- ret = sysfs_create_group(mm_kobj, &qcache_attr_group); | |
- if (ret) { | |
- pr_err("qcache: can't create sysfs\n"); | |
- goto out; | |
- } | |
-#endif /* CONFIG_SYSFS */ | |
- | |
- fdp = fmem_get_info(); | |
- qc->addr = fdp->virt; | |
- qc->pages = fdp->size >> PAGE_SHIFT; | |
- if (!qc->pages) | |
- goto out; | |
- | |
- tmem_register_hostops(&zcache_hostops); | |
- tmem_register_pamops(&zcache_pamops); | |
- for_each_online_cpu(cpu) { | |
- 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); | |
- } | |
- zcache_objnode_cache = kmem_cache_create("zcache_objnode", | |
- 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("qcache: can't create client\n"); | |
- goto out; | |
- } | |
- | |
- zbud_init(); | |
- old_ops = zcache_cleancache_register_ops(); | |
- pr_info("qcache: cleancache enabled using kernel " | |
- "transcendent memory and compression buddies\n"); | |
- if (old_ops.init_fs != NULL) | |
- pr_warning("qcache: cleancache_ops overridden"); | |
- | |
- | |
- bitmap_size = BITS_TO_LONGS(qc->pages) * sizeof(long); | |
- | |
- qc->bitmap = kzalloc(bitmap_size, GFP_KERNEL); | |
- if (!qc->bitmap) { | |
- pr_info("can't allocate qcache bitmap!\n"); | |
- ret = -ENOMEM; | |
- goto out; | |
- } | |
- spin_lock_init(&qc->lock); | |
- | |
- fmem_set_state(FMEM_T_STATE); | |
- | |
-out: | |
- return ret; | |
-} | |
- | |
-module_init(qcache_init) | |
diff --git a/drivers/staging/qcache/tmem.c b/drivers/staging/qcache/tmem.c | |
deleted file mode 100644 | |
index 40f2246..0000000 | |
--- a/drivers/staging/qcache/tmem.c | |
+++ /dev/null | |
@@ -1,833 +0,0 @@ | |
-/* | |
- * In-kernel transcendent memory (generic implementation) | |
- * | |
- * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp. | |
- * Copyright (c) 2011, The Linux Foundation. All rights reserved. | |
- * | |
- * The primary purpose of Transcedent Memory ("tmem") is to map object-oriented | |
- * "handles" (triples containing a pool id, and object id, and an index), to | |
- * pages in a page-accessible memory (PAM). Tmem references the PAM pages via | |
- * an abstract "pampd" (PAM page-descriptor), which can be operated on by a | |
- * set of functions (pamops). Each pampd contains some representation of | |
- * PAGE_SIZE bytes worth of data. Tmem must support potentially millions of | |
- * pages and must be able to insert, find, and delete these pages at a | |
- * potential frequency of thousands per second concurrently across many CPUs, | |
- * (and, if used with KVM, across many vcpus across many guests). | |
- * Tmem is tracked with a hierarchy of data structures, organized by | |
- * the elements in a handle-tuple: pool_id, object_id, and page index. | |
- * One or more "clients" (e.g. guests) each provide one or more tmem_pools. | |
- * Each pool, contains a hash table of rb_trees of tmem_objs. Each | |
- * tmem_obj contains a radix-tree-like tree of pointers, with intermediate | |
- * nodes called tmem_objnodes. Each leaf pointer in this tree points to | |
- * a pampd, which is accessible only through a small set of callbacks | |
- * registered by the PAM implementation (see tmem_register_pamops). Tmem | |
- * does all memory allocation via a set of callbacks registered by the tmem | |
- * host implementation (e.g. see tmem_register_hostops). | |
- */ | |
- | |
-#include <linux/list.h> | |
-#include <linux/spinlock.h> | |
-#include <linux/atomic.h> | |
- | |
-#include "tmem.h" | |
- | |
-/* data structure sentinels used for debugging... see tmem.h */ | |
-#define POOL_SENTINEL 0x87658765 | |
-#define OBJ_SENTINEL 0x12345678 | |
-#define OBJNODE_SENTINEL 0xfedcba09 | |
- | |
-static bool tmem_enabled; | |
- | |
-static void lock_tmem_state(void) | |
-{ | |
- lock_fmem_state(); | |
-} | |
- | |
-static void unlock_tmem_state(void) | |
-{ | |
- unlock_fmem_state(); | |
-} | |
- | |
-/* | |
- * A tmem host implementation must use this function to register callbacks | |
- * for memory allocation. | |
- */ | |
-static struct tmem_hostops tmem_hostops; | |
- | |
-static void tmem_objnode_tree_init(void); | |
- | |
-void tmem_register_hostops(struct tmem_hostops *m) | |
-{ | |
- tmem_objnode_tree_init(); | |
- tmem_hostops = *m; | |
-} | |
- | |
-/* | |
- * A tmem host implementation must use this function to register | |
- * callbacks for a page-accessible memory (PAM) implementation | |
- */ | |
-static struct tmem_pamops tmem_pamops; | |
- | |
-void tmem_register_pamops(struct tmem_pamops *m) | |
-{ | |
- tmem_pamops = *m; | |
-} | |
- | |
-/* | |
- * Oid's are potentially very sparse and tmem_objs may have an indeterminately | |
- * short life, being added and deleted at a relatively high frequency. | |
- * So an rb_tree is an ideal data structure to manage tmem_objs. But because | |
- * of the potentially huge number of tmem_objs, each pool manages a hashtable | |
- * of rb_trees to reduce search, insert, delete, and rebalancing time. | |
- * Each hashbucket also has a lock to manage concurrent access. | |
- * | |
- * The following routines manage tmem_objs. When any tmem_obj is accessed, | |
- * the hashbucket lock must be held. | |
- */ | |
- | |
-/* searches for object==oid in pool, returns locked object if found */ | |
-static struct tmem_obj *tmem_obj_find(struct tmem_hashbucket *hb, | |
- struct tmem_oid *oidp) | |
-{ | |
- struct rb_node *rbnode; | |
- struct tmem_obj *obj; | |
- | |
- rbnode = hb->obj_rb_root.rb_node; | |
- while (rbnode) { | |
- BUG_ON(RB_EMPTY_NODE(rbnode)); | |
- obj = rb_entry(rbnode, struct tmem_obj, rb_tree_node); | |
- switch (tmem_oid_compare(oidp, &obj->oid)) { | |
- case 0: /* equal */ | |
- goto out; | |
- case -1: | |
- rbnode = rbnode->rb_left; | |
- break; | |
- case 1: | |
- rbnode = rbnode->rb_right; | |
- break; | |
- } | |
- } | |
- obj = NULL; | |
-out: | |
- return obj; | |
-} | |
- | |
-static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *); | |
- | |
-/* free an object that has no more pampds in it */ | |
-static void tmem_obj_free(struct tmem_obj *obj, struct tmem_hashbucket *hb) | |
-{ | |
- struct tmem_pool *pool; | |
- | |
- BUG_ON(obj == NULL); | |
- ASSERT_SENTINEL(obj, OBJ); | |
- BUG_ON(obj->pampd_count > 0); | |
- pool = obj->pool; | |
- BUG_ON(pool == NULL); | |
- if (obj->objnode_tree_root != NULL) /* may be "stump" with no leaves */ | |
- tmem_pampd_destroy_all_in_obj(obj); | |
- BUG_ON(obj->objnode_tree_root != NULL); | |
- BUG_ON((long)obj->objnode_count != 0); | |
- atomic_dec(&pool->obj_count); | |
- BUG_ON(atomic_read(&pool->obj_count) < 0); | |
- INVERT_SENTINEL(obj, OBJ); | |
- obj->pool = NULL; | |
- tmem_oid_set_invalid(&obj->oid); | |
- rb_erase(&obj->rb_tree_node, &hb->obj_rb_root); | |
-} | |
- | |
-/* | |
- * initialize, and insert an tmem_object_root (called only if find failed) | |
- */ | |
-static void tmem_obj_init(struct tmem_obj *obj, struct tmem_hashbucket *hb, | |
- struct tmem_pool *pool, | |
- struct tmem_oid *oidp) | |
-{ | |
- struct rb_root *root = &hb->obj_rb_root; | |
- struct rb_node **new = &(root->rb_node), *parent = NULL; | |
- struct tmem_obj *this; | |
- | |
- BUG_ON(pool == NULL); | |
- atomic_inc(&pool->obj_count); | |
- obj->objnode_tree_height = 0; | |
- obj->objnode_tree_root = NULL; | |
- obj->pool = pool; | |
- 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)); | |
- this = rb_entry(*new, struct tmem_obj, rb_tree_node); | |
- parent = *new; | |
- switch (tmem_oid_compare(oidp, &this->oid)) { | |
- case 0: | |
- BUG(); /* already present; should never happen! */ | |
- break; | |
- case -1: | |
- new = &(*new)->rb_left; | |
- break; | |
- case 1: | |
- new = &(*new)->rb_right; | |
- break; | |
- } | |
- } | |
- rb_link_node(&obj->rb_tree_node, parent, new); | |
- rb_insert_color(&obj->rb_tree_node, root); | |
-} | |
- | |
-/* | |
- * Tmem is managed as a set of tmem_pools with certain attributes, such as | |
- * "ephemeral" vs "persistent". These attributes apply to all tmem_objs | |
- * and all pampds that belong to a tmem_pool. A tmem_pool is created | |
- * or deleted relatively rarely (for example, when a filesystem is | |
- * mounted or unmounted. | |
- */ | |
- | |
-/* flush all data from a pool and, optionally, free it */ | |
-static void tmem_pool_flush(struct tmem_pool *pool, bool destroy) | |
-{ | |
- struct rb_node *rbnode; | |
- struct tmem_obj *obj; | |
- struct tmem_hashbucket *hb = &pool->hashbucket[0]; | |
- int i; | |
- | |
- BUG_ON(pool == NULL); | |
- for (i = 0; i < TMEM_HASH_BUCKETS; i++, hb++) { | |
- spin_lock(&hb->lock); | |
- rbnode = rb_first(&hb->obj_rb_root); | |
- while (rbnode != NULL) { | |
- obj = rb_entry(rbnode, struct tmem_obj, rb_tree_node); | |
- rbnode = rb_next(rbnode); | |
- tmem_pampd_destroy_all_in_obj(obj); | |
- tmem_obj_free(obj, hb); | |
- (*tmem_hostops.obj_free)(obj, pool); | |
- } | |
- spin_unlock(&hb->lock); | |
- } | |
- if (destroy) | |
- list_del(&pool->pool_list); | |
-} | |
- | |
-/* | |
- * A tmem_obj contains a radix-tree-like tree in which the intermediate | |
- * nodes are called tmem_objnodes. (The kernel lib/radix-tree.c implementation | |
- * is very specialized and tuned for specific uses and is not particularly | |
- * suited for use from this code, though some code from the core algorithms has | |
- * been reused, thus the copyright notices below). Each tmem_objnode contains | |
- * a set of pointers which point to either a set of intermediate tmem_objnodes | |
- * or a set of of pampds. | |
- * | |
- * Portions Copyright (C) 2001 Momchil Velikov | |
- * Portions Copyright (C) 2001 Christoph Hellwig | |
- * Portions Copyright (C) 2005 SGI, Christoph Lameter <clameter@sgi.com> | |
- */ | |
- | |
-struct tmem_objnode_tree_path { | |
- struct tmem_objnode *objnode; | |
- int offset; | |
-}; | |
- | |
-/* objnode height_to_maxindex translation */ | |
-static unsigned long tmem_objnode_tree_h2max[OBJNODE_TREE_MAX_PATH + 1]; | |
- | |
-static void tmem_objnode_tree_init(void) | |
-{ | |
- unsigned int ht, tmp; | |
- | |
- for (ht = 0; ht < ARRAY_SIZE(tmem_objnode_tree_h2max); ht++) { | |
- tmp = ht * OBJNODE_TREE_MAP_SHIFT; | |
- if (tmp >= OBJNODE_TREE_INDEX_BITS) | |
- tmem_objnode_tree_h2max[ht] = ~0UL; | |
- else | |
- tmem_objnode_tree_h2max[ht] = | |
- (~0UL >> (OBJNODE_TREE_INDEX_BITS - tmp - 1)) >> 1; | |
- } | |
-} | |
- | |
-static struct tmem_objnode *tmem_objnode_alloc(struct tmem_obj *obj) | |
-{ | |
- struct tmem_objnode *objnode; | |
- | |
- ASSERT_SENTINEL(obj, OBJ); | |
- BUG_ON(obj->pool == NULL); | |
- ASSERT_SENTINEL(obj->pool, POOL); | |
- objnode = (*tmem_hostops.objnode_alloc)(obj->pool); | |
- if (unlikely(objnode == NULL)) | |
- goto out; | |
- objnode->obj = obj; | |
- SET_SENTINEL(objnode, OBJNODE); | |
- memset(&objnode->slots, 0, sizeof(objnode->slots)); | |
- objnode->slots_in_use = 0; | |
- obj->objnode_count++; | |
-out: | |
- return objnode; | |
-} | |
- | |
-static void tmem_objnode_free(struct tmem_objnode *objnode) | |
-{ | |
- struct tmem_pool *pool; | |
- int i; | |
- | |
- BUG_ON(objnode == NULL); | |
- for (i = 0; i < OBJNODE_TREE_MAP_SIZE; i++) | |
- BUG_ON(objnode->slots[i] != NULL); | |
- ASSERT_SENTINEL(objnode, OBJNODE); | |
- INVERT_SENTINEL(objnode, OBJNODE); | |
- BUG_ON(objnode->obj == NULL); | |
- ASSERT_SENTINEL(objnode->obj, OBJ); | |
- pool = objnode->obj->pool; | |
- BUG_ON(pool == NULL); | |
- ASSERT_SENTINEL(pool, POOL); | |
- objnode->obj->objnode_count--; | |
- objnode->obj = NULL; | |
- (*tmem_hostops.objnode_free)(objnode, pool); | |
-} | |
- | |
-/* | |
- * 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) | |
-{ | |
- unsigned int height, shift; | |
- struct tmem_objnode **slot = NULL; | |
- | |
- BUG_ON(obj == NULL); | |
- ASSERT_SENTINEL(obj, OBJ); | |
- BUG_ON(obj->pool == NULL); | |
- ASSERT_SENTINEL(obj->pool, POOL); | |
- | |
- height = obj->objnode_tree_height; | |
- if (index > tmem_objnode_tree_h2max[obj->objnode_tree_height]) | |
- goto out; | |
- if (height == 0 && obj->objnode_tree_root) { | |
- slot = &obj->objnode_tree_root; | |
- goto out; | |
- } | |
- shift = (height-1) * OBJNODE_TREE_MAP_SHIFT; | |
- slot = &obj->objnode_tree_root; | |
- while (height > 0) { | |
- if (*slot == NULL) | |
- goto out; | |
- slot = (struct tmem_objnode **) | |
- ((*slot)->slots + | |
- ((index >> shift) & OBJNODE_TREE_MAP_MASK)); | |
- shift -= OBJNODE_TREE_MAP_SHIFT; | |
- 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) | |
-{ | |
- int ret = 0; | |
- struct tmem_objnode *objnode = NULL, *newnode, *slot; | |
- unsigned int height, shift; | |
- int offset = 0; | |
- | |
- /* if necessary, extend the tree to be higher */ | |
- if (index > tmem_objnode_tree_h2max[obj->objnode_tree_height]) { | |
- height = obj->objnode_tree_height + 1; | |
- if (index > tmem_objnode_tree_h2max[height]) | |
- while (index > tmem_objnode_tree_h2max[height]) | |
- height++; | |
- if (obj->objnode_tree_root == NULL) { | |
- obj->objnode_tree_height = height; | |
- goto insert; | |
- } | |
- do { | |
- newnode = tmem_objnode_alloc(obj); | |
- if (!newnode) { | |
- ret = -ENOMEM; | |
- goto out; | |
- } | |
- newnode->slots[0] = obj->objnode_tree_root; | |
- newnode->slots_in_use = 1; | |
- obj->objnode_tree_root = newnode; | |
- obj->objnode_tree_height++; | |
- } while (height > obj->objnode_tree_height); | |
- } | |
-insert: | |
- slot = obj->objnode_tree_root; | |
- height = obj->objnode_tree_height; | |
- shift = (height-1) * OBJNODE_TREE_MAP_SHIFT; | |
- while (height > 0) { | |
- if (slot == NULL) { | |
- /* add a child objnode. */ | |
- slot = tmem_objnode_alloc(obj); | |
- if (!slot) { | |
- ret = -ENOMEM; | |
- goto out; | |
- } | |
- if (objnode) { | |
- | |
- objnode->slots[offset] = slot; | |
- objnode->slots_in_use++; | |
- } else | |
- obj->objnode_tree_root = slot; | |
- } | |
- /* go down a level */ | |
- offset = (index >> shift) & OBJNODE_TREE_MAP_MASK; | |
- objnode = slot; | |
- slot = objnode->slots[offset]; | |
- shift -= OBJNODE_TREE_MAP_SHIFT; | |
- height--; | |
- } | |
- BUG_ON(slot != NULL); | |
- if (objnode) { | |
- objnode->slots_in_use++; | |
- objnode->slots[offset] = pampd; | |
- } else | |
- obj->objnode_tree_root = pampd; | |
- obj->pampd_count++; | |
-out: | |
- return ret; | |
-} | |
- | |
-static void *tmem_pampd_delete_from_obj(struct tmem_obj *obj, uint32_t index) | |
-{ | |
- struct tmem_objnode_tree_path path[OBJNODE_TREE_MAX_PATH + 1]; | |
- struct tmem_objnode_tree_path *pathp = path; | |
- struct tmem_objnode *slot = NULL; | |
- unsigned int height, shift; | |
- int offset; | |
- | |
- BUG_ON(obj == NULL); | |
- ASSERT_SENTINEL(obj, OBJ); | |
- BUG_ON(obj->pool == NULL); | |
- ASSERT_SENTINEL(obj->pool, POOL); | |
- height = obj->objnode_tree_height; | |
- if (index > tmem_objnode_tree_h2max[height]) | |
- goto out; | |
- slot = obj->objnode_tree_root; | |
- if (height == 0 && obj->objnode_tree_root) { | |
- obj->objnode_tree_root = NULL; | |
- goto out; | |
- } | |
- shift = (height - 1) * OBJNODE_TREE_MAP_SHIFT; | |
- pathp->objnode = NULL; | |
- do { | |
- if (slot == NULL) | |
- goto out; | |
- pathp++; | |
- offset = (index >> shift) & OBJNODE_TREE_MAP_MASK; | |
- pathp->offset = offset; | |
- pathp->objnode = slot; | |
- slot = slot->slots[offset]; | |
- shift -= OBJNODE_TREE_MAP_SHIFT; | |
- height--; | |
- } while (height > 0); | |
- if (slot == NULL) | |
- goto out; | |
- while (pathp->objnode) { | |
- pathp->objnode->slots[pathp->offset] = NULL; | |
- pathp->objnode->slots_in_use--; | |
- if (pathp->objnode->slots_in_use) { | |
- if (pathp->objnode == obj->objnode_tree_root) { | |
- while (obj->objnode_tree_height > 0 && | |
- obj->objnode_tree_root->slots_in_use == 1 && | |
- obj->objnode_tree_root->slots[0]) { | |
- struct tmem_objnode *to_free = | |
- obj->objnode_tree_root; | |
- | |
- obj->objnode_tree_root = | |
- to_free->slots[0]; | |
- obj->objnode_tree_height--; | |
- to_free->slots[0] = NULL; | |
- to_free->slots_in_use = 0; | |
- tmem_objnode_free(to_free); | |
- } | |
- } | |
- goto out; | |
- } | |
- tmem_objnode_free(pathp->objnode); /* 0 slots used, free it */ | |
- pathp--; | |
- } | |
- obj->objnode_tree_height = 0; | |
- obj->objnode_tree_root = NULL; | |
- | |
-out: | |
- if (slot != NULL) | |
- obj->pampd_count--; | |
- BUG_ON(obj->pampd_count < 0); | |
- return slot; | |
-} | |
- | |
-/* recursively walk the objnode_tree destroying pampds and objnodes */ | |
-static void tmem_objnode_node_destroy(struct tmem_obj *obj, | |
- struct tmem_objnode *objnode, | |
- unsigned int ht) | |
-{ | |
- int i; | |
- | |
- if (ht == 0) | |
- return; | |
- for (i = 0; i < OBJNODE_TREE_MAP_SIZE; i++) { | |
- if (objnode->slots[i]) { | |
- if (ht == 1) { | |
- obj->pampd_count--; | |
- (*tmem_pamops.free)(objnode->slots[i], | |
- obj->pool, NULL, 0); | |
- objnode->slots[i] = NULL; | |
- continue; | |
- } | |
- tmem_objnode_node_destroy(obj, objnode->slots[i], ht-1); | |
- tmem_objnode_free(objnode->slots[i]); | |
- objnode->slots[i] = NULL; | |
- } | |
- } | |
-} | |
- | |
-static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj) | |
-{ | |
- if (obj->objnode_tree_root == NULL) | |
- return; | |
- if (obj->objnode_tree_height == 0) { | |
- obj->pampd_count--; | |
- (*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); | |
- tmem_objnode_free(obj->objnode_tree_root); | |
- obj->objnode_tree_height = 0; | |
- } | |
- obj->objnode_tree_root = NULL; | |
- (*tmem_pamops.free_obj)(obj->pool, obj); | |
-} | |
- | |
-/* | |
- * Tmem is operated on by a set of well-defined actions: | |
- * "put", "get", "flush", "flush_object", "new pool" and "destroy pool". | |
- * (The tmem ABI allows for subpages and exchanges but these operations | |
- * are not included in this implementation.) | |
- * | |
- * These "tmem core" operations are implemented in the following functions. | |
- */ | |
- | |
-/* | |
- * "Put" a page, e.g. copy a page from the kernel into newly allocated | |
- * PAM space (if such space is available). Tmem_put is complicated by | |
- * a corner case: What if a page with matching handle already exists in | |
- * tmem? To guarantee coherency, one of two actions is necessary: Either | |
- * the data for the page must be overwritten, or the page must be | |
- * "flushed" so that the data is not accessible to a subsequent "get". | |
- * Since these "duplicate puts" are relatively rare, this implementation | |
- * always flushes for simplicity. | |
- */ | |
-int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index, | |
- 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; | |
- struct tmem_hashbucket *hb; | |
- | |
- lock_tmem_state(); | |
- if (!tmem_enabled) | |
- goto disabled; | |
- hb = &pool->hashbucket[tmem_oid_hash(oidp)]; | |
- spin_lock(&hb->lock); | |
- obj = objfound = tmem_obj_find(hb, oidp); | |
- if (obj != NULL) { | |
- pampd = tmem_pampd_lookup_in_obj(objfound, index); | |
- if (pampd != NULL) { | |
- /* 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, oidp, index); | |
- if (obj->pampd_count == 0) { | |
- objnew = obj; | |
- objfound = NULL; | |
- } | |
- pampd = NULL; | |
- } | |
- } else { | |
- obj = objnew = (*tmem_hostops.obj_alloc)(pool); | |
- if (unlikely(obj == NULL)) { | |
- ret = -ENOMEM; | |
- goto out; | |
- } | |
- tmem_obj_init(obj, hb, pool, oidp); | |
- } | |
- BUG_ON(obj == NULL); | |
- BUG_ON(((objnew != obj) && (objfound != obj)) || (objnew == objfound)); | |
- 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); | |
- if (unlikely(ret == -ENOMEM)) | |
- /* may have partially built objnode tree ("stump") */ | |
- goto delete_and_free; | |
- goto out; | |
- | |
-delete_and_free: | |
- (void)tmem_pampd_delete_from_obj(obj, index); | |
-free: | |
- if (pampd) | |
- (*tmem_pamops.free)(pampd, pool, NULL, 0); | |
- if (objnew) { | |
- tmem_obj_free(objnew, hb); | |
- (*tmem_hostops.obj_free)(objnew, pool); | |
- } | |
-out: | |
- spin_unlock(&hb->lock); | |
-disabled: | |
- unlock_tmem_state(); | |
- return ret; | |
-} | |
- | |
-/* | |
- * "Get" a page, e.g. if one can be found, copy the tmem page with the | |
- * matching handle from PAM space to the kernel. By tmem definition, | |
- * when a "get" is successful on an ephemeral page, the page is "flushed", | |
- * and when a "get" is successful on a persistent page, the page is retained | |
- * in tmem. Note that to preserve | |
- * coherency, "get" can never be skipped if tmem contains the data. | |
- * That is, if a get is done with a certain handle and fails, any | |
- * subsequent "get" must also fail (unless of course there is a | |
- * "put" done with the same handle). | |
- | |
- */ | |
-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); | |
- int ret = -1; | |
- struct tmem_hashbucket *hb; | |
- bool free = (get_and_free == 1) || ((get_and_free == 0) && ephemeral); | |
- bool lock_held = false; | |
- | |
- lock_tmem_state(); | |
- if (!tmem_enabled) | |
- goto disabled; | |
- 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; | |
- if (free) | |
- pampd = tmem_pampd_delete_from_obj(obj, index); | |
- else | |
- pampd = tmem_pampd_lookup_in_obj(obj, index); | |
- if (pampd == NULL) | |
- goto out; | |
- 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: | |
- if (lock_held) | |
- spin_unlock(&hb->lock); | |
-disabled: | |
- unlock_tmem_state(); | |
- return ret; | |
-} | |
- | |
-/* | |
- * If a page in tmem matches the handle, "flush" this page from tmem such | |
- * that any subsequent "get" does not succeed (unless, of course, there | |
- * was another "put" with the same handle). | |
- */ | |
-int tmem_flush_page(struct tmem_pool *pool, | |
- struct tmem_oid *oidp, uint32_t index) | |
-{ | |
- struct tmem_obj *obj; | |
- void *pampd; | |
- 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; | |
- pampd = tmem_pampd_delete_from_obj(obj, index); | |
- if (pampd == NULL) | |
- goto out; | |
- (*tmem_pamops.free)(pampd, pool, oidp, index); | |
- if (obj->pampd_count == 0) { | |
- tmem_obj_free(obj, hb); | |
- (*tmem_hostops.obj_free)(obj, pool); | |
- } | |
- ret = 0; | |
- | |
-out: | |
- spin_unlock(&hb->lock); | |
- return ret; | |
-} | |
- | |
-/* | |
- * 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; | |
- | |
- lock_tmem_state(); | |
- if (!tmem_enabled) | |
- goto disabled; | |
- 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); | |
-disabled: | |
- unlock_tmem_state(); | |
- return ret; | |
-} | |
- | |
-/* | |
- * "Flush" all pages in tmem matching this oid. | |
- */ | |
-int tmem_flush_object(struct tmem_pool *pool, struct tmem_oid *oidp) | |
-{ | |
- struct tmem_obj *obj; | |
- struct tmem_hashbucket *hb; | |
- int ret = -1; | |
- | |
- hb = &pool->hashbucket[tmem_oid_hash(oidp)]; | |
- spin_lock(&hb->lock); | |
- obj = tmem_obj_find(hb, oidp); | |
- if (obj == NULL) | |
- goto out; | |
- tmem_pampd_destroy_all_in_obj(obj); | |
- tmem_obj_free(obj, hb); | |
- (*tmem_hostops.obj_free)(obj, pool); | |
- ret = 0; | |
- | |
-out: | |
- spin_unlock(&hb->lock); | |
- return ret; | |
-} | |
- | |
-/* | |
- * "Flush" all pages (and tmem_objs) from this tmem_pool and disable | |
- * all subsequent access to this tmem_pool. | |
- */ | |
-int tmem_destroy_pool(struct tmem_pool *pool) | |
-{ | |
- int ret = -1; | |
- | |
- if (pool == NULL) | |
- goto out; | |
- tmem_pool_flush(pool, 1); | |
- ret = 0; | |
-out: | |
- return ret; | |
-} | |
- | |
-int tmem_flush_pool(struct tmem_pool *pool) | |
-{ | |
- int ret = -1; | |
- | |
- if (pool == NULL) | |
- goto out; | |
- tmem_pool_flush(pool, 0); | |
- ret = 0; | |
-out: | |
- return ret; | |
-} | |
- | |
-static LIST_HEAD(tmem_global_pool_list); | |
- | |
-/* | |
- * Create a new tmem_pool with the provided flag and return | |
- * a pool id provided by the tmem host implementation. | |
- */ | |
-void tmem_new_pool(struct tmem_pool *pool, uint32_t flags) | |
-{ | |
- int persistent = flags & TMEM_POOL_PERSIST; | |
- int shared = flags & TMEM_POOL_SHARED; | |
- struct tmem_hashbucket *hb = &pool->hashbucket[0]; | |
- int i; | |
- | |
- for (i = 0; i < TMEM_HASH_BUCKETS; i++, hb++) { | |
- hb->obj_rb_root = RB_ROOT; | |
- spin_lock_init(&hb->lock); | |
- } | |
- INIT_LIST_HEAD(&pool->pool_list); | |
- atomic_set(&pool->obj_count, 0); | |
- SET_SENTINEL(pool, POOL); | |
- list_add_tail(&pool->pool_list, &tmem_global_pool_list); | |
- pool->persistent = persistent; | |
- pool->shared = shared; | |
-} | |
- | |
-/* The following must be called with tmem state locked */ | |
-static void tmem_cleanup(void) | |
-{ | |
- (*tmem_hostops.flush_all_obj)(); | |
-} | |
- | |
-void tmem_enable(void) | |
-{ | |
- pr_info("turning tmem on\n"); | |
- tmem_enabled = true; | |
- | |
- (*tmem_hostops.control)(false); | |
-} | |
- | |
-void tmem_disable(void) | |
-{ | |
- pr_info("turning tmem off\n"); | |
- tmem_enabled = false; | |
- | |
- tmem_cleanup(); | |
- (*tmem_hostops.control)(true); | |
-} | |
diff --git a/drivers/staging/qcache/tmem.h b/drivers/staging/qcache/tmem.h | |
deleted file mode 100644 | |
index 359c201..0000000 | |
--- a/drivers/staging/qcache/tmem.h | |
+++ /dev/null | |
@@ -1,212 +0,0 @@ | |
-/* | |
- * tmem.h | |
- * | |
- * Transcendent memory | |
- * | |
- * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp. | |
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. | |
- */ | |
- | |
-#ifndef _TMEM_H_ | |
-#define _TMEM_H_ | |
- | |
-#include <linux/types.h> | |
-#include <linux/highmem.h> | |
-#include <linux/hash.h> | |
-#include <linux/atomic.h> | |
-#include <linux/fmem.h> | |
- | |
-/* | |
- * These are pre-defined by the Xen<->Linux ABI | |
- */ | |
-#define TMEM_PUT_PAGE 4 | |
-#define TMEM_GET_PAGE 5 | |
-#define TMEM_FLUSH_PAGE 6 | |
-#define TMEM_FLUSH_OBJECT 7 | |
-#define TMEM_POOL_PERSIST 1 | |
-#define TMEM_POOL_SHARED 2 | |
-#define TMEM_POOL_PRECOMPRESSED 4 | |
-#define TMEM_POOL_PAGESIZE_SHIFT 4 | |
-#define TMEM_POOL_PAGESIZE_MASK 0xf | |
-#define TMEM_POOL_RESERVED_BITS 0x00ffff00 | |
- | |
-/* | |
- * sentinels have proven very useful for debugging but can be removed | |
- * or disabled before final merge. | |
- */ | |
-#define SENTINELS | |
-#ifdef SENTINELS | |
-#define DECL_SENTINEL uint32_t sentinel; | |
-#define SET_SENTINEL(_x, _y) (_x->sentinel = _y##_SENTINEL) | |
-#define INVERT_SENTINEL(_x, _y) (_x->sentinel = ~_y##_SENTINEL) | |
-#define ASSERT_SENTINEL(_x, _y) WARN_ON(_x->sentinel != _y##_SENTINEL) | |
-#define ASSERT_INVERTED_SENTINEL(_x, _y) WARN_ON(_x->sentinel != ~_y##_SENTINEL) | |
-#else | |
-#define DECL_SENTINEL | |
-#define SET_SENTINEL(_x, _y) do { } while (0) | |
-#define INVERT_SENTINEL(_x, _y) do { } while (0) | |
-#define ASSERT_SENTINEL(_x, _y) do { } while (0) | |
-#define ASSERT_INVERTED_SENTINEL(_x, _y) do { } while (0) | |
-#endif | |
- | |
-/* | |
- * A pool is the highest-level data structure managed by tmem and | |
- * usually corresponds to a large independent set of pages such as | |
- * a filesystem. Each pool has an id, and certain attributes and counters. | |
- * It also contains a set of hash buckets, each of which contains an rbtree | |
- * of objects and a lock to manage concurrency within the pool. | |
- */ | |
- | |
-#define TMEM_HASH_BUCKET_BITS 8 | |
-#define TMEM_HASH_BUCKETS (1<<TMEM_HASH_BUCKET_BITS) | |
- | |
-struct tmem_hashbucket { | |
- struct rb_root obj_rb_root; | |
- spinlock_t lock; | |
-}; | |
- | |
-struct tmem_pool { | |
- void *client; /* "up" for some clients, avoids table lookup */ | |
- struct list_head pool_list; | |
- uint32_t pool_id; | |
- bool persistent; | |
- bool shared; | |
- atomic_t obj_count; | |
- atomic_t refcount; | |
- struct tmem_hashbucket hashbucket[TMEM_HASH_BUCKETS]; | |
- DECL_SENTINEL | |
-}; | |
- | |
-#define is_persistent(_p) (_p->persistent) | |
-#define is_ephemeral(_p) (!(_p->persistent)) | |
- | |
-/* | |
- * An object id ("oid") is large: 192-bits (to ensure, for example, files | |
- * in a modern filesystem can be uniquely identified). | |
- */ | |
- | |
-struct tmem_oid { | |
- uint64_t oid[3]; | |
-}; | |
- | |
-static inline void tmem_oid_set_invalid(struct tmem_oid *oidp) | |
-{ | |
- oidp->oid[0] = oidp->oid[1] = oidp->oid[2] = -1UL; | |
-} | |
- | |
-static inline bool tmem_oid_valid(struct tmem_oid *oidp) | |
-{ | |
- return oidp->oid[0] != -1UL || oidp->oid[1] != -1UL || | |
- oidp->oid[2] != -1UL; | |
-} | |
- | |
-static inline int tmem_oid_compare(struct tmem_oid *left, | |
- struct tmem_oid *right) | |
-{ | |
- int ret; | |
- | |
- if (left->oid[2] == right->oid[2]) { | |
- if (left->oid[1] == right->oid[1]) { | |
- if (left->oid[0] == right->oid[0]) | |
- ret = 0; | |
- else if (left->oid[0] < right->oid[0]) | |
- ret = -1; | |
- else | |
- return 1; | |
- } else if (left->oid[1] < right->oid[1]) | |
- ret = -1; | |
- else | |
- ret = 1; | |
- } else if (left->oid[2] < right->oid[2]) | |
- ret = -1; | |
- else | |
- ret = 1; | |
- return ret; | |
-} | |
- | |
-static inline unsigned tmem_oid_hash(struct tmem_oid *oidp) | |
-{ | |
- return hash_long(oidp->oid[0] ^ oidp->oid[1] ^ oidp->oid[2], | |
- TMEM_HASH_BUCKET_BITS); | |
-} | |
- | |
-/* | |
- * A tmem_obj contains an identifier (oid), pointers to the parent | |
- * pool and the rb_tree to which it belongs, counters, and an ordered | |
- * set of pampds, structured in a radix-tree-like tree. The intermediate | |
- * nodes of the tree are called tmem_objnodes. | |
- */ | |
- | |
-struct tmem_objnode; | |
- | |
-struct tmem_obj { | |
- struct tmem_oid oid; | |
- struct tmem_pool *pool; | |
- struct rb_node rb_tree_node; | |
- struct tmem_objnode *objnode_tree_root; | |
- unsigned int objnode_tree_height; | |
- unsigned long objnode_count; | |
- long pampd_count; | |
- void *extra; /* for private use by pampd implementation */ | |
- DECL_SENTINEL | |
-}; | |
- | |
-#define OBJNODE_TREE_MAP_SHIFT 6 | |
-#define OBJNODE_TREE_MAP_SIZE (1UL << OBJNODE_TREE_MAP_SHIFT) | |
-#define OBJNODE_TREE_MAP_MASK (OBJNODE_TREE_MAP_SIZE-1) | |
-#define OBJNODE_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long)) | |
-#define OBJNODE_TREE_MAX_PATH \ | |
- (OBJNODE_TREE_INDEX_BITS/OBJNODE_TREE_MAP_SHIFT + 2) | |
- | |
-struct tmem_objnode { | |
- struct tmem_obj *obj; | |
- DECL_SENTINEL | |
- void *slots[OBJNODE_TREE_MAP_SIZE]; | |
- unsigned int slots_in_use; | |
-}; | |
- | |
-/* pampd abstract datatype methods provided by the PAM implementation */ | |
-struct tmem_pamops { | |
- 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); | |
- | |
-/* memory allocation methods provided by the host implementation */ | |
-struct tmem_hostops { | |
- struct tmem_obj *(*obj_alloc)(struct tmem_pool *); | |
- void (*obj_free)(struct tmem_obj *, struct tmem_pool *); | |
- struct tmem_objnode *(*objnode_alloc)(struct tmem_pool *); | |
- void (*objnode_free)(struct tmem_objnode *, struct tmem_pool *); | |
- void (*flush_all_obj)(void); | |
- void (*control)(bool); | |
-}; | |
-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, | |
- char *, size_t, bool, bool); | |
-extern int tmem_get(struct tmem_pool *, struct tmem_oid *, uint32_t index, | |
- 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 *); | |
-extern int tmem_destroy_pool(struct tmem_pool *); | |
-extern int tmem_flush_pool(struct tmem_pool *); | |
-extern void tmem_new_pool(struct tmem_pool *, uint32_t); | |
- | |
-extern void tmem_enable(void); | |
-extern void tmem_disable(void); | |
-#endif /* _TMEM_H */ | |
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c | |
index 303fb9f..a814813 100644 | |
--- a/drivers/video/fbsysfs.c | |
+++ b/drivers/video/fbsysfs.c | |
@@ -320,7 +320,7 @@ static ssize_t show_blank(struct device *device, | |
// struct fb_info *fb_info = dev_get_drvdata(device); | |
return 0; | |
} | |
- | |
+#endif | |
static ssize_t store_console(struct device *device, | |
struct device_attribute *attr, | |
const char *buf, size_t count) | |
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig | |
index 1f07109..6cf8467 100644 | |
--- a/drivers/video/msm/Kconfig | |
+++ b/drivers/video/msm/Kconfig | |
@@ -1055,4 +1055,7 @@ config FB_MSM_EBI2_PANEL_DETECT | |
if FB_MSM_MDSS | |
source "drivers/video/msm/mdss/Kconfig" | |
endif | |
+config FB_MSM_ALIGN_BUFFER | |
+ bool "Enable a buffer alignment hack (for recovery)." | |
+ default y | |
endif | |
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile | |
index 4bab5ea..6343e01 100644 | |
--- a/drivers/video/msm/Makefile | |
+++ b/drivers/video/msm/Makefile | |
@@ -78,20 +78,19 @@ obj-$(CONFIG_FB_MSM_MIPI_DSI) += msm_mipi.o | |
ifneq ($(CONFIG_FB_MSM_MIPI_PANEL_DETECT),y) | |
# MIPI manufacture | |
obj-$(CONFIG_FB_MSM_MIPI_DSI_TOSHIBA) += mipi_toshiba.o | |
-obj-$(CONFIG_FB_MSM_MIPI_DSI_NOVATEK) += mipi_novatek.o | |
obj-$(CONFIG_FB_MSM_MIPI_DSI_ORISE) += mipi_orise.o | |
obj-$(CONFIG_FB_MSM_MIPI_DSI_RENESAS) += mipi_renesas.o | |
obj-$(CONFIG_FB_MSM_MIPI_DSI_TRULY) += mipi_truly.o | |
obj-$(CONFIG_FB_MSM_MIPI_DSI_NT35510) += mipi_NT35510.o | |
-obj-$(CONFIG_FB_MSM_MIPI_DSI_HX8389B) += mipi_hx8389b.o | |
-obj-$(CONFIG_FB_MSM_MIPI_DSI_OTM9605A) += mipi_otm9605a.o | |
+ | |
+ | |
obj-$(CONFIG_FB_MSM_MIPI_DSI_NT35516) += mipi_truly_tft540960_1_e.o | |
-obj-$(CONFIG_FB_MSM_MIPI_DSI_NT35590) += mipi_NT35590.o | |
+ | |
obj-$(CONFIG_FB_MSM_MIPI_DSI_HX8392A) += mipi_hx8392a.o | |
obj-$(CONFIG_FB_MSM_MIPI_DSI_SIMULATOR) += mipi_simulator.o | |
# MIPI Bridge | |
-obj-$(CONFIG_FB_MSM_MIPI_DSI_TC358764_DSI2LVDS) += mipi_tc358764_dsi2lvds.o | |
+# obj-$(CONFIG_FB_MSM_MIPI_DSI_TC358764_DSI2LVDS) += mipi_tc358764_dsi2lvds.o | |
endif | |
# TVEnc | |
@@ -104,6 +103,7 @@ endif | |
obj-y += msm_fb_panel.o | |
obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_tmd20.o | |
obj-$(CONFIG_FB_MSM_EBI2_TMD_QVGA_EPSON_QCIF) += ebi2_l2f.o | |
+obj-$(CONFIG_FB_MSM_EBI2_TOVIS_QVGA) += ebi2_tovis.o | |
ifeq ($(CONFIG_FB_MSM_MDDI_AUTO_DETECT),y) | |
obj-y += mddi_prism.o | |
@@ -131,8 +131,8 @@ ifeq ($(CONFIG_FB_MSM_MIPI_PANEL_DETECT),y) | |
# obj-y += mipi_orise_video_720p_pt.o mipi_orise_cmd_720p_pt.o | |
# obj-y += mipi_renesas_video_fwvga_pt.o mipi_renesas_cmd_fwvga_pt.o | |
#ifeq ($(CONFIG_FB_MSM_MIPI_DIV4_WVGA_NT35510_PANEL),y) | |
-#obj-y += mipi_NT35510.o mipi_NT35510_cmd_wvga_pt.o | |
-#obj-y += mipi_NT35510.o mipi_NT35510_video_wvga_pt.o | |
+obj-y += mipi_NT35510.o mipi_NT35510_cmd_wvga_pt.o | |
+obj-y += mipi_NT35510.o mipi_NT35510_video_wvga_pt.o | |
#else | |
#obj-y += mipi_nt35516_e808t.o | |
obj-y += mipi_div4_nt35510_cmd_wvga.o | |
@@ -160,7 +160,7 @@ obj-$(CONFIG_FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT) += mipi_truly_video_wvga_pt.o | |
obj-$(CONFIG_FB_MSM_MIPI_NT35510_CMD_WVGA_PT) += mipi_NT35510_cmd_wvga_pt.o | |
obj-$(CONFIG_FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT) += mipi_NT35510_video_wvga_pt.o | |
obj-$(CONFIG_FB_MSM_MIPI_HX8389B_VIDEO_QHD_PT) += mipi_hx8389b_video_qhd_pt.o | |
-obj-$(CONFIG_FB_MSM_MIPI_OTM9605A_VIDEO_QHD_PT) += mipi_otm9605a_video_qhd_pt.o | |
+ | |
obj-$(CONFIG_FB_MSM_MIPI_NT35516_CMD_QHD_PT) += mipi_truly_tft540960_1_e_cmd_qhd_pt.o | |
obj-$(CONFIG_FB_MSM_MIPI_NT35516_VIDEO_QHD_PT) += mipi_truly_tft540960_1_e_video_qhd_pt.o | |
obj-$(CONFIG_FB_MSM_MIPI_NT35590_CMD_720P_PT) += mipi_NT35590_cmd_720p_pt.o mipi_NT35590_video_720p_pt.o | |
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c | |
index d9bb4b9..25a4fa7 100644 | |
--- a/drivers/video/msm/external_common.c | |
+++ b/drivers/video/msm/external_common.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/video/msm/external_common.h b/drivers/video/msm/external_common.h | |
index 4374154..6f5529b 100644 | |
--- a/drivers/video/msm/external_common.h | |
+++ b/drivers/video/msm/external_common.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c | |
index c8d3ca1..041f6f2 100644 | |
--- a/drivers/video/msm/hdmi_msm.c | |
+++ b/drivers/video/msm/hdmi_msm.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/video/msm/hdmi_msm.h b/drivers/video/msm/hdmi_msm.h | |
index 76ffce5..46014a3 100644 | |
--- a/drivers/video/msm/hdmi_msm.h | |
+++ b/drivers/video/msm/hdmi_msm.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, The Linux Foundation. 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 and | |
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c | |
index 41c7913..5e31557 100755 | |
--- a/drivers/video/msm/mdp.c | |
+++ b/drivers/video/msm/mdp.c | |
@@ -2,7 +2,7 @@ | |
* | |
* MSM MDP Interface (used by framebuffer core) | |
* | |
- * Copyright (c) 2007-2013, The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved. | |
* Copyright (C) 2007 Google Incorporated | |
* | |
* This software is licensed under the terms of the GNU General Public | |
@@ -956,6 +956,7 @@ int mdp_histogram_start(struct mdp_histogram_start_req *req) | |
mgmt->frame_cnt = req->frame_cnt; | |
mgmt->bit_mask = req->bit_mask; | |
mgmt->num_bins = req->num_bins; | |
+ mgmt->hist = NULL; | |
ret = mdp_histogram_enable(mgmt); | |
@@ -2391,6 +2392,7 @@ static int mdp_probe(struct platform_device *pdev) | |
unsigned long cur_addr; | |
struct splash_pages page_data; | |
+ | |
if ((pdev->id == 0) && (pdev->num_resources > 0)) { | |
mdp_init_pdev = pdev; | |
mdp_pdata = pdev->dev.platform_data; | |
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h | |
index 09d7bc8..0ddad02 100644 | |
--- a/drivers/video/msm/mdp.h | |
+++ b/drivers/video/msm/mdp.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2008-2012, The Linux Foundation. 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 and | |
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h | |
index bc69958..595e2b1 100644 | |
--- a/drivers/video/msm/mdp4.h | |
+++ b/drivers/video/msm/mdp4.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2009-2013, The Linux Foundation. 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 and | |
@@ -720,11 +720,9 @@ static inline void mdp4_dsi_video_base_swap(int cndx, | |
} | |
static inline void mdp4_dsi_cmd_blt_start(struct msm_fb_data_type *mfd) | |
{ | |
- /* empty */ | |
} | |
static inline void mdp4_dsi_cmd_blt_stop(struct msm_fb_data_type *mfd) | |
{ | |
- /* empty */ | |
} | |
#endif /* CONFIG_FB_MSM_MIPI_DSI */ | |
diff --git a/drivers/video/msm/mdp4_hsic.c b/drivers/video/msm/mdp4_hsic.c | |
index 9b45231..5735f45 100644 | |
--- a/drivers/video/msm/mdp4_hsic.c | |
+++ b/drivers/video/msm/mdp4_hsic.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2009-2011, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2009-2011, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c | |
index 9a4c6ef..506e782 100644 | |
--- a/drivers/video/msm/mdp4_overlay.c | |
+++ b/drivers/video/msm/mdp4_overlay.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2009-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c | |
index 40c0788..d0d2b09 100644 | |
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c | |
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2011-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/video/msm/mdp4_overlay_mddi.c b/drivers/video/msm/mdp4_overlay_mddi.c | |
index 717bba9..db81a6d 100644 | |
--- a/drivers/video/msm/mdp4_overlay_mddi.c | |
+++ b/drivers/video/msm/mdp4_overlay_mddi.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2009-2012, Linux Foundation. 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 and | |
diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c | |
index 43e8f56..54e60ab 100644 | |
--- a/drivers/video/msm/mdp4_overlay_writeback.c | |
+++ b/drivers/video/msm/mdp4_overlay_writeback.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2011-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c | |
index 469e5bc..1e4ab23 100644 | |
--- a/drivers/video/msm/mdp4_util.c | |
+++ b/drivers/video/msm/mdp4_util.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2009-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/video/msm/mdp4_wfd_writeback.c b/drivers/video/msm/mdp4_wfd_writeback.c | |
index d96fc7d..ae459cc 100644 | |
--- a/drivers/video/msm/mdp4_wfd_writeback.c | |
+++ b/drivers/video/msm/mdp4_wfd_writeback.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2011, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2011-2013, The Linux Foundation. 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 and | |
diff --git a/drivers/video/msm/mdp_hw_init.c b/drivers/video/msm/mdp_hw_init.c | |
index e937dbe..fc2a00d 100644 | |
--- a/drivers/video/msm/mdp_hw_init.c | |
+++ b/drivers/video/msm/mdp_hw_init.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2008-2009, 2013 The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2008-2009, 2012 The Linux Foundation. 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 and | |
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h | |
index e1b7179..a58c3e6 100644 | |
--- a/drivers/video/msm/mdss/mdss.h | |
+++ b/drivers/video/msm/mdss/mdss.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c | |
index 5b658a5..fda7094 100644 | |
--- a/drivers/video/msm/mdss/mdss_fb.c | |
+++ b/drivers/video/msm/mdss/mdss_fb.c | |
@@ -2,7 +2,7 @@ | |
* Core MDSS framebuffer driver. | |
* | |
* Copyright (C) 2007 Google Incorporated | |
- * Copyright (c) 2008-2012, The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved. | |
* | |
* This software is licensed under the terms of the GNU General Public | |
* License version 2, as published by the Free Software Foundation, and | |
@@ -16,7 +16,6 @@ | |
#define pr_fmt(fmt) "%s: " fmt, __func__ | |
-#include <linux/android_pmem.h> | |
#include <linux/bootmem.h> | |
#include <linux/console.h> | |
#include <linux/debugfs.h> | |
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h | |
index 98c967d..51a48d4 100644 | |
--- a/drivers/video/msm/mdss/mdss_fb.h | |
+++ b/drivers/video/msm/mdss/mdss_fb.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2008-2012, Code Aurora Forum. 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 and | |
@@ -14,7 +14,7 @@ | |
#ifndef MDSS_FB_H | |
#define MDSS_FB_H | |
-#include <linux/ion.h> | |
+#include <linux/msm_ion.h> | |
#include <linux/list.h> | |
#include <linux/msm_mdp.h> | |
#include <linux/types.h> | |
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c | |
index 0bcc768..46e49da 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp.c | |
+++ b/drivers/video/msm/mdss/mdss_mdp.c | |
@@ -1,7 +1,7 @@ | |
/* | |
* MDSS MDP Interface (used by framebuffer core) | |
* | |
- * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved. | |
* Copyright (C) 2007 Google Incorporated | |
* | |
* This software is licensed under the terms of the GNU General Public | |
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h | |
index cc516ce..9d7046b 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp.h | |
+++ b/drivers/video/msm/mdss/mdss_mdp.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
@@ -40,6 +40,11 @@ | |
#define MAX_DOWNSCALE_RATIO 4 | |
#define MAX_UPSCALE_RATIO 20 | |
+#define C3_ALPHA 3 /* alpha */ | |
+#define C2_R_Cr 2 /* R/Cr */ | |
+#define C1_B_Cb 1 /* B/Cb */ | |
+#define C0_G_Y 0 /* G/luma */ | |
+ | |
#ifdef MDSS_MDP_DEBUG_REG | |
static inline void mdss_mdp_reg_write(u32 addr, u32 val) | |
{ | |
@@ -171,23 +176,8 @@ struct mdss_mdp_format_params { | |
u8 bpp; | |
u8 alpha_enable; /* source has alpha */ | |
- /* | |
- * number of bits for source component, | |
- * 0 = 1 bit, 1 = 2 bits, 2 = 6 bits, 3 = 8 bits | |
- */ | |
- u8 a_bit; /* component 3, alpha */ | |
- u8 r_bit; /* component 2, R_Cr */ | |
- u8 b_bit; /* component 1, B_Cb */ | |
- u8 g_bit; /* component 0, G_lumz */ | |
- | |
- /* | |
- * unpack pattern | |
- * A = C3, R = C2, B = C1, G = C0 | |
- */ | |
- u8 element3; | |
- u8 element2; | |
- u8 element1; | |
- u8 element0; | |
+ u8 bits[MAX_PLANES]; | |
+ u8 element[MAX_PLANES]; | |
}; | |
struct mdss_mdp_plane_sizes { | |
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c | |
index 8b178cd..c80527d 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c | |
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mdss/mdss_mdp_formats.h b/drivers/video/msm/mdss/mdss_mdp_formats.h | |
index b73f1e9..ee3b8e6 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp_formats.h | |
+++ b/drivers/video/msm/mdss/mdss_mdp_formats.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
@@ -18,311 +18,149 @@ | |
#include "mdss_mdp.h" | |
-#define C3_ALPHA 3 /* alpha */ | |
-#define C2_R_Cr 2 /* R/Cr */ | |
-#define C1_B_Cb 1 /* B/Cb */ | |
-#define C0_G_Y 0 /* G/luma */ | |
+ /* | |
+ * number of bits for source component, | |
+ * 0 = 1 bit, 1 = 2 bits, 2 = 6 bits, 3 = 8 bits | |
+ */ | |
+enum { | |
+ COLOR_4BIT, | |
+ COLOR_5BIT, | |
+ COLOR_6BIT, | |
+ COLOR_8BIT, | |
+}; | |
-static struct mdss_mdp_format_params mdss_mdp_format_map[MDP_IMGTYPE_LIMIT] = { | |
- [MDP_RGB_565] = { | |
- .format = MDP_RGB_565, | |
- .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, | |
- .a_bit = 0, | |
- .r_bit = 1, /* R, 5 bits */ | |
- .b_bit = 1, /* B, 5 bits */ | |
- .g_bit = 2, /* G, 6 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 2, | |
- .element2 = C2_R_Cr, | |
- .element1 = C0_G_Y, | |
- .element0 = C1_B_Cb, | |
- .bpp = 1, /* 2 bpp */ | |
- }, | |
- [MDP_BGR_565] = { | |
- .format = MDP_BGR_565, | |
- .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, | |
- .a_bit = 0, | |
- .r_bit = 1, /* R, 5 bits */ | |
- .b_bit = 1, /* B, 5 bits */ | |
- .g_bit = 2, /* G, 6 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 2, | |
- .element2 = C1_B_Cb, | |
- .element1 = C0_G_Y, | |
- .element0 = C2_R_Cr, | |
- .bpp = 1, /* 2 bpp */ | |
- }, | |
- [MDP_RGB_888] = { | |
- .format = MDP_RGB_888, | |
- .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, | |
- .a_bit = 0, | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 2, | |
- .element2 = C1_B_Cb, | |
- .element1 = C0_G_Y, | |
- .element0 = C2_R_Cr, | |
- .bpp = 2, /* 3 bpp */ | |
- }, | |
- [MDP_XRGB_8888] = { | |
- .format = MDP_XRGB_8888, | |
- .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, | |
- .a_bit = 3, /* alpha, 4 bits */ | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 3, | |
- .element3 = C1_B_Cb, | |
- .element2 = C0_G_Y, | |
- .element1 = C2_R_Cr, | |
- .element0 = C3_ALPHA, | |
- .bpp = 3, /* 4 bpp */ | |
- }, | |
- [MDP_ARGB_8888] = { | |
- .format = MDP_ARGB_8888, | |
- .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, | |
- .a_bit = 3, /* alpha, 4 bits */ | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 1, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 3, | |
- .element3 = C1_B_Cb, | |
- .element2 = C0_G_Y, | |
- .element1 = C2_R_Cr, | |
- .element0 = C3_ALPHA, | |
- .bpp = 3, /* 4 bpp */ | |
- }, | |
- [MDP_RGBA_8888] = { | |
- .format = MDP_RGBA_8888, | |
- .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, | |
- .a_bit = 3, /* alpha, 4 bits */ | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 1, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 3, | |
- .element3 = C3_ALPHA, | |
- .element2 = C1_B_Cb, | |
- .element1 = C0_G_Y, | |
- .element0 = C2_R_Cr, | |
- .bpp = 3, /* 4 bpp */ | |
- }, | |
- [MDP_RGBX_8888] = { | |
- .format = MDP_RGBX_8888, | |
+#define FMT_RGB_565(fmt, e0, e1, e2) \ | |
+ { \ | |
+ .format = (fmt), \ | |
+ .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, \ | |
+ .unpack_tight = 1, \ | |
+ .unpack_align_msb = 0, \ | |
+ .alpha_enable = 0, \ | |
+ .unpack_count = 3, \ | |
+ .bpp = 2, \ | |
+ .element = { (e0), (e1), (e2) }, \ | |
+ .bits = { \ | |
+ [C2_R_Cr] = COLOR_5BIT, \ | |
+ [C0_G_Y] = COLOR_6BIT, \ | |
+ [C1_B_Cb] = COLOR_5BIT, \ | |
+ }, \ | |
+ } | |
+ | |
+#define FMT_RGB_888(fmt, e0, e1, e2) \ | |
+ { \ | |
+ .format = (fmt), \ | |
+ .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, \ | |
+ .unpack_tight = 1, \ | |
+ .unpack_align_msb = 0, \ | |
+ .alpha_enable = 0, \ | |
+ .unpack_count = 3, \ | |
+ .bpp = 3, \ | |
+ .element = { (e0), (e1), (e2) }, \ | |
+ .bits = { \ | |
+ [C2_R_Cr] = COLOR_8BIT, \ | |
+ [C0_G_Y] = COLOR_8BIT, \ | |
+ [C1_B_Cb] = COLOR_8BIT, \ | |
+ }, \ | |
+ } | |
+ | |
+#define FMT_RGB_8888(fmt, alpha_en, e0, e1, e2, e3) \ | |
+ { \ | |
+ .format = (fmt), \ | |
+ .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, \ | |
+ .unpack_tight = 1, \ | |
+ .unpack_align_msb = 0, \ | |
+ .alpha_enable = (alpha_en), \ | |
+ .unpack_count = 4, \ | |
+ .bpp = 4, \ | |
+ .element = { (e0), (e1), (e2), (e3) }, \ | |
+ .bits = { \ | |
+ [C3_ALPHA] = COLOR_8BIT, \ | |
+ [C2_R_Cr] = COLOR_8BIT, \ | |
+ [C0_G_Y] = COLOR_8BIT, \ | |
+ [C1_B_Cb] = COLOR_8BIT, \ | |
+ }, \ | |
+ } | |
+ | |
+#define FMT_YUV_COMMON(fmt) \ | |
+ .format = (fmt), \ | |
+ .is_yuv = 1, \ | |
+ .bits = { \ | |
+ [C2_R_Cr] = COLOR_8BIT, \ | |
+ [C0_G_Y] = COLOR_8BIT, \ | |
+ [C1_B_Cb] = COLOR_8BIT, \ | |
+ }, \ | |
+ .alpha_enable = 0, \ | |
+ .unpack_tight = 1, \ | |
+ .unpack_align_msb = 0 | |
+ | |
+#define FMT_YUV_PSEUDO(fmt, samp, e0, e1) \ | |
+ { \ | |
+ FMT_YUV_COMMON(fmt), \ | |
+ .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR, \ | |
+ .chroma_sample = samp, \ | |
+ .unpack_count = 2, \ | |
+ .bpp = 2, \ | |
+ .element = { (e0), (e1) }, \ | |
+ } | |
+ | |
+#define FMT_YUV_PLANR(fmt, samp, e0, e1) \ | |
+ { \ | |
+ FMT_YUV_COMMON(fmt), \ | |
+ .fetch_planes = MDSS_MDP_PLANE_PLANAR, \ | |
+ .chroma_sample = samp, \ | |
+ .element = { (e0), (e1) } \ | |
+ } | |
+ | |
+static struct mdss_mdp_format_params mdss_mdp_format_map[] = { | |
+ FMT_RGB_565(MDP_RGB_565, C1_B_Cb, C0_G_Y, C2_R_Cr), | |
+ FMT_RGB_565(MDP_BGR_565, C2_R_Cr, C0_G_Y, C1_B_Cb), | |
+ FMT_RGB_888(MDP_RGB_888, C2_R_Cr, C0_G_Y, C1_B_Cb), | |
+ FMT_RGB_888(MDP_BGR_888, C1_B_Cb, C0_G_Y, C2_R_Cr), | |
+ | |
+ FMT_RGB_8888(MDP_XRGB_8888, 0, C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb), | |
+ FMT_RGB_8888(MDP_ARGB_8888, 1, C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb), | |
+ FMT_RGB_8888(MDP_RGBA_8888, 1, C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA), | |
+ FMT_RGB_8888(MDP_RGBX_8888, 0, C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA), | |
+ FMT_RGB_8888(MDP_BGRA_8888, 1, C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA), | |
+ | |
+ FMT_YUV_PSEUDO(MDP_Y_CRCB_H1V1, MDSS_MDP_CHROMA_RGB, C2_R_Cr, C1_B_Cb), | |
+ FMT_YUV_PSEUDO(MDP_Y_CBCR_H1V1, MDSS_MDP_CHROMA_RGB, C1_B_Cb, C2_R_Cr), | |
+ FMT_YUV_PSEUDO(MDP_Y_CRCB_H2V1, MDSS_MDP_CHROMA_H2V1, C2_R_Cr, C1_B_Cb), | |
+ FMT_YUV_PSEUDO(MDP_Y_CBCR_H2V1, MDSS_MDP_CHROMA_H2V1, C1_B_Cb, C2_R_Cr), | |
+ FMT_YUV_PSEUDO(MDP_Y_CRCB_H1V2, MDSS_MDP_CHROMA_H1V2, C2_R_Cr, C1_B_Cb), | |
+ FMT_YUV_PSEUDO(MDP_Y_CBCR_H1V2, MDSS_MDP_CHROMA_H1V2, C1_B_Cb, C2_R_Cr), | |
+ FMT_YUV_PSEUDO(MDP_Y_CRCB_H2V2, MDSS_MDP_CHROMA_420, C2_R_Cr, C1_B_Cb), | |
+ FMT_YUV_PSEUDO(MDP_Y_CBCR_H2V2, MDSS_MDP_CHROMA_420, C1_B_Cb, C2_R_Cr), | |
+ FMT_YUV_PSEUDO(MDP_Y_CBCR_H2V2_VENUS, MDSS_MDP_CHROMA_420, | |
+ C1_B_Cb, C2_R_Cr), | |
+ | |
+ FMT_YUV_PLANR(MDP_Y_CR_CB_H2V2, MDSS_MDP_CHROMA_420, C2_R_Cr, C1_B_Cb), | |
+ FMT_YUV_PLANR(MDP_Y_CB_CR_H2V2, MDSS_MDP_CHROMA_420, C1_B_Cb, C2_R_Cr), | |
+ FMT_YUV_PLANR(MDP_Y_CR_CB_GH2V2, MDSS_MDP_CHROMA_420, C2_R_Cr, C1_B_Cb), | |
+ | |
+ { | |
+ FMT_YUV_COMMON(MDP_YCBCR_H1V1), | |
.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, | |
- .a_bit = 3, | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
+ .chroma_sample = MDSS_MDP_CHROMA_RGB, | |
.unpack_count = 3, | |
- .element3 = C3_ALPHA, | |
- .element2 = C1_B_Cb, | |
- .element1 = C0_G_Y, | |
- .element0 = C2_R_Cr, | |
- .bpp = 3, /* 4 bpp */ | |
+ .bpp = 3, | |
+ .element = { C2_R_Cr, C1_B_Cb, C0_G_Y }, | |
}, | |
- [MDP_BGRA_8888] = { | |
- .format = MDP_BGRA_8888, | |
+ { | |
+ FMT_YUV_COMMON(MDP_YCRCB_H1V1), | |
.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, | |
- .a_bit = 3, /* alpha, 4 bits */ | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 1, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
+ .chroma_sample = MDSS_MDP_CHROMA_RGB, | |
.unpack_count = 3, | |
- .element3 = C3_ALPHA, | |
- .element2 = C2_R_Cr, | |
- .element1 = C0_G_Y, | |
- .element0 = C1_B_Cb, | |
- .bpp = 3, /* 4 bpp */ | |
+ .bpp = 3, | |
+ .element = { C1_B_Cb, C2_R_Cr, C0_G_Y }, | |
}, | |
- [MDP_YCRYCB_H2V1] = { | |
- .format = MDP_YCRYCB_H2V1, | |
- .is_yuv = 1, | |
- .a_bit = 0, | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 1, /* 2 */ | |
- .bpp = 1, /* 2 bpp */ | |
+ { | |
+ FMT_YUV_COMMON(MDP_YCRYCB_H2V1), | |
.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, | |
.chroma_sample = MDSS_MDP_CHROMA_H2V1, | |
- .unpack_count = 3, | |
- .element3 = C0_G_Y, | |
- .element2 = C2_R_Cr, | |
- .element1 = C0_G_Y, | |
- .element0 = C1_B_Cb, | |
- }, | |
- [MDP_Y_CRCB_H2V1] = { | |
- .format = MDP_Y_CRCB_H2V1, | |
- .is_yuv = 1, | |
- .a_bit = 0, | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 1, /* 2 */ | |
- .bpp = 1, /* 2 bpp */ | |
- .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR, | |
- .chroma_sample = MDSS_MDP_CHROMA_H2V1, | |
- .element1 = C1_B_Cb, | |
- .element0 = C2_R_Cr, | |
- }, | |
- [MDP_Y_CBCR_H2V1] = { | |
- .format = MDP_Y_CBCR_H2V1, | |
- .is_yuv = 1, | |
- .a_bit = 0, | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 1, /* 2 */ | |
- .bpp = 1, /* 2 bpp */ | |
- .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR, | |
- .chroma_sample = MDSS_MDP_CHROMA_H2V1, | |
- .element1 = C2_R_Cr, | |
- .element0 = C1_B_Cb, | |
- }, | |
- [MDP_Y_CRCB_H1V2] = { | |
- .format = MDP_Y_CRCB_H1V2, | |
- .is_yuv = 1, | |
- .a_bit = 0, | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 1, /* 2 */ | |
- .bpp = 1, /* 2 bpp */ | |
- .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR, | |
- .chroma_sample = MDSS_MDP_CHROMA_H1V2, | |
- .element1 = C1_B_Cb, | |
- .element0 = C2_R_Cr, | |
- }, | |
- [MDP_Y_CBCR_H1V2] = { | |
- .format = MDP_Y_CBCR_H1V2, | |
- .is_yuv = 1, | |
- .a_bit = 0, | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 1, /* 2 */ | |
- .bpp = 1, /* 2 bpp */ | |
- .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR, | |
- .chroma_sample = MDSS_MDP_CHROMA_H1V2, | |
- .element1 = C2_R_Cr, | |
- .element0 = C1_B_Cb, | |
- }, | |
- [MDP_Y_CRCB_H2V2] = { | |
- .format = MDP_Y_CRCB_H2V2, | |
- .is_yuv = 1, | |
- .a_bit = 0, | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 1, /* 2 */ | |
- .bpp = 1, /* 2 bpp */ | |
- .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR, | |
- .chroma_sample = MDSS_MDP_CHROMA_420, | |
- .element1 = C1_B_Cb, | |
- .element0 = C2_R_Cr, | |
- }, | |
- [MDP_Y_CBCR_H2V2] = { | |
- .format = MDP_Y_CBCR_H2V2, | |
- .is_yuv = 1, | |
- .a_bit = 0, | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 1, /* 2 */ | |
- .bpp = 1, /* 2 bpp */ | |
- .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR, | |
- .chroma_sample = MDSS_MDP_CHROMA_420, | |
- .element1 = C2_R_Cr, | |
- .element0 = C1_B_Cb, | |
- }, | |
- [MDP_Y_CR_CB_H2V2] = { | |
- .format = MDP_Y_CR_CB_H2V2, | |
- .is_yuv = 1, | |
- .a_bit = 0, | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 1, /* 2 */ | |
- .bpp = 1, /* 2 bpp */ | |
- .fetch_planes = MDSS_MDP_PLANE_PLANAR, | |
- .chroma_sample = MDSS_MDP_CHROMA_420, | |
- }, | |
- [MDP_Y_CB_CR_H2V2] = { | |
- .format = MDP_Y_CB_CR_H2V2, | |
- .is_yuv = 1, | |
- .a_bit = 0, | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 1, /* 2 */ | |
- .bpp = 1, /* 2 bpp */ | |
- .fetch_planes = MDSS_MDP_PLANE_PLANAR, | |
- .chroma_sample = MDSS_MDP_CHROMA_420, | |
- }, | |
- [MDP_Y_CR_CB_GH2V2] = { | |
- .format = MDP_Y_CR_CB_GH2V2, | |
- .is_yuv = 1, | |
- .a_bit = 0, | |
- .r_bit = 3, /* R, 8 bits */ | |
- .b_bit = 3, /* B, 8 bits */ | |
- .g_bit = 3, /* G, 8 bits */ | |
- .alpha_enable = 0, | |
- .unpack_tight = 1, | |
- .unpack_align_msb = 0, | |
- .unpack_count = 1, /* 2 */ | |
- .bpp = 1, /* 2 bpp */ | |
- .fetch_planes = MDSS_MDP_PLANE_PLANAR, | |
- .chroma_sample = MDSS_MDP_CHROMA_420, | |
+ .unpack_count = 4, | |
+ .bpp = 2, | |
+ .element = { C1_B_Cb, C0_G_Y, C2_R_Cr, C0_G_Y }, | |
}, | |
}; | |
#endif | |
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h | |
index 068bbf8..4ca1dce 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h | |
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c | |
index 69ea04e..21ef290 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c | |
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c | |
index cd6bd14..8b4434e 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c | |
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
@@ -145,20 +145,24 @@ static int mdss_mdp_writeback_format_setup(struct mdss_mdp_writeback_ctx *ctx) | |
dst_format = (chroma_samp << 23) | | |
(fmt->fetch_planes << 19) | | |
- (fmt->unpack_align_msb << 18) | | |
- (fmt->unpack_tight << 17) | | |
- (fmt->unpack_count << 12) | | |
- (fmt->bpp << 9) | | |
- (fmt->alpha_enable << 8) | | |
- (fmt->a_bit << 6) | | |
- (fmt->r_bit << 4) | | |
- (fmt->b_bit << 2) | | |
- (fmt->g_bit << 0); | |
- | |
- pattern = (fmt->element3 << 24) | | |
- (fmt->element2 << 15) | | |
- (fmt->element1 << 8) | | |
- (fmt->element0 << 0); | |
+ (fmt->bits[C3_ALPHA] << 6) | | |
+ (fmt->bits[C2_R_Cr] << 4) | | |
+ (fmt->bits[C1_B_Cb] << 2) | | |
+ (fmt->bits[C0_G_Y] << 0); | |
+ | |
+ if (fmt->alpha_enable) | |
+ dst_format |= BIT(8); /* DSTC3_EN */ | |
+ | |
+ if (fmt->fetch_planes != MDSS_MDP_PLANE_PLANAR) { | |
+ pattern = (fmt->element[3] << 24) | (fmt->element[2] << 15) | | |
+ (fmt->element[1] << 8) | (fmt->element[0] << 0); | |
+ dst_format |= (fmt->unpack_align_msb << 18) | | |
+ (fmt->unpack_tight << 17) | | |
+ ((fmt->unpack_count - 1) << 12) | | |
+ ((fmt->bpp - 1) << 9); | |
+ } else { | |
+ pattern = 0; | |
+ } | |
ystride0 = (ctx->dst_planes.ystride[0]) | | |
(ctx->dst_planes.ystride[1] << 16); | |
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c | |
index 33e4543..43ddb5e 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c | |
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c | |
index a409102..f38215b 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c | |
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
@@ -362,6 +362,12 @@ static int mdss_mdp_scale_setup(struct mdss_mdp_pipe *pipe) | |
} | |
chroma_sample = pipe->src_fmt->chroma_sample; | |
+ if (pipe->flags & MDP_SOURCE_ROTATED_90) { | |
+ if (chroma_sample == MDSS_MDP_CHROMA_H1V2) | |
+ chroma_sample = MDSS_MDP_CHROMA_H2V1; | |
+ else if (chroma_sample == MDSS_MDP_CHROMA_H2V1) | |
+ chroma_sample = MDSS_MDP_CHROMA_H1V2; | |
+ } | |
if ((pipe->src.h != pipe->dst.h) || | |
(chroma_sample == MDSS_MDP_CHROMA_420) || | |
@@ -522,7 +528,7 @@ static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe) | |
static int mdss_mdp_format_setup(struct mdss_mdp_pipe *pipe) | |
{ | |
struct mdss_mdp_format_params *fmt; | |
- u32 rot90, opmode, chroma_samp; | |
+ u32 opmode, chroma_samp, unpack, src_format; | |
fmt = pipe->src_fmt; | |
@@ -545,26 +551,34 @@ static int mdss_mdp_format_setup(struct mdss_mdp_pipe *pipe) | |
chroma_samp = MDSS_MDP_CHROMA_H2V1; | |
} | |
- mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_FORMAT, | |
- (chroma_samp << 23) | | |
- (fmt->fetch_planes << 19) | | |
- (fmt->unpack_align_msb << 18) | | |
- (fmt->unpack_tight << 17) | | |
- (fmt->unpack_count << 12) | | |
- (rot90 << 11) | | |
- (fmt->bpp << 9) | | |
- (fmt->alpha_enable << 8) | | |
- (fmt->a_bit << 6) | | |
- (fmt->r_bit << 4) | | |
- (fmt->b_bit << 2) | | |
- (fmt->g_bit << 0)); | |
- | |
- mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN, | |
- (fmt->element3 << 24) | | |
- (fmt->element2 << 16) | | |
- (fmt->element1 << 8) | | |
- (fmt->element0 << 0)); | |
+ src_format = (chroma_samp << 23) | | |
+ (fmt->fetch_planes << 19) | | |
+ (fmt->bits[C3_ALPHA] << 6) | | |
+ (fmt->bits[C2_R_Cr] << 4) | | |
+ (fmt->bits[C1_B_Cb] << 2) | | |
+ (fmt->bits[C0_G_Y] << 0); | |
+ | |
+ if (pipe->flags & MDP_ROT_90) | |
+ src_format |= BIT(11); /* ROT90 */ | |
+ | |
+ if (fmt->alpha_enable && | |
+ fmt->fetch_planes != MDSS_MDP_PLANE_INTERLEAVED) | |
+ src_format |= BIT(8); /* SRCC3_EN */ | |
+ | |
+ if (fmt->fetch_planes != MDSS_MDP_PLANE_PLANAR) { | |
+ unpack = (fmt->element[3] << 24) | (fmt->element[2] << 16) | | |
+ (fmt->element[1] << 8) | (fmt->element[0] << 0); | |
+ | |
+ src_format |= ((fmt->unpack_count - 1) << 12) | | |
+ (fmt->unpack_tight << 17) | | |
+ (fmt->unpack_align_msb << 18) | | |
+ ((fmt->bpp - 1) << 9); | |
+ } else { | |
+ unpack = 0; | |
+ } | |
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_FORMAT, src_format); | |
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN, unpack); | |
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_OP_MODE, opmode); | |
return 0; | |
@@ -594,17 +608,23 @@ static int mdss_mdp_vig_setup(struct mdss_mdp_pipe *pipe) | |
static int mdss_mdp_src_addr_setup(struct mdss_mdp_pipe *pipe, | |
struct mdss_mdp_data *data) | |
{ | |
- int ret; | |
+ int is_rot = pipe->mixer->rotator_mode; | |
+ int ret = 0; | |
pr_debug("pnum=%d\n", pipe->num); | |
- if (pipe->type != MDSS_MDP_PIPE_TYPE_DMA) | |
+ if (!is_rot) | |
data->bwc_enabled = pipe->bwc_mode; | |
ret = mdss_mdp_data_check(data, &pipe->src_planes); | |
if (ret) | |
return ret; | |
+ /* planar format expects YCbCr, swap chroma planes if YCrCb */ | |
+ if (!is_rot && (pipe->src_fmt->fetch_planes == MDSS_MDP_PLANE_PLANAR) && | |
+ (pipe->src_fmt->element[0] == C2_R_Cr)) | |
+ swap(data->p[1].addr, data->p[2].addr); | |
+ | |
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC0_ADDR, data->p[0].addr); | |
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC1_ADDR, data->p[1].addr); | |
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC2_ADDR, data->p[2].addr); | |
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c | |
index b84a075..db840a8 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c | |
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c | |
index a23ec87..fc3a843 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c | |
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.h b/drivers/video/msm/mdss/mdss_mdp_rotator.h | |
index 7d39c72..1e4b81e 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.h | |
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c | |
index 41d5bc2..eab6890 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp_util.c | |
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
@@ -12,11 +12,10 @@ | |
*/ | |
#define pr_fmt(fmt) "%s: " fmt, __func__ | |
-#include <linux/android_pmem.h> | |
#include <linux/dma-mapping.h> | |
#include <linux/errno.h> | |
#include <linux/file.h> | |
-#include <linux/ion.h> | |
+#include <linux/msm_ion.h> | |
#include <linux/msm_kgsl.h> | |
#include <linux/spinlock.h> | |
#include <linux/types.h> | |
@@ -164,14 +163,16 @@ done: | |
struct mdss_mdp_format_params *mdss_mdp_get_format_params(u32 format) | |
{ | |
- struct mdss_mdp_format_params *fmt = NULL; | |
if (format < MDP_IMGTYPE_LIMIT) { | |
- fmt = &mdss_mdp_format_map[format]; | |
- if (fmt->format != format) | |
- fmt = NULL; | |
+ struct mdss_mdp_format_params *fmt = NULL; | |
+ int i; | |
+ for (i = 0; i < ARRAY_SIZE(mdss_mdp_format_map); i++) { | |
+ fmt = &mdss_mdp_format_map[i]; | |
+ if (format == fmt->format) | |
+ return fmt; | |
+ } | |
} | |
- | |
- return fmt; | |
+ return NULL; | |
} | |
int mdss_mdp_get_plane_sizes(u32 format, u32 w, u32 h, | |
@@ -193,30 +194,35 @@ int mdss_mdp_get_plane_sizes(u32 format, u32 w, u32 h, | |
memset(ps, 0, sizeof(struct mdss_mdp_plane_sizes)); | |
if (fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) { | |
- u32 bpp = fmt->bpp + 1; | |
+ u32 bpp = fmt->bpp; | |
ps->num_planes = 1; | |
ps->plane_size[0] = w * h * bpp; | |
ps->ystride[0] = w * bpp; | |
} else { | |
u8 hmap[] = { 1, 2, 1, 2 }; | |
u8 vmap[] = { 1, 1, 2, 2 }; | |
- u8 horiz, vert; | |
+ u8 horiz, vert, stride_align; | |
horiz = hmap[fmt->chroma_sample]; | |
vert = vmap[fmt->chroma_sample]; | |
- if (format == MDP_Y_CR_CB_GH2V2) { | |
- ps->plane_size[0] = ALIGN(w, 16) * h; | |
- ps->plane_size[1] = ALIGN(w / horiz, 16) * (h / vert); | |
- ps->ystride[0] = ALIGN(w, 16); | |
- ps->ystride[1] = ALIGN(w / horiz, 16); | |
- } else { | |
- ps->plane_size[0] = w * h; | |
- ps->plane_size[1] = (w / horiz) * (h / vert); | |
- ps->ystride[0] = w; | |
- ps->ystride[1] = (w / horiz); | |
+ switch (format) { | |
+ case MDP_Y_CR_CB_GH2V2: | |
+ stride_align = 16; | |
+ break; | |
+ case MDP_Y_CBCR_H2V2_VENUS: | |
+ stride_align = 32; | |
+ break; | |
+ default: | |
+ stride_align = 1; | |
+ break; | |
} | |
+ ps->ystride[0] = ALIGN(w, stride_align); | |
+ ps->ystride[1] = ALIGN(w / horiz, stride_align); | |
+ ps->plane_size[0] = ps->ystride[0] * h; | |
+ ps->plane_size[1] = ps->ystride[1] * (h / vert); | |
+ | |
if (fmt->fetch_planes == MDSS_MDP_PLANE_PSEUDO_PLANAR) { | |
ps->num_planes = 2; | |
ps->plane_size[1] *= 2; | |
@@ -285,7 +291,6 @@ int mdss_mdp_put_img(struct mdss_mdp_img_data *data) | |
return 0; | |
} | |
if (data->srcp_file) { | |
- put_pmem_file(data->srcp_file); | |
data->srcp_file = NULL; | |
return 0; | |
} | |
@@ -331,10 +336,6 @@ int mdss_mdp_get_img(struct ion_client *iclient, struct msmfb_data *img, | |
return PTR_ERR(data->srcp_ihdl); | |
ret = ion_phys(iclient, data->srcp_ihdl, | |
start, (size_t *) len); | |
- } else { | |
- unsigned long vstart; | |
- ret = get_pmem_file(img->memory_id, start, &vstart, len, | |
- &data->srcp_file); | |
} | |
if (!ret && (img->offset < data->len)) { | |
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c | |
index 82bcf57..da55edc 100644 | |
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c | |
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h | |
index f5ee212..3fd943d 100644 | |
--- a/drivers/video/msm/mdss/mdss_panel.h | |
+++ b/drivers/video/msm/mdss/mdss_panel.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2008-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mdss/mdss_wb.c b/drivers/video/msm/mdss/mdss_wb.c | |
index 78dfd6f..3be4525 100644 | |
--- a/drivers/video/msm/mdss/mdss_wb.c | |
+++ b/drivers/video/msm/mdss/mdss_wb.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2011-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mhl/mhl_8334.c b/drivers/video/msm/mhl/mhl_8334.c | |
index c7ba590..d6e3f6f 100644 | |
--- a/drivers/video/msm/mhl/mhl_8334.c | |
+++ b/drivers/video/msm/mhl/mhl_8334.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mhl/mhl_8334.h b/drivers/video/msm/mhl/mhl_8334.h | |
index 693532d..eba544a 100644 | |
--- a/drivers/video/msm/mhl/mhl_8334.h | |
+++ b/drivers/video/msm/mhl/mhl_8334.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mhl/mhl_defs.h b/drivers/video/msm/mhl/mhl_defs.h | |
index 9e85f07..094874e 100644 | |
--- a/drivers/video/msm/mhl/mhl_defs.h | |
+++ b/drivers/video/msm/mhl/mhl_defs.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mhl/mhl_devcap.h b/drivers/video/msm/mhl/mhl_devcap.h | |
index 40a87fe..6d01daf 100644 | |
--- a/drivers/video/msm/mhl/mhl_devcap.h | |
+++ b/drivers/video/msm/mhl/mhl_devcap.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mhl/mhl_i2c_utils.c b/drivers/video/msm/mhl/mhl_i2c_utils.c | |
index 2120f1f..aab6e02 100644 | |
--- a/drivers/video/msm/mhl/mhl_i2c_utils.c | |
+++ b/drivers/video/msm/mhl/mhl_i2c_utils.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mhl/mhl_i2c_utils.h b/drivers/video/msm/mhl/mhl_i2c_utils.h | |
index 94daad7..76498d4 100644 | |
--- a/drivers/video/msm/mhl/mhl_i2c_utils.h | |
+++ b/drivers/video/msm/mhl/mhl_i2c_utils.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c | |
index b3544d5..ad8d187 100644 | |
--- a/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c | |
+++ b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c | |
@@ -93,8 +93,6 @@ static int mipi_cmd_nt35510_wvga_pt_init(void) | |
if (ret) | |
pr_err("%s: failed to register device!\n", __func__); | |
- pr_debug("%s: X\n", __func__); | |
- | |
return ret; | |
} | |
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c | |
index 7848dbc..9d6f835 100755 | |
--- a/drivers/video/msm/mipi_dsi.c | |
+++ b/drivers/video/msm/mipi_dsi.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2008-2012, Code Aurora Forum. 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 and | |
@@ -100,6 +100,8 @@ static int mipi_dsi_off(struct platform_device *pdev) | |
struct msm_fb_data_type *mfd; | |
struct msm_panel_info *pinfo; | |
+ pr_debug("%s+:\n", __func__); | |
+ | |
mfd = platform_get_drvdata(pdev); | |
pinfo = &mfd->panel_info; | |
@@ -136,7 +138,6 @@ static int mipi_dsi_off(struct platform_device *pdev) | |
} | |
ret = panel_next_off(pdev); | |
- | |
#ifdef CONFIG_MSM_BUS_SCALING | |
mdp_bus_scale_update_request(0); | |
#endif | |
@@ -152,7 +153,7 @@ static int mipi_dsi_off(struct platform_device *pdev) | |
mipi_dsi_ahb_ctrl(0); | |
spin_unlock_bh(&dsi_clk_lock); | |
- mipi_dsi_unprepare_clocks(); | |
+ mipi_dsi_unprepare_clocks(); | |
if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save) | |
mipi_dsi_pdata->dsi_power_save(0); | |
@@ -180,6 +181,8 @@ static int mipi_dsi_on(struct platform_device *pdev) | |
u32 dummy_xres, dummy_yres; | |
int target_type = 0; | |
+ pr_debug("%s+:\n", __func__); | |
+ | |
mfd = platform_get_drvdata(pdev); | |
fbi = mfd->fbi; | |
var = &fbi->var; | |
@@ -342,10 +345,6 @@ static int mipi_dsi_on(struct platform_device *pdev) | |
} | |
} | |
-#ifdef CONFIG_MSM_BUS_SCALING | |
- mdp_bus_scale_update_request(2); | |
-#endif | |
- | |
mdp4_overlay_dsi_state_set(ST_DSI_RESUME); | |
if (mdp_rev >= MDP_REV_41) | |
@@ -359,6 +358,13 @@ static int mipi_dsi_on(struct platform_device *pdev) | |
} | |
+ | |
+static int mipi_dsi_late_init(struct platform_device *pdev) | |
+{ | |
+ return panel_next_late_init(pdev); | |
+} | |
+ | |
+ | |
static int mipi_dsi_resource_initialized; | |
static int mipi_dsi_probe(struct platform_device *pdev) | |
@@ -505,6 +511,7 @@ static int mipi_dsi_probe(struct platform_device *pdev) | |
pdata = mdp_dev->dev.platform_data; | |
pdata->on = mipi_dsi_on; | |
pdata->off = mipi_dsi_off; | |
+ pdata->late_init = mipi_dsi_late_init; | |
pdata->next = pdev; | |
/* | |
diff --git a/drivers/video/msm/mipi_dsi.h b/drivers/video/msm/mipi_dsi.h | |
index ef6bddf..4bf1094 100755 | |
--- a/drivers/video/msm/mipi_dsi.h | |
+++ b/drivers/video/msm/mipi_dsi.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2009-2013, The Linux Foundation. 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 and | |
@@ -188,7 +188,7 @@ struct dsi_clk_desc { | |
#define DSI_HDR_DATA1(data) ((data) & 0x0ff) | |
#define DSI_HDR_WC(wc) ((wc) & 0x0ffff) | |
-#define DSI_BUF_SIZE 64 | |
+#define DSI_BUF_SIZE 1024 | |
#define MIPI_DSI_MRPS 0x04 /* Maximum Return Packet Size */ | |
#define MIPI_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align */ | |
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c | |
index 94c0df7..67c7a92 100755 | |
--- a/drivers/video/msm/mipi_dsi_host.c | |
+++ b/drivers/video/msm/mipi_dsi_host.c | |
@@ -1,5 +1,4 @@ | |
- | |
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2008-2012, Code Aurora Forum. 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 and | |
@@ -183,6 +182,8 @@ void mipi_dsi_clk_cfg(int on) | |
} | |
} | |
} | |
+ pr_debug("%s: on=%d clk_cnt=%d pid=%d\n", __func__, | |
++ on, dsi_clk_cnt, current->pid); | |
spin_unlock_irqrestore(&mdp_spin_lock, flags); | |
} | |
@@ -1056,6 +1057,7 @@ void mipi_dsi_cmd_mdp_start(void) | |
spin_lock_irqsave(&dsi_mdp_lock, flag); | |
mipi_dsi_enable_irq(DSI_MDP_TERM); | |
dsi_mdp_busy = TRUE; | |
+ INIT_COMPLETION(dsi_mdp_comp); | |
spin_unlock_irqrestore(&dsi_mdp_lock, flag); | |
} | |
@@ -1534,25 +1536,28 @@ int mipi_dsi_cmd_dma_rx(struct dsi_buf *rp, int rlen) | |
void mipi_dsi_cmd_mdp_busy(void) | |
{ | |
- u32 status; | |
unsigned long flags; | |
int need_wait = 0; | |
+ pr_debug("%s: start pid=%d\n", | |
+ __func__, current->pid); | |
+ | |
spin_lock_irqsave(&dsi_mdp_lock, flags); | |
- status = MIPI_INP(MIPI_DSI_BASE + 0x0004);/* DSI_STATUS */ | |
- if (status & 0x04) { /* MDP BUSY */ | |
- INIT_COMPLETION(dsi_mdp_comp); | |
- need_wait = 1; | |
- pr_debug("%s: status=%x need_wait\n", __func__, (int)status); | |
- mipi_dsi_enable_irq(DSI_MDP_TERM); | |
- } | |
+ if (dsi_mdp_busy == TRUE) | |
+ need_wait++; | |
spin_unlock_irqrestore(&dsi_mdp_lock, flags); | |
- if (need_wait){ | |
+ if (need_wait) { | |
+ /* wait until DMA finishes the current job */ | |
+ pr_debug("%s: pending pid=%d\n", | |
+ __func__, current->pid); | |
+ | |
// wait_for_completion(&dsi_mdp_comp); | |
if (!wait_for_completion_timeout(&dsi_mdp_comp, msecs_to_jiffies(200))) { | |
pr_err("%s: dma timeout error\n", __func__); | |
} | |
+ pr_debug("%s: done pid=%d\n", | |
+ __func__, current->pid); | |
} | |
} | |
@@ -1613,10 +1618,11 @@ void mipi_dsi_cmdlist_commit(int from_mdp) | |
mutex_lock(&cmd_mutex); | |
req = mipi_dsi_cmdlist_get(); | |
- if (req == NULL) { | |
- mutex_unlock(&cmd_mutex); | |
- return; | |
- } | |
+/* make sure dsi_cmd_mdp is idle */ | |
+ mipi_dsi_cmd_mdp_busy(); | |
+ | |
+ if (req == NULL) | |
+ goto need_lock; | |
pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid); | |
@@ -1632,6 +1638,11 @@ void mipi_dsi_cmdlist_commit(int from_mdp) | |
mipi_dsi_cmdlist_tx(req); | |
mipi_dsi_clk_cfg(0); | |
+ need_lock: | |
+ | |
+ if (from_mdp) /* from pipe_commit */ | |
+ mipi_dsi_cmd_mdp_start(); | |
+ | |
mutex_unlock(&cmd_mutex); | |
} | |
@@ -1776,6 +1787,7 @@ irqreturn_t mipi_dsi_isr(int irq, void *ptr) | |
spin_lock(&dsi_mdp_lock); | |
complete(&dsi_dma_comp); | |
dsi_ctrl_lock = FALSE; | |
+ dsi_mdp_busy = FALSE; | |
mipi_dsi_disable_irq_nosync(DSI_CMD_TERM); | |
spin_unlock(&dsi_mdp_lock); | |
} | |
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c | |
index 5cd4200..3e47d92 100644 | |
--- a/drivers/video/msm/mipi_novatek.c | |
+++ b/drivers/video/msm/mipi_novatek.c | |
@@ -446,7 +446,7 @@ static void mipi_novatek_set_backlight(struct msm_fb_data_type *mfd) | |
cmdreq.cmds = &backlight_cmd; | |
cmdreq.cmds_cnt = 1; | |
- cmdreq.flags = 0; | |
+ cmdreq.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL; | |
cmdreq.rlen = 0; | |
cmdreq.cb = NULL; | |
diff --git a/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c b/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c | |
index 616622e..d2820a8 100644 | |
--- a/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c | |
+++ b/drivers/video/msm/mipi_novatek_cmd_qhd_pt.c | |
@@ -64,7 +64,7 @@ static int __init mipi_cmd_novatek_blue_qhd_pt_init(void) | |
pinfo.is_3d_panel = FB_TYPE_3D_PANEL; | |
pinfo.lcd.vsync_enable = TRUE; | |
pinfo.lcd.hw_vsync_mode = TRUE; | |
- pinfo.lcd.refx100 = 6000; /* adjust refx100 to prevent tearing */ | |
+ pinfo.lcd.refx100 = 6200; /* adjust refx100 to prevent tearing */ | |
pinfo.lcd.v_back_porch = 11; | |
pinfo.lcd.v_front_porch = 10; | |
pinfo.lcd.v_pulse_width = 5; | |
diff --git a/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c b/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c | |
index ef4d85a..1bf86a7 100644 | |
--- a/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c | |
+++ b/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c | |
@@ -126,6 +126,7 @@ static int __init mipi_cmd_renesas_fwvga_pt_init(void) | |
pinfo.mipi.dsi_phy_db = &dsi_cmd_mode_phy_db; | |
pinfo.mipi.tx_eot_append = 0x01; | |
pinfo.mipi.rx_eot_ignore = 0; | |
+ pinfo.mipi.dlane_swap = 0x01; | |
#else | |
#if defined(RENESAS_FWVGA_TWO_LANE) | |
pinfo.mipi.data_lane1 = TRUE; | |
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h | |
index fc2c285..b429baf 100755 | |
--- a/drivers/video/msm/msm_fb.h | |
+++ b/drivers/video/msm/msm_fb.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2008-2013, The Linux Foundation. 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 and | |
@@ -204,6 +204,11 @@ extern int msm_drm_debug; | |
__func__ , ##_arg); \ | |
} while (0) | |
+struct msm_fb_backup_type { | |
+ struct fb_info info; | |
+ struct mdp_display_commit disp_commit; | |
+}; | |
+ | |
struct dentry *msm_fb_get_debugfs_root(void); | |
void msm_fb_debugfs_file_create(struct dentry *root, const char *name, | |
u32 *var); | |
@@ -230,7 +235,6 @@ void msm_fb_config_backlight(struct msm_fb_data_type *mfd); | |
#endif | |
void fill_black_screen(void); | |
-void unfill_black_screen(void); | |
int msm_fb_check_frame_rate(struct msm_fb_data_type *mfd, | |
struct fb_info *info); | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c | |
index ac002e1..d5b195d 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h | |
index 359c06f..1fee124 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h | |
index 3a7e443..5c1ee21 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h | |
index 0e9ccdd..db8a777 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c | |
index d9e73fb..a2327d5 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_errors.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c | |
index 4948e8b..61ab0f4 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
@@ -10,7 +10,7 @@ | |
* GNU General Public License for more details. | |
* | |
*/ | |
-#include <linux/ion.h> | |
+#include <linux/msm_ion.h> | |
#include <mach/msm_memtypes.h> | |
#include "vcd_ddl.h" | |
#include "vcd_ddl_shared_mem.h" | |
@@ -278,7 +278,8 @@ u32 ddl_decoder_dpb_init(struct ddl_client_context *ddl) | |
memset(frame[i].vcd_frm.virtual + luma_size, | |
0x80808080, | |
frame[i].vcd_frm.alloc_len - luma_size); | |
- if (frame[i].vcd_frm.ion_flag == CACHED) { | |
+ if (frame[i].vcd_frm.ion_flag | |
+ == ION_FLAG_CACHED) { | |
msm_ion_do_cache_op( | |
ddl_context->video_ion_client, | |
frame[i].vcd_frm.buff_ion_handle, | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c | |
index 73938ee..f499f78 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c | |
index aa28276..267e924 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h | |
index 1128393..c63b6a9 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c | |
index 4baa463..0a17752 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c | |
index 6d8c4b9..839a9c1 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h | |
index fd77454..6cd7559 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c | |
index 32960f1..721561d 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
@@ -84,7 +84,7 @@ void *ddl_pmem_alloc(struct ddl_buf_addr *addr, size_t sz, u32 alignment) | |
ionflag = CACHED; | |
kernel_vaddr = (unsigned long *) ion_map_kernel( | |
ddl_context->video_ion_client, | |
- addr->alloc_handle, ionflag); | |
+ addr->alloc_handle); | |
if (IS_ERR_OR_NULL(kernel_vaddr)) { | |
DDL_MSG_ERROR("%s() :DDL ION map failed\n", | |
__func__); | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h | |
index 565fa93..bbde7ae 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c | |
index 333d1e0..98b052a 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.c b/drivers/video/msm/vidc/1080p/ddl/vidc.c | |
index 00f75a9..d399847 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.c | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.h b/drivers/video/msm/vidc/1080p/ddl/vidc.h | |
index 39d3e8f..7460ef3 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.h | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h | |
index d63a45b..a5a8e57 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc_hwio_reg.h b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio_reg.h | |
index 0de06bf..819cd6c 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vidc_hwio_reg.h | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc_hwio_reg.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.c b/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.c | |
index de294fd..6870525 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.c | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.h b/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.h | |
index c70b113..e8a93a1 100644 | |
--- a/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.h | |
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc_pix_cache.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c | |
index 9417d53..cd8460b 100644 | |
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c | |
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
@@ -69,7 +69,7 @@ static void *res_trk_pmem_map | |
if (res_trk_get_enable_ion() && addr->alloc_handle) { | |
kernel_vaddr = (unsigned long *) ion_map_kernel( | |
ddl_context->video_ion_client, | |
- addr->alloc_handle, UNCACHED); | |
+ addr->alloc_handle); | |
if (IS_ERR_OR_NULL(kernel_vaddr)) { | |
DDL_MSG_ERROR("%s():DDL ION client map failed\n", | |
__func__); | |
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h | |
index 639cfce..a980230 100644 | |
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h | |
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
@@ -14,7 +14,7 @@ | |
#define _VIDEO_720P_RESOURCE_TRACKER_H_ | |
#include <linux/regulator/consumer.h> | |
-#include <linux/ion.h> | |
+#include <linux/msm_ion.h> | |
#include "vcd_res_tracker_api.h" | |
#ifdef CONFIG_MSM_BUS_SCALING | |
#include <mach/msm_bus.h> | |
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h | |
index 26c20c5..2ae2512 100644 | |
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h | |
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c | |
index 9b27abd..a144e06 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h | |
index 7a79a40..e6d3527 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012 The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012 Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_api.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_api.h | |
index 3796e8f..53cc93e 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_api.h | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_api.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_core.h | |
index 78b05ec..9fdb668 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_core.h | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_core.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c | |
index 6e43a7c..91136f3 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_errors.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c | |
index 23948d4..965c3aa 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h | |
index ba8dbcb..a136de8 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_firmware.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c | |
index 4cbd984..6a69955 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_hal.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c | |
index b97fae6..15adf21 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_helper.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h | |
index 32a4047..7e201cf 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c | |
index 817a98e..fe71dc1 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_interrupt_handler.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c | |
index 5d87533..2a74da8 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.h | |
index 7c9ac95..ed43861 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.h | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_metadata.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c | |
index cdb6313..3aebdaf 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_properties.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c | |
index aa5e72d..e77d1c5 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
@@ -142,8 +142,7 @@ void ddl_pmem_alloc(struct ddl_buf_addr *buff_addr, size_t sz, u32 align) | |
buff_addr->physical_base_addr = (u32 *)phyaddr; | |
kernel_vaddr = (unsigned long *) ion_map_kernel( | |
ddl_context->video_ion_client, | |
- buff_addr->alloc_handle, | |
- UNCACHED); | |
+ buff_addr->alloc_handle); | |
if (IS_ERR_OR_NULL(kernel_vaddr)) { | |
ERR("\n%s(): DDL ION map failed\n", __func__); | |
goto unmap_ion_buffer; | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h | |
index 633292b..59bb620 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h | |
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vidc.c b/drivers/video/msm/vidc/720p/ddl/vidc.c | |
index da969ef..de6cbbb 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vidc.c | |
+++ b/drivers/video/msm/vidc/720p/ddl/vidc.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/ddl/vidc.h b/drivers/video/msm/vidc/720p/ddl/vidc.h | |
index a09034f..509482b 100644 | |
--- a/drivers/video/msm/vidc/720p/ddl/vidc.h | |
+++ b/drivers/video/msm/vidc/720p/ddl/vidc.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c | |
index 5b39818..900c450 100644 | |
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c | |
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
@@ -746,8 +746,10 @@ struct ion_client *res_trk_get_ion_client(void) | |
u32 res_trk_get_mem_type(void) | |
{ | |
- u32 mem_type = ION_HEAP(resource_context.memtype); | |
- return mem_type; | |
+ if (resource_context.vidc_platform_data->enable_ion) | |
+ return (u32) ION_HEAP(resource_context.memtype); | |
+ else | |
+ return resource_context.memtype; | |
} | |
void res_trk_set_mem_type(enum ddl_mem_area mem_type) | |
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h | |
index 5f18076..5f126fd 100644 | |
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h | |
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
@@ -13,7 +13,7 @@ | |
#ifndef _VIDEO_720P_RESOURCE_TRACKER_H_ | |
#define _VIDEO_720P_RESOURCE_TRACKER_H_ | |
#include <mach/board.h> | |
-#include <linux/ion.h> | |
+#include <linux/msm_ion.h> | |
#include "vcd_res_tracker_api.h" | |
#define VCD_RESTRK_MIN_PERF_LEVEL 37900 | |
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h | |
index 1b2b4fa..75fdb3e 100644 | |
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h | |
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c | |
index 3aa4d40..a80f899 100644 | |
--- a/drivers/video/msm/vidc/common/dec/vdec.c | |
+++ b/drivers/video/msm/vidc/common/dec/vdec.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
@@ -25,7 +25,7 @@ | |
#include <linux/uaccess.h> | |
#include <linux/wait.h> | |
#include <linux/workqueue.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <linux/clk.h> | |
#include <linux/timer.h> | |
#include <mach/msm_subsystem_map.h> | |
@@ -48,8 +48,6 @@ static struct vid_dec_dev *vid_dec_device_p; | |
static dev_t vid_dec_dev_num; | |
static struct class *vid_dec_class; | |
-static unsigned int vidc_mmu_subsystem[] = { | |
- MSM_SUBSYSTEM_VIDEO}; | |
static s32 vid_dec_get_empty_client_index(void) | |
{ | |
u32 i, found = false; | |
@@ -844,10 +842,8 @@ static u32 vid_dec_set_h264_mv_buffers(struct video_client_ctx *client_ctx, | |
{ | |
struct vcd_property_hdr vcd_property_hdr; | |
struct vcd_property_h264_mv_buffer *vcd_h264_mv_buffer = NULL; | |
- struct msm_mapped_buffer *mapped_buffer = NULL; | |
u32 vcd_status = VCD_ERR_FAIL; | |
- u32 len = 0, flags = 0; | |
- struct file *file; | |
+ u32 len = 0; | |
int rc = 0; | |
unsigned long ionflag = 0; | |
unsigned long buffer_size = 0; | |
@@ -868,28 +864,8 @@ static u32 vid_dec_set_h264_mv_buffers(struct video_client_ctx *client_ctx, | |
vcd_h264_mv_buffer->offset = mv_data->offset; | |
if (!vcd_get_ion_status()) { | |
- if (get_pmem_file(vcd_h264_mv_buffer->pmem_fd, | |
- (unsigned long *) (&(vcd_h264_mv_buffer-> | |
- physical_addr)), | |
- (unsigned long *) (&vcd_h264_mv_buffer-> | |
- kernel_virtual_addr), | |
- (unsigned long *) (&len), &file)) { | |
- ERR("%s(): get_pmem_file failed\n", __func__); | |
- return false; | |
- } | |
- put_pmem_file(file); | |
- flags = MSM_SUBSYSTEM_MAP_IOVA; | |
- mapped_buffer = msm_subsystem_map_buffer( | |
- (unsigned long)vcd_h264_mv_buffer->physical_addr, len, | |
- flags, vidc_mmu_subsystem, | |
- sizeof(vidc_mmu_subsystem)/ | |
- sizeof(unsigned int)); | |
- if (IS_ERR(mapped_buffer)) { | |
- pr_err("buffer map failed"); | |
- return false; | |
- } | |
- vcd_h264_mv_buffer->client_data = (void *) mapped_buffer; | |
- vcd_h264_mv_buffer->dev_addr = (u8 *)mapped_buffer->iova[0]; | |
+ pr_err("PMEM not available\n"); | |
+ return false; | |
} else { | |
client_ctx->h264_mv_ion_handle = ion_import_dma_buf( | |
client_ctx->user_ion_client, | |
@@ -908,8 +884,7 @@ static u32 vid_dec_set_h264_mv_buffers(struct video_client_ctx *client_ctx, | |
} | |
vcd_h264_mv_buffer->kernel_virtual_addr = (u8 *) ion_map_kernel( | |
client_ctx->user_ion_client, | |
- client_ctx->h264_mv_ion_handle, | |
- ionflag); | |
+ client_ctx->h264_mv_ion_handle); | |
if (!vcd_h264_mv_buffer->kernel_virtual_addr) { | |
ERR("%s(): get_ION_kernel virtual addr failed\n", | |
__func__); | |
@@ -1471,7 +1446,6 @@ static long vid_dec_ioctl(struct file *file, | |
u32 vcd_status; | |
unsigned long kernel_vaddr, phy_addr, len; | |
unsigned long ker_vaddr; | |
- struct file *pmem_file; | |
u32 result = true; | |
void __user *arg = (void __user *)u_arg; | |
int rc = 0; | |
@@ -1786,12 +1760,8 @@ static long vid_dec_ioctl(struct file *file, | |
} | |
if (!vcd_get_ion_status()) { | |
- if (get_pmem_file(seq_header.pmem_fd, | |
- &phy_addr, &kernel_vaddr, &len, &pmem_file)) { | |
- ERR("%s(): get_pmem_file failed\n", __func__); | |
- return false; | |
- } | |
- put_pmem_file(pmem_file); | |
+ pr_err("PMEM Not available\n"); | |
+ return -EINVAL; | |
} else { | |
client_ctx->seq_hdr_ion_handle = ion_import_dma_buf( | |
client_ctx->user_ion_client, | |
@@ -1812,7 +1782,7 @@ static long vid_dec_ioctl(struct file *file, | |
} | |
ker_vaddr = (unsigned long) ion_map_kernel( | |
client_ctx->user_ion_client, | |
- client_ctx->seq_hdr_ion_handle, ionflag); | |
+ client_ctx->seq_hdr_ion_handle); | |
if (!ker_vaddr) { | |
ERR("%s():get_ION_kernel virtual addr fail\n", | |
__func__); | |
diff --git a/drivers/video/msm/vidc/common/dec/vdec_internal.h b/drivers/video/msm/vidc/common/dec/vdec_internal.h | |
index a7a32a5..89da9a2 100644 | |
--- a/drivers/video/msm/vidc/common/dec/vdec_internal.h | |
+++ b/drivers/video/msm/vidc/common/dec/vdec_internal.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, 2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, 2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c | |
index 29b74d1..7ba88e8 100644 | |
--- a/drivers/video/msm/vidc/common/enc/venc.c | |
+++ b/drivers/video/msm/vidc/common/enc/venc.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
@@ -25,7 +25,7 @@ | |
#include <linux/uaccess.h> | |
#include <linux/wait.h> | |
#include <linux/workqueue.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <linux/clk.h> | |
#include <media/msm/vidc_type.h> | |
#include <media/msm/vcd_api.h> | |
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c | |
index ff82d4b..1f40d5c 100644 | |
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c | |
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2013, The Linux Foundation. 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 and | |
@@ -25,7 +25,7 @@ | |
#include <linux/uaccess.h> | |
#include <linux/wait.h> | |
#include <linux/workqueue.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <linux/clk.h> | |
#include <mach/msm_subsystem_map.h> | |
#include <media/msm/vidc_type.h> | |
@@ -41,9 +41,6 @@ | |
#endif | |
#define ERR(x...) printk(KERN_ERR x) | |
-static unsigned int vidc_mmu_subsystem[] = { | |
- MSM_SUBSYSTEM_VIDEO}; | |
- | |
u32 vid_enc_set_get_base_cfg(struct video_client_ctx *client_ctx, | |
struct venc_basecfg *base_config, u32 set_flag) | |
@@ -1577,7 +1574,12 @@ u32 vid_enc_set_buffer(struct video_client_ctx *client_ctx, | |
enum vcd_buffer_type vcd_buffer_t = VCD_BUFFER_INPUT; | |
enum buffer_dir dir_buffer = BUFFER_TYPE_INPUT; | |
u32 vcd_status = VCD_ERR_FAIL; | |
- unsigned long kernel_vaddr, length = 0; | |
+ unsigned long kernel_vaddr, length, user_vaddr, phy_addr = 0; | |
+ int pmem_fd = 0; | |
+ struct ion_handle *buff_handle = NULL; | |
+ u32 ion_flag = 0; | |
+ struct file *file = NULL; | |
+ s32 buffer_index = 0; | |
if (!client_ctx || !buffer_info) | |
return false; | |
@@ -1599,6 +1601,38 @@ u32 vid_enc_set_buffer(struct video_client_ctx *client_ctx, | |
return false; | |
} | |
+ /* | |
+ * Flush output buffers explcitly once, during registration. This ensures | |
+ * any pending CPU writes (if cleared after allocation) are | |
+ * committed right away, or else this may get flushed _after_ | |
+ * the hardware has written bitstream. rare bug, but can happen ! | |
+ */ | |
+ if (buffer == VEN_BUFFER_TYPE_OUTPUT) { | |
+ user_vaddr = (unsigned long)buffer_info->pbuffer; | |
+ if (!vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT, | |
+ true, &user_vaddr, &kernel_vaddr, | |
+ &phy_addr, &pmem_fd, &file, | |
+ &buffer_index)) { | |
+ ERR("%s(): vidc_lookup_addr_table failed\n", | |
+ __func__); | |
+ return false; | |
+ } | |
+ | |
+ ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT, | |
+ buffer_info->fd, kernel_vaddr, buffer_index, | |
+ &buff_handle); | |
+ | |
+ if (ion_flag == ION_FLAG_CACHED && buff_handle) { | |
+ msm_ion_do_cache_op( | |
+ client_ctx->user_ion_client, | |
+ buff_handle, | |
+ NULL, | |
+ (unsigned long) length, | |
+ ION_IOC_INV_CACHES); | |
+ } | |
+ } | |
+ | |
+ | |
vcd_status = vcd_set_buffer(client_ctx->vcd_handle, | |
vcd_buffer_t, (u8 *) kernel_vaddr, | |
buffer_info->sz); | |
@@ -1765,11 +1799,9 @@ u32 vid_enc_set_recon_buffers(struct video_client_ctx *client_ctx, | |
struct venc_recon_addr *venc_recon) | |
{ | |
u32 vcd_status = VCD_ERR_FAIL; | |
- u32 len, i, flags = 0; | |
- struct file *file; | |
+ u32 len, i; | |
struct vcd_property_hdr vcd_property_hdr; | |
struct vcd_property_enc_recon_buffer *control = NULL; | |
- struct msm_mapped_buffer *mapped_buffer = NULL; | |
int rc = -1; | |
unsigned long ionflag = 0; | |
unsigned long iova = 0; | |
@@ -1801,25 +1833,8 @@ u32 vid_enc_set_recon_buffers(struct video_client_ctx *client_ctx, | |
control->user_virtual_addr = venc_recon->pbuffer; | |
if (!vcd_get_ion_status()) { | |
- if (get_pmem_file(control->pmem_fd, (unsigned long *) | |
- (&(control->physical_addr)), (unsigned long *) | |
- (&control->kernel_virtual_addr), | |
- (unsigned long *) (&len), &file)) { | |
- ERR("%s(): get_pmem_file failed\n", __func__); | |
- return false; | |
- } | |
- put_pmem_file(file); | |
- flags = MSM_SUBSYSTEM_MAP_IOVA; | |
- mapped_buffer = msm_subsystem_map_buffer( | |
- (unsigned long)control->physical_addr, len, | |
- flags, vidc_mmu_subsystem, | |
- sizeof(vidc_mmu_subsystem)/sizeof(unsigned int)); | |
- if (IS_ERR(mapped_buffer)) { | |
- pr_err("buffer map failed"); | |
- return false; | |
- } | |
- control->client_data = (void *) mapped_buffer; | |
- control->dev_addr = (u8 *)mapped_buffer->iova[0]; | |
+ pr_err("PMEM not available\n"); | |
+ return false; | |
} else { | |
client_ctx->recon_buffer_ion_handle[i] = ion_import_dma_buf( | |
client_ctx->user_ion_client, control->pmem_fd); | |
@@ -1837,8 +1852,7 @@ u32 vid_enc_set_recon_buffers(struct video_client_ctx *client_ctx, | |
} | |
control->kernel_virtual_addr = (u8 *) ion_map_kernel( | |
client_ctx->user_ion_client, | |
- client_ctx->recon_buffer_ion_handle[i], | |
- ionflag); | |
+ client_ctx->recon_buffer_ion_handle[i]); | |
if (!control->kernel_virtual_addr) { | |
ERR("%s(): get_ION_kernel virtual addr fail\n", | |
__func__); | |
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.h b/drivers/video/msm/vidc/common/enc/venc_internal.h | |
index 324ed9e..8a07fdb 100644 | |
--- a/drivers/video/msm/vidc/common/enc/venc_internal.h | |
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c | |
index 870b892..746c783 100644 | |
--- a/drivers/video/msm/vidc/common/init/vidc_init.c | |
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2013, The Linux Foundation. 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 and | |
@@ -24,7 +24,7 @@ | |
#include <linux/uaccess.h> | |
#include <linux/wait.h> | |
#include <linux/workqueue.h> | |
-#include <linux/android_pmem.h> | |
+ | |
#include <linux/clk.h> | |
#include <linux/delay.h> | |
#include <linux/debugfs.h> | |
@@ -49,7 +49,6 @@ | |
static struct vidc_dev *vidc_device_p; | |
static dev_t vidc_dev_num; | |
static struct class *vidc_class; | |
-static unsigned int vidc_mmu_subsystem[] = {MSM_SUBSYSTEM_VIDEO}; | |
static const struct file_operations vidc_fops = { | |
.owner = THIS_MODULE, | |
@@ -565,9 +564,8 @@ u32 vidc_insert_addr_table(struct video_client_ctx *client_ctx, | |
unsigned long len, phys_addr; | |
struct file *file = NULL; | |
u32 *num_of_buffers = NULL; | |
- u32 i, flags; | |
+ u32 i; | |
struct buf_addr_table *buf_addr_table; | |
- struct msm_mapped_buffer *mapped_buffer = NULL; | |
struct ion_handle *buff_ion_handle = NULL; | |
unsigned long ionflag = 0; | |
unsigned long iova = 0; | |
@@ -609,26 +607,8 @@ u32 vidc_insert_addr_table(struct video_client_ctx *client_ctx, | |
goto bail_out_add; | |
} else { | |
if (!vcd_get_ion_status()) { | |
- if (get_pmem_file(pmem_fd, &phys_addr, | |
- kernel_vaddr, &len, &file)) { | |
- ERR("%s(): get_pmem_file failed\n", __func__); | |
- goto bail_out_add; | |
- } | |
- put_pmem_file(file); | |
- flags = (buffer == BUFFER_TYPE_INPUT) | |
- ? MSM_SUBSYSTEM_MAP_IOVA : | |
- MSM_SUBSYSTEM_MAP_IOVA|MSM_SUBSYSTEM_ALIGN_IOVA_8K; | |
- mapped_buffer = msm_subsystem_map_buffer(phys_addr, | |
- length, flags, vidc_mmu_subsystem, | |
- sizeof(vidc_mmu_subsystem)/sizeof(unsigned int)); | |
- if (IS_ERR(mapped_buffer)) { | |
- pr_err("buffer map failed"); | |
- goto bail_out_add; | |
- } | |
- buf_addr_table[*num_of_buffers].client_data = (void *) | |
- mapped_buffer; | |
- buf_addr_table[*num_of_buffers].dev_addr = | |
- mapped_buffer->iova[0]; | |
+ pr_err("PMEM not available\n"); | |
+ return false; | |
} else { | |
buff_ion_handle = ion_import_dma_buf( | |
client_ctx->user_ion_client, pmem_fd); | |
@@ -647,8 +627,7 @@ u32 vidc_insert_addr_table(struct video_client_ctx *client_ctx, | |
*kernel_vaddr = (unsigned long) | |
ion_map_kernel( | |
client_ctx->user_ion_client, | |
- buff_ion_handle, | |
- ionflag); | |
+ buff_ion_handle); | |
if (IS_ERR_OR_NULL((void *)*kernel_vaddr)) { | |
ERR("%s():ION virtual addr fail\n", | |
__func__); | |
@@ -913,7 +892,8 @@ void vidc_timer_start(void *timer_handle, u32 time_out) | |
struct vidc_timer *hw_timer = (struct vidc_timer *)timer_handle; | |
DBG("%s(): start timer\n ", __func__); | |
if (hw_timer) { | |
- hw_timer->hw_timeout.expires = jiffies + 1*HZ; | |
+ //hw_timer->hw_timeout.expires = jiffies + 1*HZ; | |
+ hw_timer->hw_timeout.expires = jiffies + 10*HZ; | |
add_timer(&hw_timer->hw_timeout); | |
} | |
} | |
diff --git a/drivers/video/msm/vidc/common/init/vidc_init_internal.h b/drivers/video/msm/vidc/common/init/vidc_init_internal.h | |
index b62280f..1d903ad 100644 | |
--- a/drivers/video/msm/vidc/common/init/vidc_init_internal.h | |
+++ b/drivers/video/msm/vidc/common/init/vidc_init_internal.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/vcd/vcd.h b/drivers/video/msm/vidc/common/vcd/vcd.h | |
index 122db76..8f44a56 100644 | |
--- a/drivers/video/msm/vidc/common/vcd/vcd.h | |
+++ b/drivers/video/msm/vidc/common/vcd/vcd.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_api.c b/drivers/video/msm/vidc/common/vcd/vcd_api.c | |
index facde34..c66c2b7 100644 | |
--- a/drivers/video/msm/vidc/common/vcd/vcd_api.c | |
+++ b/drivers/video/msm/vidc/common/vcd/vcd_api.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c | |
index b96d496..7c0d9fe 100644 | |
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c | |
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h | |
index ba1884d..9f2d63d 100644 | |
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h | |
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h | |
index 2dd69d8..ff47cd5 100644 | |
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h | |
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
@@ -13,7 +13,7 @@ | |
#ifndef _VCD_CORE_H_ | |
#define _VCD_CORE_H_ | |
-#include <linux/ion.h> | |
+#include <linux/msm_ion.h> | |
#include <media/msm/vcd_api.h> | |
#include "vcd_ddl_api.h" | |
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c | |
index b44cf0c..96e729d 100644 | |
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c | |
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h | |
index 898f284..2443c33 100644 | |
--- a/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h | |
+++ b/drivers/video/msm/vidc/common/vcd/vcd_device_sm.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c | |
index 4b70eed..44d270a 100644 | |
--- a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c | |
+++ b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.h b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.h | |
index aecbc8d..26ce019 100644 | |
--- a/drivers/video/msm/vidc/common/vcd/vcd_power_sm.h | |
+++ b/drivers/video/msm/vidc/common/vcd/vcd_power_sm.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c | |
index e392414..ab21bac 100644 | |
--- a/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c | |
+++ b/drivers/video/msm/vidc/common/vcd/vcd_scheduler.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c | |
index 0eb2e0e..43a32fd 100644 | |
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c | |
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
@@ -105,8 +105,7 @@ static int vcd_pmem_alloc(size_t sz, u8 **kernel_vaddr, u8 **phy_addr, | |
} | |
*kernel_vaddr = (u8 *) ion_map_kernel( | |
cctxt->vcd_ion_client, | |
- map_buffer->alloc_handle, | |
- ionflag); | |
+ map_buffer->alloc_handle); | |
if (!(*kernel_vaddr)) { | |
pr_err("%s() ION map failed", __func__); | |
goto ion_free_bailout; | |
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_util.c b/drivers/video/msm/vidc/common/vcd/vcd_util.c | |
index 98bc7f5..ba991f1 100644 | |
--- a/drivers/video/msm/vidc/common/vcd/vcd_util.c | |
+++ b/drivers/video/msm/vidc/common/vcd/vcd_util.c | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010, Code Aurora Forum. 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 and | |
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_util.h b/drivers/video/msm/vidc/common/vcd/vcd_util.h | |
index 7571b25..7164029 100644 | |
--- a/drivers/video/msm/vidc/common/vcd/vcd_util.h | |
+++ b/drivers/video/msm/vidc/common/vcd/vcd_util.h | |
@@ -1,4 +1,4 @@ | |
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. | |
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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 and | |
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h | |
index 8aeadf6..6af2a3e 100644 | |
--- a/include/asm-generic/vmlinux.lds.h | |
+++ b/include/asm-generic/vmlinux.lds.h | |
@@ -645,6 +645,11 @@ | |
*(.security_initcall.init) \ | |
VMLINUX_SYMBOL(__security_initcall_end) = .; | |
+#define COMPAT_EXPORTS \ | |
+ VMLINUX_SYMBOL(__compat_exports_start) = .; \ | |
+ *(.exportcompat.init) \ | |
+ VMLINUX_SYMBOL(__compat_exports_end) = .; | |
+ | |
#ifdef CONFIG_BLK_DEV_INITRD | |
#define INIT_RAM_FS \ | |
. = ALIGN(4); \ | |
diff --git a/include/linux/android_pmem.h b/include/linux/android_pmem.h | |
index cfca491..689d373 100644 | |
--- a/include/linux/android_pmem.h | |
+++ b/include/linux/android_pmem.h | |
@@ -163,6 +163,7 @@ int pmem_setup(struct android_pmem_platform_data *pdata, | |
int pmem_remap(struct pmem_region *region, struct file *file, | |
unsigned operation); | |
+ | |
#endif /* __KERNEL__ */ | |
#endif //_ANDROID_PPP_H_ | |
diff --git a/include/linux/genlock.h b/include/linux/genlock.h | |
index 587c49d..e233662 100644 | |
--- a/include/linux/genlock.h | |
+++ b/include/linux/genlock.h | |
@@ -8,6 +8,7 @@ struct genlock_handle; | |
struct genlock_handle *genlock_get_handle(void); | |
struct genlock_handle *genlock_get_handle_fd(int fd); | |
+int genlock_get_fd_handle(struct genlock_handle *handle); | |
void genlock_put_handle(struct genlock_handle *handle); | |
struct genlock *genlock_create_lock(struct genlock_handle *); | |
struct genlock *genlock_attach_lock(struct genlock_handle *, int fd); | |
diff --git a/include/linux/msm_audio.h b/include/linux/msm_audio.h | |
index 322a374..9173d54 100644 | |
--- a/include/linux/msm_audio.h | |
+++ b/include/linux/msm_audio.h | |
@@ -1,7 +1,7 @@ | |
/* include/linux/msm_audio.h | |
* | |
* Copyright (C) 2008 Google, Inc. | |
- * Copyright (c) 2012 The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2012 Code Aurora Forum. All rights reserved. | |
* | |
* This software is licensed under the terms of the GNU General Public | |
* License version 2, as published by the Free Software Foundation, and | |
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h | |
index 1449b68..938c80c 100644 | |
--- a/include/linux/msm_mdp.h | |
+++ b/include/linux/msm_mdp.h | |
@@ -1,7 +1,7 @@ | |
/* include/linux/msm_mdp.h | |
* | |
* Copyright (C) 2007 Google Incorporated | |
- * Copyright (c) 2012 The Linux Foundation. All rights reserved. | |
+ * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. | |
* | |
* This software is licensed under the terms of the GNU General Public | |
* License version 2, as published by the Free Software Foundation, and | |
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild | |
index 1697036..b66bc03 100644 | |
--- a/include/linux/netfilter/Kbuild | |
+++ b/include/linux/netfilter/Kbuild | |
@@ -17,20 +17,20 @@ header-y += x_tables.h | |
header-y += xt_AUDIT.h | |
header-y += xt_CHECKSUM.h | |
header-y += xt_CLASSIFY.h | |
-header-y += xt_CONNMARK.h | |
+header-y += xt_CONNMARK_new.h | |
header-y += xt_CONNSECMARK.h | |
header-y += xt_CT.h | |
-header-y += xt_DSCP.h | |
+header-y += xt_DSCP_new.h | |
header-y += xt_IDLETIMER.h | |
header-y += xt_LED.h | |
header-y += xt_LOG.h | |
-header-y += xt_MARK.h | |
+header-y += xt_MARK_new.h | |
header-y += xt_nfacct.h | |
header-y += xt_NFLOG.h | |
header-y += xt_NFQUEUE.h | |
-header-y += xt_RATEEST.h | |
+header-y += xt_RATEEST_new.h | |
header-y += xt_SECMARK.h | |
-header-y += xt_TCPMSS.h | |
+header-y += xt_TCPMSS_new.h | |
header-y += xt_TCPOPTSTRIP.h | |
header-y += xt_TEE.h | |
header-y += xt_TPROXY.h | |
diff --git a/include/linux/netfilter/xt_CONNMARK_new.h b/include/linux/netfilter/xt_CONNMARK_new.h | |
new file mode 100644 | |
index 0000000..2f2e48e | |
--- /dev/null | |
+++ b/include/linux/netfilter/xt_CONNMARK_new.h | |
@@ -0,0 +1,6 @@ | |
+#ifndef _XT_CONNMARK_H_target | |
+#define _XT_CONNMARK_H_target | |
+ | |
+#include <linux/netfilter/xt_connmark.h> | |
+ | |
+#endif /*_XT_CONNMARK_H_target*/ | |
diff --git a/include/linux/netfilter/xt_DSCP_new.h b/include/linux/netfilter/xt_DSCP_new.h | |
new file mode 100644 | |
index 0000000..648e0b3 | |
--- /dev/null | |
+++ b/include/linux/netfilter/xt_DSCP_new.h | |
@@ -0,0 +1,26 @@ | |
+/* x_tables module for setting the IPv4/IPv6 DSCP field | |
+ * | |
+ * (C) 2002 Harald Welte <laforge@gnumonks.org> | |
+ * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.com> | |
+ * This software is distributed under GNU GPL v2, 1991 | |
+ * | |
+ * See RFC2474 for a description of the DSCP field within the IP Header. | |
+ * | |
+ * xt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp | |
+*/ | |
+#ifndef _XT_DSCP_TARGET_H | |
+#define _XT_DSCP_TARGET_H | |
+#include <linux/netfilter/xt_dscp.h> | |
+#include <linux/types.h> | |
+ | |
+/* target info */ | |
+struct xt_DSCP_info { | |
+ __u8 dscp; | |
+}; | |
+ | |
+struct xt_tos_target_info { | |
+ __u8 tos_value; | |
+ __u8 tos_mask; | |
+}; | |
+ | |
+#endif /* _XT_DSCP_TARGET_H */ | |
diff --git a/include/linux/netfilter/xt_MARK_new.h b/include/linux/netfilter/xt_MARK_new.h | |
new file mode 100644 | |
index 0000000..41c456d | |
--- /dev/null | |
+++ b/include/linux/netfilter/xt_MARK_new.h | |
@@ -0,0 +1,6 @@ | |
+#ifndef _XT_MARK_H_target | |
+#define _XT_MARK_H_target | |
+ | |
+#include <linux/netfilter/xt_mark.h> | |
+ | |
+#endif /*_XT_MARK_H_target */ | |
diff --git a/include/linux/netfilter/xt_RATEEST_new.h b/include/linux/netfilter/xt_RATEEST_new.h | |
new file mode 100644 | |
index 0000000..6605e20 | |
--- /dev/null | |
+++ b/include/linux/netfilter/xt_RATEEST_new.h | |
@@ -0,0 +1,15 @@ | |
+#ifndef _XT_RATEEST_TARGET_H | |
+#define _XT_RATEEST_TARGET_H | |
+ | |
+#include <linux/types.h> | |
+ | |
+struct xt_rateest_target_info { | |
+ char name[IFNAMSIZ]; | |
+ __s8 interval; | |
+ __u8 ewma_log; | |
+ | |
+ /* Used internally by the kernel */ | |
+ struct xt_rateest *est __attribute__((aligned(8))); | |
+}; | |
+ | |
+#endif /* _XT_RATEEST_TARGET_H */ | |
diff --git a/include/linux/netfilter/xt_TCPMSS_new.h b/include/linux/netfilter/xt_TCPMSS_new.h | |
new file mode 100644 | |
index 0000000..9a6960a | |
--- /dev/null | |
+++ b/include/linux/netfilter/xt_TCPMSS_new.h | |
@@ -0,0 +1,12 @@ | |
+#ifndef _XT_TCPMSS_H | |
+#define _XT_TCPMSS_H | |
+ | |
+#include <linux/types.h> | |
+ | |
+struct xt_tcpmss_info { | |
+ __u16 mss; | |
+}; | |
+ | |
+#define XT_TCPMSS_CLAMP_PMTU 0xffff | |
+ | |
+#endif /* _XT_TCPMSS_H */ | |
diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild | |
index 31f8bec..6ed2cad 100644 | |
--- a/include/linux/netfilter_ipv4/Kbuild | |
+++ b/include/linux/netfilter_ipv4/Kbuild | |
@@ -1,10 +1,10 @@ | |
header-y += ip_queue.h | |
header-y += ip_tables.h | |
header-y += ipt_CLUSTERIP.h | |
-header-y += ipt_ECN.h | |
+header-y += ipt_ECN_new.h | |
header-y += ipt_LOG.h | |
header-y += ipt_REJECT.h | |
-header-y += ipt_TTL.h | |
+header-y += ipt_TTL_new.h | |
header-y += ipt_ULOG.h | |
header-y += ipt_addrtype.h | |
header-y += ipt_ah.h | |
diff --git a/include/linux/netfilter_ipv4/ipt_ECN_new.h b/include/linux/netfilter_ipv4/ipt_ECN_new.h | |
new file mode 100644 | |
index 0000000..3086fed | |
--- /dev/null | |
+++ b/include/linux/netfilter_ipv4/ipt_ECN_new.h | |
@@ -0,0 +1,33 @@ | |
+/* Header file for iptables ipt_ECN target | |
+ * | |
+ * (C) 2002 by Harald Welte <laforge@gnumonks.org> | |
+ * | |
+ * This software is distributed under GNU GPL v2, 1991 | |
+ * | |
+ * ipt_ECN.h,v 1.3 2002/05/29 12:17:40 laforge Exp | |
+*/ | |
+#ifndef _IPT_ECN_TARGET_H | |
+#define _IPT_ECN_TARGET_H | |
+ | |
+#include <linux/types.h> | |
+#include <linux/netfilter/xt_DSCP_new.h> | |
+ | |
+#define IPT_ECN_IP_MASK (~XT_DSCP_MASK) | |
+ | |
+#define IPT_ECN_OP_SET_IP 0x01 /* set ECN bits of IPv4 header */ | |
+#define IPT_ECN_OP_SET_ECE 0x10 /* set ECE bit of TCP header */ | |
+#define IPT_ECN_OP_SET_CWR 0x20 /* set CWR bit of TCP header */ | |
+ | |
+#define IPT_ECN_OP_MASK 0xce | |
+ | |
+struct ipt_ECN_info { | |
+ __u8 operation; /* bitset of operations */ | |
+ __u8 ip_ect; /* ECT codepoint of IPv4 header, pre-shifted */ | |
+ union { | |
+ struct { | |
+ __u8 ece:1, cwr:1; /* TCP ECT bits */ | |
+ } tcp; | |
+ } proto; | |
+}; | |
+ | |
+#endif /* _IPT_ECN_TARGET_H */ | |
diff --git a/include/linux/netfilter_ipv4/ipt_TTL_new.h b/include/linux/netfilter_ipv4/ipt_TTL_new.h | |
new file mode 100644 | |
index 0000000..f6ac169 | |
--- /dev/null | |
+++ b/include/linux/netfilter_ipv4/ipt_TTL_new.h | |
@@ -0,0 +1,23 @@ | |
+/* TTL modification module for IP tables | |
+ * (C) 2000 by Harald Welte <laforge@netfilter.org> */ | |
+ | |
+#ifndef _IPT_TTL_H | |
+#define _IPT_TTL_H | |
+ | |
+#include <linux/types.h> | |
+ | |
+enum { | |
+ IPT_TTL_SET = 0, | |
+ IPT_TTL_INC, | |
+ IPT_TTL_DEC | |
+}; | |
+ | |
+#define IPT_TTL_MAXMODE IPT_TTL_DEC | |
+ | |
+struct ipt_TTL_info { | |
+ __u8 mode; | |
+ __u8 ttl; | |
+}; | |
+ | |
+ | |
+#endif | |
diff --git a/include/linux/netfilter_ipv6/Kbuild b/include/linux/netfilter_ipv6/Kbuild | |
index bd095bc..44b2973 100644 | |
--- a/include/linux/netfilter_ipv6/Kbuild | |
+++ b/include/linux/netfilter_ipv6/Kbuild | |
@@ -1,5 +1,5 @@ | |
header-y += ip6_tables.h | |
-header-y += ip6t_HL.h | |
+header-y += ip6t_HL_new.h | |
header-y += ip6t_LOG.h | |
header-y += ip6t_REJECT.h | |
header-y += ip6t_ah.h | |
diff --git a/include/linux/netfilter_ipv6/ip6t_HL_new.h b/include/linux/netfilter_ipv6/ip6t_HL_new.h | |
new file mode 100644 | |
index 0000000..ebd8ead | |
--- /dev/null | |
+++ b/include/linux/netfilter_ipv6/ip6t_HL_new.h | |
@@ -0,0 +1,24 @@ | |
+/* Hop Limit modification module for ip6tables | |
+ * Maciej Soltysiak <solt@dns.toxicfilms.tv> | |
+ * Based on HW's TTL module */ | |
+ | |
+#ifndef _IP6T_HL_H | |
+#define _IP6T_HL_H | |
+ | |
+#include <linux/types.h> | |
+ | |
+enum { | |
+ IP6T_HL_SET = 0, | |
+ IP6T_HL_INC, | |
+ IP6T_HL_DEC | |
+}; | |
+ | |
+#define IP6T_HL_MAXMODE IP6T_HL_DEC | |
+ | |
+struct ip6t_HL_info { | |
+ __u8 mode; | |
+ __u8 hop_limit; | |
+}; | |
+ | |
+ | |
+#endif | |
diff --git a/include/linux/sched.h b/include/linux/sched.h | |
index 66f12c7..49985f6 100755 | |
--- a/include/linux/sched.h | |
+++ b/include/linux/sched.h | |
@@ -122,7 +122,7 @@ extern void get_avenrun(unsigned long *loads, unsigned long offset, int shift); | |
#define FSHIFT 11 /* nr of bits of precision */ | |
#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */ | |
-#define LOAD_FREQ (5*HZ+1) /* 5 sec intervals */ | |
+#define LOAD_FREQ (4*HZ+61) /* 5 sec intervals */ | |
#define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */ | |
#define EXP_5 2014 /* 1/exp(5sec/5min) */ | |
#define EXP_15 2037 /* 1/exp(5sec/15min) */ | |
@@ -2844,7 +2844,7 @@ static inline unsigned long rlimit_max(unsigned int limit) | |
{ | |
return task_rlimit_max(current, limit); | |
} | |
- | |
+ | |
#endif /* __KERNEL__ */ | |
#endif | |
diff --git a/include/linux/security.h b/include/linux/security.h | |
index b62f396..2a82530 100644 | |
--- a/include/linux/security.h | |
+++ b/include/linux/security.h | |
@@ -144,6 +144,7 @@ struct request_sock; | |
#define LSM_UNSAFE_SHARE 1 | |
#define LSM_UNSAFE_PTRACE 2 | |
#define LSM_UNSAFE_PTRACE_CAP 4 | |
+#define LSM_UNSAFE_NO_NEW_PRIVS 8 | |
#ifdef CONFIG_MMU | |
extern int mmap_min_addr_handler(struct ctl_table *table, int write, | |
diff --git a/include/linux/writeback.h b/include/linux/writeback.h | |
index 57b3695..ad78b3d 100644 | |
--- a/include/linux/writeback.h | |
+++ b/include/linux/writeback.h | |
@@ -137,6 +137,12 @@ extern int vm_highmem_is_dirtyable; | |
extern int block_dump; | |
extern int laptop_mode; | |
+#ifdef CONFIG_DYNAMIC_PAGE_WRITEBACK | |
+extern int dyn_dirty_writeback_enabled; | |
+extern unsigned int dirty_writeback_active_interval; | |
+extern unsigned int dirty_writeback_suspend_interval; | |
+#endif | |
+ | |
extern int dirty_background_ratio_handler(struct ctl_table *table, int write, | |
void __user *buffer, size_t *lenp, | |
loff_t *ppos); | |
@@ -154,6 +160,15 @@ struct ctl_table; | |
int dirty_writeback_centisecs_handler(struct ctl_table *, int, | |
void __user *, size_t *, loff_t *); | |
+#ifdef CONFIG_DYNAMIC_PAGE_WRITEBACK | |
+int dynamic_dirty_writeback_handler(struct ctl_table *, int, | |
+ void __user *, size_t *, loff_t *); | |
+int dirty_writeback_active_centisecs_handler(struct ctl_table *, int, | |
+ void __user *, size_t *, loff_t *); | |
+int dirty_writeback_suspend_centisecs_handler(struct ctl_table *, int, | |
+ void __user *, size_t *, loff_t *); | |
+#endif | |
+ | |
void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty); | |
unsigned long bdi_dirty_limit(struct backing_dev_info *bdi, | |
unsigned long dirty); | |
diff --git a/kernel/sched/core.c b/kernel/sched/core.c | |
index 6500008..b6b25e3 100644 | |
--- a/kernel/sched/core.c | |
+++ b/kernel/sched/core.c | |
@@ -5632,6 +5632,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) | |
case CPU_UP_PREPARE: | |
rq->calc_load_update = calc_load_update; | |
+ rq->next_balance = jiffies; | |
break; | |
case CPU_ONLINE: | |
@@ -7148,8 +7149,6 @@ void __init sched_init_smp(void) | |
hotcpu_notifier(cpuset_cpu_active, CPU_PRI_CPUSET_ACTIVE); | |
hotcpu_notifier(cpuset_cpu_inactive, CPU_PRI_CPUSET_INACTIVE); | |
- /* RT runtime code needs to handle some hotplug events */ | |
- hotcpu_notifier(update_runtime, 0); | |
init_hrtick(); | |
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c | |
index a7b5014..808f6aa 100644 | |
--- a/kernel/sched/fair.c | |
+++ b/kernel/sched/fair.c | |
@@ -43,8 +43,8 @@ | |
* (to see the precise effective timeslice length of your workload, | |
* run vmstat and monitor the context-switches (cs) field) | |
*/ | |
-unsigned int sysctl_sched_latency = 6000000ULL; | |
-unsigned int normalized_sysctl_sched_latency = 6000000ULL; | |
+unsigned int sysctl_sched_latency = 20000000ULL; | |
+unsigned int normalized_sysctl_sched_latency = 20000000ULL; | |
/* | |
* The initial- and re-scaling of tunables is configurable | |
@@ -62,8 +62,8 @@ enum sched_tunable_scaling sysctl_sched_tunable_scaling | |
* Minimal preemption granularity for CPU-bound tasks: | |
* (default: 0.75 msec * (1 + ilog(ncpus)), units: nanoseconds) | |
*/ | |
-unsigned int sysctl_sched_min_granularity = 750000ULL; | |
-unsigned int normalized_sysctl_sched_min_granularity = 750000ULL; | |
+unsigned int sysctl_sched_min_granularity = 4000000ULL; | |
+unsigned int normalized_sysctl_sched_min_granularity = 4000000ULL; | |
/* | |
* is kept at sysctl_sched_latency / sysctl_sched_min_granularity | |
@@ -84,8 +84,8 @@ unsigned int sysctl_sched_child_runs_first __read_mostly; | |
* and reduces their over-scheduling. Synchronous workloads will still | |
* have immediate wakeup/sleep latencies. | |
*/ | |
-unsigned int sysctl_sched_wakeup_granularity = 1000000UL; | |
-unsigned int normalized_sysctl_sched_wakeup_granularity = 1000000UL; | |
+unsigned int sysctl_sched_wakeup_granularity = 5000000UL; | |
+unsigned int normalized_sysctl_sched_wakeup_granularity = 5000000UL; | |
const_debug unsigned int sysctl_sched_migration_cost = 500000UL; | |
diff --git a/kernel/sched/features.h b/kernel/sched/features.h | |
index f83fdc3..2174483 100644 | |
--- a/kernel/sched/features.h | |
+++ b/kernel/sched/features.h | |
@@ -67,5 +67,5 @@ SCHED_FEAT(NONTASK_POWER, true) | |
SCHED_FEAT(TTWU_QUEUE, true) | |
SCHED_FEAT(FORCE_SD_OVERLAP, false) | |
-SCHED_FEAT(RT_RUNTIME_SHARE, true) | |
+SCHED_FEAT(RT_RUNTIME_SHARE, false) | |
SCHED_FEAT(LB_MIN, false) | |
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c | |
index 526c77d..62dac8c 100644 | |
--- a/kernel/sched/rt.c | |
+++ b/kernel/sched/rt.c | |
@@ -691,15 +691,6 @@ balanced: | |
} | |
} | |
-static void disable_runtime(struct rq *rq) | |
-{ | |
- unsigned long flags; | |
- | |
- raw_spin_lock_irqsave(&rq->lock, flags); | |
- __disable_runtime(rq); | |
- raw_spin_unlock_irqrestore(&rq->lock, flags); | |
-} | |
- | |
static void __enable_runtime(struct rq *rq) | |
{ | |
rt_rq_iter_t iter; | |
@@ -724,37 +715,6 @@ static void __enable_runtime(struct rq *rq) | |
} | |
} | |
-static void enable_runtime(struct rq *rq) | |
-{ | |
- unsigned long flags; | |
- | |
- raw_spin_lock_irqsave(&rq->lock, flags); | |
- __enable_runtime(rq); | |
- raw_spin_unlock_irqrestore(&rq->lock, flags); | |
-} | |
- | |
-int update_runtime(struct notifier_block *nfb, unsigned long action, void *hcpu) | |
-{ | |
- int cpu = (int)(long)hcpu; | |
- | |
- switch (action) { | |
- case CPU_DOWN_PREPARE: | |
- case CPU_DOWN_PREPARE_FROZEN: | |
- disable_runtime(cpu_rq(cpu)); | |
- return NOTIFY_OK; | |
- | |
- case CPU_DOWN_FAILED: | |
- case CPU_DOWN_FAILED_FROZEN: | |
- case CPU_ONLINE: | |
- case CPU_ONLINE_FROZEN: | |
- enable_runtime(cpu_rq(cpu)); | |
- return NOTIFY_OK; | |
- | |
- default: | |
- return NOTIFY_DONE; | |
- } | |
-} | |
- | |
static int balance_runtime(struct rt_rq *rt_rq) | |
{ | |
int more = 0; | |
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h | |
index 8aac084..3ede2c3 100644 | |
--- a/kernel/sched/sched.h | |
+++ b/kernel/sched/sched.h | |
@@ -866,7 +866,6 @@ extern void sysrq_sched_debug_show(void); | |
extern void sched_init_granularity(void); | |
extern void update_max_interval(void); | |
extern void update_group_power(struct sched_domain *sd, int cpu); | |
-extern int update_runtime(struct notifier_block *nfb, unsigned long action, void *hcpu); | |
extern void init_sched_rt_class(void); | |
extern void init_sched_fair_class(void); | |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c | |
index 85bd64a..92afd83 100644 | |
--- a/kernel/sysctl.c | |
+++ b/kernel/sysctl.c | |
@@ -1106,6 +1106,33 @@ static struct ctl_table vm_table[] = { | |
.mode = 0644, | |
.proc_handler = dirty_writeback_centisecs_handler, | |
}, | |
+ #ifdef CONFIG_DYNAMIC_PAGE_WRITEBACK | |
+ { | |
+ .procname = "dynamic_dirty_writeback", | |
+ .data = &dyn_dirty_writeback_enabled, | |
+ .maxlen = sizeof(dyn_dirty_writeback_enabled), | |
+ .mode = 0644, | |
+ .proc_handler = dynamic_dirty_writeback_handler, | |
+ .extra1 = &zero, | |
+ .extra2 = &one, | |
+ }, | |
+ { | |
+ .procname = "dirty_writeback_active_centisecs", | |
+ .data = &dirty_writeback_active_interval, | |
+ .maxlen = sizeof(dirty_writeback_active_interval), | |
+ .mode = 0644, | |
+ .proc_handler = dirty_writeback_active_centisecs_handler, | |
+ .extra1 = &zero, | |
+ }, | |
+ { | |
+ .procname = "dirty_writeback_suspend_centisecs", | |
+ .data = &dirty_writeback_suspend_interval, | |
+ .maxlen = sizeof(dirty_writeback_suspend_interval), | |
+ .mode = 0644, | |
+ .proc_handler = dirty_writeback_suspend_centisecs_handler, | |
+ .extra1 = &zero, | |
+ }, | |
+#endif | |
{ | |
.procname = "dirty_expire_centisecs", | |
.data = &dirty_expire_interval, | |
diff --git a/mm/Kconfig b/mm/Kconfig | |
index bbab5a6..dac149a 100644 | |
--- a/mm/Kconfig | |
+++ b/mm/Kconfig | |
@@ -380,6 +380,15 @@ config CLEANCACHE | |
If unsure, say Y to enable cleancache | |
+config DYNAMIC_PAGE_WRITEBACK | |
+ bool "Dynamically manage the dirty page writebacks during suspend/resume" | |
+ default y | |
+ help | |
+ This feature allows to use different dirty page writeback intervals | |
+ when the system is suspended and when the system has been resumed. | |
+ | |
+ If unsure, say N to disable this feature | |
+ | |
config MEMORY_HOLE_CARVEOUT | |
bool | |
help | |
diff --git a/mm/memory.c b/mm/memory.c | |
index 0bebc9c..ec4b426 100644 | |
--- a/mm/memory.c | |
+++ b/mm/memory.c | |
@@ -2396,6 +2396,53 @@ int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long | |
} | |
EXPORT_SYMBOL(vm_iomap_memory); | |
+/** | |
++ * vm_iomap_memory - remap memory to userspace | |
++ * @vma: user vma to map to | |
++ * @start: start of area | |
++ * @len: size of area | |
++ * | |
++ * This is a simplified io_remap_pfn_range() for common driver use. The | |
++ * driver just needs to give us the physical memory range to be mapped, | |
++ * we'll figure out the rest from the vma information. | |
++ * | |
++ * NOTE! Some drivers might want to tweak vma->vm_page_prot first to get | |
++ * whatever write-combining details or similar. | |
++ */ | |
+int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len) | |
+{ | |
+ unsigned long vm_len, pfn, pages; | |
+ | |
+ /* Check that the physical memory area passed in looks valid */ | |
+ if (start + len < start) | |
+ return -EINVAL; | |
+ /* | |
+ * You *really* shouldn't map things that aren't page-aligned, | |
+ * but we've historically allowed it because IO memory might | |
+ * just have smaller alignment. | |
++ */ | |
+ len += start & ~PAGE_MASK; | |
+ pfn = start >> PAGE_SHIFT; | |
+ pages = (len + ~PAGE_MASK) >> PAGE_SHIFT; | |
+ if (pfn + pages < pfn) | |
+ return -EINVAL; | |
+ | |
+ /* We start the mapping 'vm_pgoff' pages into the area */ | |
+ if (vma->vm_pgoff > pages) | |
+ return -EINVAL; | |
+ pfn += vma->vm_pgoff; | |
+ pages -= vma->vm_pgoff; | |
+ | |
+ /* Can we fit all of the mapping? */ | |
+ vm_len = vma->vm_end - vma->vm_start; | |
+ if (vm_len >> PAGE_SHIFT > pages) | |
+ return -EINVAL; | |
+ | |
+ /* Ok, let it rip */ | |
+ return io_remap_pfn_range(vma, vma->vm_start, pfn, vm_len, vma->vm_page_prot); | |
+} | |
+EXPORT_SYMBOL(vm_iomap_memory); | |
+ | |
static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd, | |
unsigned long addr, unsigned long end, | |
pte_fn_t fn, void *data) | |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c | |
index f7f5a55..b9dbcd4 100644 | |
--- a/mm/page-writeback.c | |
+++ b/mm/page-writeback.c | |
@@ -36,6 +36,10 @@ | |
#include <linux/pagevec.h> | |
#include <trace/events/writeback.h> | |
+#ifdef CONFIG_DYNAMIC_PAGE_WRITEBACK | |
+#include <linux/earlysuspend.h> | |
+#endif | |
+ | |
/* | |
* Sleep at most 200ms at a time in balance_dirty_pages(). | |
*/ | |
@@ -90,13 +94,43 @@ int vm_dirty_ratio = 20; | |
*/ | |
unsigned long vm_dirty_bytes; | |
+#define DEFAULT_DIRTY_WRITEBACK_INTERVAL 5 * 100 /* centiseconds */ | |
+#define HIGH_DIRTY_WRITEBACK_INTERVAL 15 * 100 /* centiseconds */ | |
+ | |
+/* | |
+++ * The interval between `kupdate'-style writebacks | |
+++ */ | |
+unsigned int dirty_writeback_interval = DEFAULT_DIRTY_WRITEBACK_INTERVAL; /* centiseconds */ | |
+ | |
+ | |
/* | |
* The interval between `kupdate'-style writebacks | |
*/ | |
-unsigned int dirty_writeback_interval = 5 * 100; /* centiseconds */ | |
+ | |
EXPORT_SYMBOL_GPL(dirty_writeback_interval); | |
+ #ifdef CONFIG_DYNAMIC_PAGE_WRITEBACK | |
+ /* | |
+ ++ * The dynamic writeback activation status | |
+ ++ */ | |
+ int dyn_dirty_writeback_enabled = 1; | |
+ EXPORT_SYMBOL_GPL(dyn_dirty_writeback_enabled); | |
+ | |
+ /* | |
+ ++ * The interval between `kupdate'-style writebacks when the system is active | |
+ ++ */ | |
+ unsigned int dirty_writeback_active_interval = HIGH_DIRTY_WRITEBACK_INTERVAL; /* centiseconds */ | |
+ EXPORT_SYMBOL_GPL(dirty_writeback_active_interval); | |
+ | |
+ /* | |
+ ++ * The interval between `kupdate'-style writebacks when the system is suspended | |
+ ++ */ | |
+ unsigned int dirty_writeback_suspend_interval = DEFAULT_DIRTY_WRITEBACK_INTERVAL; /* centiseconds */ | |
+ EXPORT_SYMBOL_GPL(dirty_writeback_suspend_interval); | |
+ #endif | |
+ | |
+ | |
/* | |
* The longest time for which data is allowed to remain dirty | |
*/ | |
@@ -1529,6 +1563,67 @@ int dirty_writeback_centisecs_handler(ctl_table *table, int write, | |
bdi_arm_supers_timer(); | |
return 0; | |
} | |
+#ifdef CONFIG_DYNAMIC_PAGE_WRITEBACK | |
+/* | |
+++ * Manages the dirty page writebacks activation status | |
+++ */ | |
+static void set_dirty_writeback_status(bool active) { | |
+ /* Change the current dirty writeback interval according to the | |
+++ * status provided */ | |
+ dirty_writeback_interval = (active) ? | |
+ dirty_writeback_active_interval : | |
+ dirty_writeback_suspend_interval; | |
+ | |
+ /* Update the timer related to dirty writebacks interval */ | |
+ bdi_arm_supers_timer(); | |
+ | |
+ /* Print debug info */ | |
+ pr_debug("%s: Set dirty_writeback_interval = %d centisecs\n", | |
+ __func__, dirty_writeback_interval); | |
+} | |
+ | |
+/* | |
+++ * sysctl handler for /proc/sys/vm/dyn_dirty_writeback_enabled | |
+++ */ | |
+int dynamic_dirty_writeback_handler(struct ctl_table *table, int write, | |
+ void __user *buffer, size_t *lenp, loff_t *ppos) | |
+{ | |
+ int ret; | |
+ int old_status = dyn_dirty_writeback_enabled; | |
+ | |
+ /* Get and store the new status */ | |
+ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); | |
+ | |
+ /* If the dynamic writeback has been enabled then set the active | |
+++ * dirty writebacks interval, otherwise if the feature has been | |
+++ * disabled, set the suspend interval (the default interval) | |
+++ * to restore the standard functionality */ | |
+ if (ret == 0 && write && dyn_dirty_writeback_enabled != old_status) | |
+ set_dirty_writeback_status(!!dyn_dirty_writeback_enabled); | |
+ | |
+ return ret; | |
+} | |
+ | |
+/* | |
+++ * sysctl handler for /proc/sys/vm/dirty_writeback_active_centisecs | |
+++ */ | |
+int dirty_writeback_active_centisecs_handler(ctl_table *table, int write, | |
+ void __user *buffer, size_t *length, loff_t *ppos) | |
+{ | |
+ proc_dointvec_minmax(table, write, buffer, length, ppos); | |
+ return 0; | |
+} | |
+ | |
+/* | |
+++ * sysctl handler for /proc/sys/vm/dirty_writeback_suspend_centisecs | |
+++ */ | |
+int dirty_writeback_suspend_centisecs_handler(ctl_table *table, int write, | |
+ void __user *buffer, size_t *length, loff_t *ppos) | |
+{ | |
+ proc_dointvec_minmax(table, write, buffer, length, ppos); | |
+ return 0; | |
+} | |
+#endif | |
#ifdef CONFIG_BLOCK | |
void laptop_mode_timer_fn(unsigned long data) | |
@@ -1607,6 +1702,34 @@ static struct notifier_block __cpuinitdata ratelimit_nb = { | |
.next = NULL, | |
}; | |
+#ifdef CONFIG_DYNAMIC_PAGE_WRITEBACK | |
+/* | |
+++ * Sets the dirty page writebacks interval for suspended system | |
+++ */ | |
+static void dirty_writeback_early_suspend(struct early_suspend *handler) | |
+{ | |
+ if (dyn_dirty_writeback_enabled) | |
+ set_dirty_writeback_status(false); | |
+} | |
+ | |
+/* | |
++ * Sets the dirty page writebacks interval for active system | |
+++ */ | |
+static void dirty_writeback_late_resume(struct early_suspend *handler) | |
+{ | |
+ if (dyn_dirty_writeback_enabled) | |
+ set_dirty_writeback_status(true); | |
+} | |
+ | |
+/* | |
+++ * Struct for the dirty page writeback management during suspend/resume | |
+++ */ | |
+static struct early_suspend dirty_writeback_suspend = { | |
+ .suspend = dirty_writeback_early_suspend, | |
+ .resume = dirty_writeback_late_resume, | |
+}; | |
+#endif | |
+ | |
/* | |
* Called early on to tune the page writeback dirty limits. | |
* | |
@@ -1628,6 +1751,11 @@ static struct notifier_block __cpuinitdata ratelimit_nb = { | |
void __init page_writeback_init(void) | |
{ | |
int shift; | |
+ | |
+ #ifdef CONFIG_DYNAMIC_PAGE_WRITEBACK | |
+ /* Register the dirty page writeback management during suspend/resume */ | |
+ register_early_suspend(&dirty_writeback_suspend); | |
+ #endif | |
writeback_set_ratelimit(); | |
register_cpu_notifier(&ratelimit_nb); | |
diff --git a/mm/vmscan.c b/mm/vmscan.c | |
index b9253d7..8d201a2 100644 | |
--- a/mm/vmscan.c | |
+++ b/mm/vmscan.c | |
@@ -153,7 +153,7 @@ struct mem_cgroup_zone { | |
/* | |
* From 0 .. 100. Higher means more swappy. | |
*/ | |
-int vm_swappiness = 45; | |
+int vm_swappiness = 70; | |
long vm_total_pages; /* The total number of pages which the VM controls */ | |
static LIST_HEAD(shrinker_list); | |
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c | |
index 4bf3dc4..8960689 100644 | |
--- a/net/ipv4/netfilter/ipt_ECN.c | |
+++ b/net/ipv4/netfilter/ipt_ECN.c | |
@@ -17,7 +17,7 @@ | |
#include <linux/netfilter/x_tables.h> | |
#include <linux/netfilter_ipv4/ip_tables.h> | |
-#include <linux/netfilter_ipv4/ipt_ECN.h> | |
+#include <linux/netfilter_ipv4/ipt_ECN_new.h> | |
MODULE_LICENSE("GPL"); | |
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile | |
index 452e84d..ba05747 100644 | |
--- a/net/netfilter/Makefile | |
+++ b/net/netfilter/Makefile | |
@@ -57,17 +57,17 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CHECKSUM) += xt_CHECKSUM.o | |
obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o | |
obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o | |
obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o | |
-obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o | |
-obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o | |
+obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP_new.o | |
+obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL_new.o | |
obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o | |
obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o | |
obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o | |
obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o | |
obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o | |
-obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o | |
+obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST_new.o | |
obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o | |
obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o | |
-obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o | |
+obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS_new.o | |
obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o | |
obj-$(CONFIG_NETFILTER_XT_TARGET_TEE) += xt_TEE.o | |
obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o | |
diff --git a/net/netfilter/xt_DSCP_new.c b/net/netfilter/xt_DSCP_new.c | |
new file mode 100644 | |
index 0000000..a1dc46e | |
--- /dev/null | |
+++ b/net/netfilter/xt_DSCP_new.c | |
@@ -0,0 +1,164 @@ | |
+/* x_tables module for setting the IPv4/IPv6 DSCP field, Version 1.8 | |
+ * | |
+ * (C) 2002 by Harald Welte <laforge@netfilter.org> | |
+ * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh <mgm@paktronix.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. | |
+ * | |
+ * See RFC2474 for a description of the DSCP field within the IP Header. | |
+*/ | |
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
+#include <linux/module.h> | |
+#include <linux/skbuff.h> | |
+#include <linux/ip.h> | |
+#include <linux/ipv6.h> | |
+#include <net/dsfield.h> | |
+ | |
+#include <linux/netfilter/x_tables.h> | |
+#include <linux/netfilter/xt_DSCP_new.h> | |
+ | |
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | |
+MODULE_DESCRIPTION("Xtables: DSCP/TOS field modification"); | |
+MODULE_LICENSE("GPL"); | |
+MODULE_ALIAS("ipt_DSCP"); | |
+MODULE_ALIAS("ip6t_DSCP"); | |
+MODULE_ALIAS("ipt_TOS"); | |
+MODULE_ALIAS("ip6t_TOS"); | |
+ | |
+static unsigned int | |
+dscp_tg(struct sk_buff *skb, const struct xt_action_param *par) | |
+{ | |
+ const struct xt_DSCP_info *dinfo = par->targinfo; | |
+ u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; | |
+ | |
+ if (dscp != dinfo->dscp) { | |
+ if (!skb_make_writable(skb, sizeof(struct iphdr))) | |
+ return NF_DROP; | |
+ | |
+ ipv4_change_dsfield(ip_hdr(skb), (__u8)(~XT_DSCP_MASK), | |
+ dinfo->dscp << XT_DSCP_SHIFT); | |
+ | |
+ } | |
+ return XT_CONTINUE; | |
+} | |
+ | |
+static unsigned int | |
+dscp_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |
+{ | |
+ const struct xt_DSCP_info *dinfo = par->targinfo; | |
+ u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; | |
+ | |
+ if (dscp != dinfo->dscp) { | |
+ if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) | |
+ return NF_DROP; | |
+ | |
+ ipv6_change_dsfield(ipv6_hdr(skb), (__u8)(~XT_DSCP_MASK), | |
+ dinfo->dscp << XT_DSCP_SHIFT); | |
+ } | |
+ return XT_CONTINUE; | |
+} | |
+ | |
+static int dscp_tg_check(const struct xt_tgchk_param *par) | |
+{ | |
+ const struct xt_DSCP_info *info = par->targinfo; | |
+ | |
+ if (info->dscp > XT_DSCP_MAX) { | |
+ pr_info("dscp %x out of range\n", info->dscp); | |
+ return -EDOM; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+static unsigned int | |
+tos_tg(struct sk_buff *skb, const struct xt_action_param *par) | |
+{ | |
+ const struct xt_tos_target_info *info = par->targinfo; | |
+ struct iphdr *iph = ip_hdr(skb); | |
+ u_int8_t orig, nv; | |
+ | |
+ orig = ipv4_get_dsfield(iph); | |
+ nv = (orig & ~info->tos_mask) ^ info->tos_value; | |
+ | |
+ if (orig != nv) { | |
+ if (!skb_make_writable(skb, sizeof(struct iphdr))) | |
+ return NF_DROP; | |
+ iph = ip_hdr(skb); | |
+ ipv4_change_dsfield(iph, 0, nv); | |
+ } | |
+ | |
+ return XT_CONTINUE; | |
+} | |
+ | |
+static unsigned int | |
+tos_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |
+{ | |
+ const struct xt_tos_target_info *info = par->targinfo; | |
+ struct ipv6hdr *iph = ipv6_hdr(skb); | |
+ u_int8_t orig, nv; | |
+ | |
+ orig = ipv6_get_dsfield(iph); | |
+ nv = (orig & ~info->tos_mask) ^ info->tos_value; | |
+ | |
+ if (orig != nv) { | |
+ if (!skb_make_writable(skb, sizeof(struct iphdr))) | |
+ return NF_DROP; | |
+ iph = ipv6_hdr(skb); | |
+ ipv6_change_dsfield(iph, 0, nv); | |
+ } | |
+ | |
+ return XT_CONTINUE; | |
+} | |
+ | |
+static struct xt_target dscp_tg_reg[] __read_mostly = { | |
+ { | |
+ .name = "DSCP", | |
+ .family = NFPROTO_IPV4, | |
+ .checkentry = dscp_tg_check, | |
+ .target = dscp_tg, | |
+ .targetsize = sizeof(struct xt_DSCP_info), | |
+ .table = "mangle", | |
+ .me = THIS_MODULE, | |
+ }, | |
+ { | |
+ .name = "DSCP", | |
+ .family = NFPROTO_IPV6, | |
+ .checkentry = dscp_tg_check, | |
+ .target = dscp_tg6, | |
+ .targetsize = sizeof(struct xt_DSCP_info), | |
+ .table = "mangle", | |
+ .me = THIS_MODULE, | |
+ }, | |
+ { | |
+ .name = "TOS", | |
+ .revision = 1, | |
+ .family = NFPROTO_IPV4, | |
+ .table = "mangle", | |
+ .target = tos_tg, | |
+ .targetsize = sizeof(struct xt_tos_target_info), | |
+ .me = THIS_MODULE, | |
+ }, | |
+ { | |
+ .name = "TOS", | |
+ .revision = 1, | |
+ .family = NFPROTO_IPV6, | |
+ .table = "mangle", | |
+ .target = tos_tg6, | |
+ .targetsize = sizeof(struct xt_tos_target_info), | |
+ .me = THIS_MODULE, | |
+ }, | |
+}; | |
+ | |
+static int __init dscp_tg_init(void) | |
+{ | |
+ return xt_register_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); | |
+} | |
+ | |
+static void __exit dscp_tg_exit(void) | |
+{ | |
+ xt_unregister_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); | |
+} | |
+ | |
+module_init(dscp_tg_init); | |
+module_exit(dscp_tg_exit); | |
diff --git a/net/netfilter/xt_HL_new.c b/net/netfilter/xt_HL_new.c | |
new file mode 100644 | |
index 0000000..1a6db28 | |
--- /dev/null | |
+++ b/net/netfilter/xt_HL_new.c | |
@@ -0,0 +1,169 @@ | |
+/* | |
+ * TTL modification target for IP tables | |
+ * (C) 2000,2005 by Harald Welte <laforge@netfilter.org> | |
+ * | |
+ * Hop Limit modification target for ip6tables | |
+ * Maciej Soltysiak <solt@dns.toxicfilms.tv> | |
+ * | |
+ * 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
+#include <linux/module.h> | |
+#include <linux/skbuff.h> | |
+#include <linux/ip.h> | |
+#include <linux/ipv6.h> | |
+#include <net/checksum.h> | |
+ | |
+#include <linux/netfilter/x_tables.h> | |
+#include <linux/netfilter_ipv4/ipt_TTL_new.h> | |
+#include <linux/netfilter_ipv6/ip6t_HL_new.h> | |
+ | |
+MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | |
+MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>"); | |
+MODULE_DESCRIPTION("Xtables: Hoplimit/TTL Limit field modification target"); | |
+MODULE_LICENSE("GPL"); | |
+ | |
+static unsigned int | |
+ttl_tg(struct sk_buff *skb, const struct xt_action_param *par) | |
+{ | |
+ struct iphdr *iph; | |
+ const struct ipt_TTL_info *info = par->targinfo; | |
+ int new_ttl; | |
+ | |
+ if (!skb_make_writable(skb, skb->len)) | |
+ return NF_DROP; | |
+ | |
+ iph = ip_hdr(skb); | |
+ | |
+ switch (info->mode) { | |
+ case IPT_TTL_SET: | |
+ new_ttl = info->ttl; | |
+ break; | |
+ case IPT_TTL_INC: | |
+ new_ttl = iph->ttl + info->ttl; | |
+ if (new_ttl > 255) | |
+ new_ttl = 255; | |
+ break; | |
+ case IPT_TTL_DEC: | |
+ new_ttl = iph->ttl - info->ttl; | |
+ if (new_ttl < 0) | |
+ new_ttl = 0; | |
+ break; | |
+ default: | |
+ new_ttl = iph->ttl; | |
+ break; | |
+ } | |
+ | |
+ if (new_ttl != iph->ttl) { | |
+ csum_replace2(&iph->check, htons(iph->ttl << 8), | |
+ htons(new_ttl << 8)); | |
+ iph->ttl = new_ttl; | |
+ } | |
+ | |
+ return XT_CONTINUE; | |
+} | |
+ | |
+static unsigned int | |
+hl_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |
+{ | |
+ struct ipv6hdr *ip6h; | |
+ const struct ip6t_HL_info *info = par->targinfo; | |
+ int new_hl; | |
+ | |
+ if (!skb_make_writable(skb, skb->len)) | |
+ return NF_DROP; | |
+ | |
+ ip6h = ipv6_hdr(skb); | |
+ | |
+ switch (info->mode) { | |
+ case IP6T_HL_SET: | |
+ new_hl = info->hop_limit; | |
+ break; | |
+ case IP6T_HL_INC: | |
+ new_hl = ip6h->hop_limit + info->hop_limit; | |
+ if (new_hl > 255) | |
+ new_hl = 255; | |
+ break; | |
+ case IP6T_HL_DEC: | |
+ new_hl = ip6h->hop_limit - info->hop_limit; | |
+ if (new_hl < 0) | |
+ new_hl = 0; | |
+ break; | |
+ default: | |
+ new_hl = ip6h->hop_limit; | |
+ break; | |
+ } | |
+ | |
+ ip6h->hop_limit = new_hl; | |
+ | |
+ return XT_CONTINUE; | |
+} | |
+ | |
+static int ttl_tg_check(const struct xt_tgchk_param *par) | |
+{ | |
+ const struct ipt_TTL_info *info = par->targinfo; | |
+ | |
+ if (info->mode > IPT_TTL_MAXMODE) { | |
+ pr_info("TTL: invalid or unknown mode %u\n", info->mode); | |
+ return -EINVAL; | |
+ } | |
+ if (info->mode != IPT_TTL_SET && info->ttl == 0) | |
+ return -EINVAL; | |
+ return 0; | |
+} | |
+ | |
+static int hl_tg6_check(const struct xt_tgchk_param *par) | |
+{ | |
+ const struct ip6t_HL_info *info = par->targinfo; | |
+ | |
+ if (info->mode > IP6T_HL_MAXMODE) { | |
+ pr_info("invalid or unknown mode %u\n", info->mode); | |
+ return -EINVAL; | |
+ } | |
+ if (info->mode != IP6T_HL_SET && info->hop_limit == 0) { | |
+ pr_info("increment/decrement does not " | |
+ "make sense with value 0\n"); | |
+ return -EINVAL; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+static struct xt_target hl_tg_reg[] __read_mostly = { | |
+ { | |
+ .name = "TTL", | |
+ .revision = 0, | |
+ .family = NFPROTO_IPV4, | |
+ .target = ttl_tg, | |
+ .targetsize = sizeof(struct ipt_TTL_info), | |
+ .table = "mangle", | |
+ .checkentry = ttl_tg_check, | |
+ .me = THIS_MODULE, | |
+ }, | |
+ { | |
+ .name = "HL", | |
+ .revision = 0, | |
+ .family = NFPROTO_IPV6, | |
+ .target = hl_tg6, | |
+ .targetsize = sizeof(struct ip6t_HL_info), | |
+ .table = "mangle", | |
+ .checkentry = hl_tg6_check, | |
+ .me = THIS_MODULE, | |
+ }, | |
+}; | |
+ | |
+static int __init hl_tg_init(void) | |
+{ | |
+ return xt_register_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg)); | |
+} | |
+ | |
+static void __exit hl_tg_exit(void) | |
+{ | |
+ xt_unregister_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg)); | |
+} | |
+ | |
+module_init(hl_tg_init); | |
+module_exit(hl_tg_exit); | |
+MODULE_ALIAS("ipt_TTL"); | |
+MODULE_ALIAS("ip6t_HL"); | |
diff --git a/net/netfilter/xt_RATEEST_new.c b/net/netfilter/xt_RATEEST_new.c | |
new file mode 100644 | |
index 0000000..73d607d | |
--- /dev/null | |
+++ b/net/netfilter/xt_RATEEST_new.c | |
@@ -0,0 +1,195 @@ | |
+/* | |
+ * (C) 2007 Patrick McHardy <kaber@trash.net> | |
+ * | |
+ * 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. | |
+ */ | |
+#include <linux/module.h> | |
+#include <linux/skbuff.h> | |
+#include <linux/gen_stats.h> | |
+#include <linux/jhash.h> | |
+#include <linux/rtnetlink.h> | |
+#include <linux/random.h> | |
+#include <linux/slab.h> | |
+#include <net/gen_stats.h> | |
+#include <net/netlink.h> | |
+ | |
+#include <linux/netfilter/x_tables.h> | |
+#include <linux/netfilter/xt_RATEEST_new.h> | |
+#include <net/netfilter/xt_rateest.h> | |
+ | |
+static DEFINE_MUTEX(xt_rateest_mutex); | |
+ | |
+#define RATEEST_HSIZE 16 | |
+static struct hlist_head rateest_hash[RATEEST_HSIZE] __read_mostly; | |
+static unsigned int jhash_rnd __read_mostly; | |
+static bool rnd_inited __read_mostly; | |
+ | |
+static unsigned int xt_rateest_hash(const char *name) | |
+{ | |
+ return jhash(name, FIELD_SIZEOF(struct xt_rateest, name), jhash_rnd) & | |
+ (RATEEST_HSIZE - 1); | |
+} | |
+ | |
+static void xt_rateest_hash_insert(struct xt_rateest *est) | |
+{ | |
+ unsigned int h; | |
+ | |
+ h = xt_rateest_hash(est->name); | |
+ hlist_add_head(&est->list, &rateest_hash[h]); | |
+} | |
+ | |
+struct xt_rateest *xt_rateest_lookup(const char *name) | |
+{ | |
+ struct xt_rateest *est; | |
+ struct hlist_node *n; | |
+ unsigned int h; | |
+ | |
+ h = xt_rateest_hash(name); | |
+ mutex_lock(&xt_rateest_mutex); | |
+ hlist_for_each_entry(est, n, &rateest_hash[h], list) { | |
+ if (strcmp(est->name, name) == 0) { | |
+ est->refcnt++; | |
+ mutex_unlock(&xt_rateest_mutex); | |
+ return est; | |
+ } | |
+ } | |
+ mutex_unlock(&xt_rateest_mutex); | |
+ return NULL; | |
+} | |
+EXPORT_SYMBOL_GPL(xt_rateest_lookup); | |
+ | |
+void xt_rateest_put(struct xt_rateest *est) | |
+{ | |
+ mutex_lock(&xt_rateest_mutex); | |
+ if (--est->refcnt == 0) { | |
+ hlist_del(&est->list); | |
+ gen_kill_estimator(&est->bstats, &est->rstats); | |
+ /* | |
+ * gen_estimator est_timer() might access est->lock or bstats, | |
+ * wait a RCU grace period before freeing 'est' | |
+ */ | |
+ kfree_rcu(est, rcu); | |
+ } | |
+ mutex_unlock(&xt_rateest_mutex); | |
+} | |
+EXPORT_SYMBOL_GPL(xt_rateest_put); | |
+ | |
+static unsigned int | |
+xt_rateest_tg(struct sk_buff *skb, const struct xt_action_param *par) | |
+{ | |
+ const struct xt_rateest_target_info *info = par->targinfo; | |
+ struct gnet_stats_basic_packed *stats = &info->est->bstats; | |
+ | |
+ spin_lock_bh(&info->est->lock); | |
+ stats->bytes += skb->len; | |
+ stats->packets++; | |
+ spin_unlock_bh(&info->est->lock); | |
+ | |
+ return XT_CONTINUE; | |
+} | |
+ | |
+static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) | |
+{ | |
+ struct xt_rateest_target_info *info = par->targinfo; | |
+ struct xt_rateest *est; | |
+ struct { | |
+ struct nlattr opt; | |
+ struct gnet_estimator est; | |
+ } cfg; | |
+ int ret; | |
+ | |
+ if (unlikely(!rnd_inited)) { | |
+ get_random_bytes(&jhash_rnd, sizeof(jhash_rnd)); | |
+ rnd_inited = true; | |
+ } | |
+ | |
+ est = xt_rateest_lookup(info->name); | |
+ if (est) { | |
+ /* | |
+ * If estimator parameters are specified, they must match the | |
+ * existing estimator. | |
+ */ | |
+ if ((!info->interval && !info->ewma_log) || | |
+ (info->interval != est->params.interval || | |
+ info->ewma_log != est->params.ewma_log)) { | |
+ xt_rateest_put(est); | |
+ return -EINVAL; | |
+ } | |
+ info->est = est; | |
+ return 0; | |
+ } | |
+ | |
+ ret = -ENOMEM; | |
+ est = kzalloc(sizeof(*est), GFP_KERNEL); | |
+ if (!est) | |
+ goto err1; | |
+ | |
+ strlcpy(est->name, info->name, sizeof(est->name)); | |
+ spin_lock_init(&est->lock); | |
+ est->refcnt = 1; | |
+ est->params.interval = info->interval; | |
+ est->params.ewma_log = info->ewma_log; | |
+ | |
+ cfg.opt.nla_len = nla_attr_size(sizeof(cfg.est)); | |
+ cfg.opt.nla_type = TCA_STATS_RATE_EST; | |
+ cfg.est.interval = info->interval; | |
+ cfg.est.ewma_log = info->ewma_log; | |
+ | |
+ ret = gen_new_estimator(&est->bstats, &est->rstats, | |
+ &est->lock, &cfg.opt); | |
+ if (ret < 0) | |
+ goto err2; | |
+ | |
+ info->est = est; | |
+ xt_rateest_hash_insert(est); | |
+ return 0; | |
+ | |
+err2: | |
+ kfree(est); | |
+err1: | |
+ return ret; | |
+} | |
+ | |
+static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par) | |
+{ | |
+ struct xt_rateest_target_info *info = par->targinfo; | |
+ | |
+ xt_rateest_put(info->est); | |
+} | |
+ | |
+static struct xt_target xt_rateest_tg_reg __read_mostly = { | |
+ .name = "RATEEST", | |
+ .revision = 0, | |
+ .family = NFPROTO_UNSPEC, | |
+ .target = xt_rateest_tg, | |
+ .checkentry = xt_rateest_tg_checkentry, | |
+ .destroy = xt_rateest_tg_destroy, | |
+ .targetsize = sizeof(struct xt_rateest_target_info), | |
+ .me = THIS_MODULE, | |
+}; | |
+ | |
+static int __init xt_rateest_tg_init(void) | |
+{ | |
+ unsigned int i; | |
+ | |
+ for (i = 0; i < ARRAY_SIZE(rateest_hash); i++) | |
+ INIT_HLIST_HEAD(&rateest_hash[i]); | |
+ | |
+ return xt_register_target(&xt_rateest_tg_reg); | |
+} | |
+ | |
+static void __exit xt_rateest_tg_fini(void) | |
+{ | |
+ xt_unregister_target(&xt_rateest_tg_reg); | |
+} | |
+ | |
+ | |
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | |
+MODULE_LICENSE("GPL"); | |
+MODULE_DESCRIPTION("Xtables: packet rate estimator"); | |
+MODULE_ALIAS("ipt_RATEEST"); | |
+MODULE_ALIAS("ip6t_RATEEST"); | |
+module_init(xt_rateest_tg_init); | |
+module_exit(xt_rateest_tg_fini); | |
diff --git a/net/netfilter/xt_TCPMSS_new.c b/net/netfilter/xt_TCPMSS_new.c | |
new file mode 100644 | |
index 0000000..61d0f83 | |
--- /dev/null | |
+++ b/net/netfilter/xt_TCPMSS_new.c | |
@@ -0,0 +1,320 @@ | |
+/* | |
+ * This is a module which is used for setting the MSS option in TCP packets. | |
+ * | |
+ * Copyright (C) 2000 Marc Boucher <marc@mbsi.ca> | |
+ * | |
+ * 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
+#include <linux/module.h> | |
+#include <linux/skbuff.h> | |
+#include <linux/ip.h> | |
+#include <linux/gfp.h> | |
+#include <linux/ipv6.h> | |
+#include <linux/tcp.h> | |
+#include <net/dst.h> | |
+#include <net/flow.h> | |
+#include <net/ipv6.h> | |
+#include <net/route.h> | |
+#include <net/tcp.h> | |
+ | |
+#include <linux/netfilter_ipv4/ip_tables.h> | |
+#include <linux/netfilter_ipv6/ip6_tables.h> | |
+#include <linux/netfilter/x_tables.h> | |
+#include <linux/netfilter/xt_tcpudp.h> | |
+#include <linux/netfilter/xt_TCPMSS_new.h> | |
+ | |
+MODULE_LICENSE("GPL"); | |
+MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | |
+MODULE_DESCRIPTION("Xtables: TCP Maximum Segment Size (MSS) adjustment"); | |
+MODULE_ALIAS("ipt_TCPMSS"); | |
+MODULE_ALIAS("ip6t_TCPMSS"); | |
+ | |
+static inline unsigned int | |
+optlen(const u_int8_t *opt, unsigned int offset) | |
+{ | |
+ /* Beware zero-length options: make finite progress */ | |
+ if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0) | |
+ return 1; | |
+ else | |
+ return opt[offset+1]; | |
+} | |
+ | |
+static int | |
+tcpmss_mangle_packet(struct sk_buff *skb, | |
+ const struct xt_tcpmss_info *info, | |
+ unsigned int in_mtu, | |
+ unsigned int tcphoff, | |
+ unsigned int minlen) | |
+{ | |
+ struct tcphdr *tcph; | |
+ unsigned int tcplen, i; | |
+ __be16 oldval; | |
+ u16 newmss; | |
+ u8 *opt; | |
+ | |
+ if (!skb_make_writable(skb, skb->len)) | |
+ return -1; | |
+ | |
+ tcplen = skb->len - tcphoff; | |
+ tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); | |
+ | |
+ /* Header cannot be larger than the packet */ | |
+ if (tcplen < tcph->doff*4) | |
+ return -1; | |
+ | |
+ if (info->mss == XT_TCPMSS_CLAMP_PMTU) { | |
+ if (dst_mtu(skb_dst(skb)) <= minlen) { | |
+ if (net_ratelimit()) | |
+ pr_err("unknown or invalid path-MTU (%u)\n", | |
+ dst_mtu(skb_dst(skb))); | |
+ return -1; | |
+ } | |
+ if (in_mtu <= minlen) { | |
+ if (net_ratelimit()) | |
+ pr_err("unknown or invalid path-MTU (%u)\n", | |
+ in_mtu); | |
+ return -1; | |
+ } | |
+ newmss = min(dst_mtu(skb_dst(skb)), in_mtu) - minlen; | |
+ } else | |
+ newmss = info->mss; | |
+ | |
+ opt = (u_int8_t *)tcph; | |
+ for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)) { | |
+ if (opt[i] == TCPOPT_MSS && tcph->doff*4 - i >= TCPOLEN_MSS && | |
+ opt[i+1] == TCPOLEN_MSS) { | |
+ u_int16_t oldmss; | |
+ | |
+ oldmss = (opt[i+2] << 8) | opt[i+3]; | |
+ | |
+ /* Never increase MSS, even when setting it, as | |
+ * doing so results in problems for hosts that rely | |
+ * on MSS being set correctly. | |
+ */ | |
+ if (oldmss <= newmss) | |
+ return 0; | |
+ | |
+ opt[i+2] = (newmss & 0xff00) >> 8; | |
+ opt[i+3] = newmss & 0x00ff; | |
+ | |
+ inet_proto_csum_replace2(&tcph->check, skb, | |
+ htons(oldmss), htons(newmss), | |
+ 0); | |
+ return 0; | |
+ } | |
+ } | |
+ | |
+ /* There is data after the header so the option can't be added | |
+ without moving it, and doing so may make the SYN packet | |
+ itself too large. Accept the packet unmodified instead. */ | |
+ if (tcplen > tcph->doff*4) | |
+ return 0; | |
+ | |
+ /* | |
+ * MSS Option not found ?! add it.. | |
+ */ | |
+ if (skb_tailroom(skb) < TCPOLEN_MSS) { | |
+ if (pskb_expand_head(skb, 0, | |
+ TCPOLEN_MSS - skb_tailroom(skb), | |
+ GFP_ATOMIC)) | |
+ return -1; | |
+ tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); | |
+ } | |
+ | |
+ skb_put(skb, TCPOLEN_MSS); | |
+ | |
+ opt = (u_int8_t *)tcph + sizeof(struct tcphdr); | |
+ memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); | |
+ | |
+ inet_proto_csum_replace2(&tcph->check, skb, | |
+ htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1); | |
+ opt[0] = TCPOPT_MSS; | |
+ opt[1] = TCPOLEN_MSS; | |
+ opt[2] = (newmss & 0xff00) >> 8; | |
+ opt[3] = newmss & 0x00ff; | |
+ | |
+ inet_proto_csum_replace4(&tcph->check, skb, 0, *((__be32 *)opt), 0); | |
+ | |
+ oldval = ((__be16 *)tcph)[6]; | |
+ tcph->doff += TCPOLEN_MSS/4; | |
+ inet_proto_csum_replace2(&tcph->check, skb, | |
+ oldval, ((__be16 *)tcph)[6], 0); | |
+ return TCPOLEN_MSS; | |
+} | |
+ | |
+static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb, | |
+ unsigned int family) | |
+{ | |
+ struct flowi fl; | |
+ const struct nf_afinfo *ai; | |
+ struct rtable *rt = NULL; | |
+ u_int32_t mtu = ~0U; | |
+ | |
+ if (family == PF_INET) { | |
+ struct flowi4 *fl4 = &fl.u.ip4; | |
+ memset(fl4, 0, sizeof(*fl4)); | |
+ fl4->daddr = ip_hdr(skb)->saddr; | |
+ } else { | |
+ struct flowi6 *fl6 = &fl.u.ip6; | |
+ | |
+ memset(fl6, 0, sizeof(*fl6)); | |
+ fl6->daddr = ipv6_hdr(skb)->saddr; | |
+ } | |
+ rcu_read_lock(); | |
+ ai = nf_get_afinfo(family); | |
+ if (ai != NULL) | |
+ ai->route(&init_net, (struct dst_entry **)&rt, &fl, false); | |
+ rcu_read_unlock(); | |
+ | |
+ if (rt != NULL) { | |
+ mtu = dst_mtu(&rt->dst); | |
+ dst_release(&rt->dst); | |
+ } | |
+ return mtu; | |
+} | |
+ | |
+static unsigned int | |
+tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par) | |
+{ | |
+ struct iphdr *iph = ip_hdr(skb); | |
+ __be16 newlen; | |
+ int ret; | |
+ | |
+ ret = tcpmss_mangle_packet(skb, par->targinfo, | |
+ tcpmss_reverse_mtu(skb, PF_INET), | |
+ iph->ihl * 4, | |
+ sizeof(*iph) + sizeof(struct tcphdr)); | |
+ if (ret < 0) | |
+ return NF_DROP; | |
+ if (ret > 0) { | |
+ iph = ip_hdr(skb); | |
+ newlen = htons(ntohs(iph->tot_len) + ret); | |
+ csum_replace2(&iph->check, iph->tot_len, newlen); | |
+ iph->tot_len = newlen; | |
+ } | |
+ return XT_CONTINUE; | |
+} | |
+ | |
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | |
+static unsigned int | |
+tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |
+{ | |
+ struct ipv6hdr *ipv6h = ipv6_hdr(skb); | |
+ u8 nexthdr; | |
+ __be16 frag_off; | |
+ int tcphoff; | |
+ int ret; | |
+ | |
+ nexthdr = ipv6h->nexthdr; | |
+ tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off); | |
+ if (tcphoff < 0) | |
+ return NF_DROP; | |
+ ret = tcpmss_mangle_packet(skb, par->targinfo, | |
+ tcpmss_reverse_mtu(skb, PF_INET6), | |
+ tcphoff, | |
+ sizeof(*ipv6h) + sizeof(struct tcphdr)); | |
+ if (ret < 0) | |
+ return NF_DROP; | |
+ if (ret > 0) { | |
+ ipv6h = ipv6_hdr(skb); | |
+ ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) + ret); | |
+ } | |
+ return XT_CONTINUE; | |
+} | |
+#endif | |
+ | |
+/* Must specify -p tcp --syn */ | |
+static inline bool find_syn_match(const struct xt_entry_match *m) | |
+{ | |
+ const struct xt_tcp *tcpinfo = (const struct xt_tcp *)m->data; | |
+ | |
+ if (strcmp(m->u.kernel.match->name, "tcp") == 0 && | |
+ tcpinfo->flg_cmp & TCPHDR_SYN && | |
+ !(tcpinfo->invflags & XT_TCP_INV_FLAGS)) | |
+ return true; | |
+ | |
+ return false; | |
+} | |
+ | |
+static int tcpmss_tg4_check(const struct xt_tgchk_param *par) | |
+{ | |
+ const struct xt_tcpmss_info *info = par->targinfo; | |
+ const struct ipt_entry *e = par->entryinfo; | |
+ const struct xt_entry_match *ematch; | |
+ | |
+ if (info->mss == XT_TCPMSS_CLAMP_PMTU && | |
+ (par->hook_mask & ~((1 << NF_INET_FORWARD) | | |
+ (1 << NF_INET_LOCAL_OUT) | | |
+ (1 << NF_INET_POST_ROUTING))) != 0) { | |
+ pr_info("path-MTU clamping only supported in " | |
+ "FORWARD, OUTPUT and POSTROUTING hooks\n"); | |
+ return -EINVAL; | |
+ } | |
+ xt_ematch_foreach(ematch, e) | |
+ if (find_syn_match(ematch)) | |
+ return 0; | |
+ pr_info("Only works on TCP SYN packets\n"); | |
+ return -EINVAL; | |
+} | |
+ | |
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | |
+static int tcpmss_tg6_check(const struct xt_tgchk_param *par) | |
+{ | |
+ const struct xt_tcpmss_info *info = par->targinfo; | |
+ const struct ip6t_entry *e = par->entryinfo; | |
+ const struct xt_entry_match *ematch; | |
+ | |
+ if (info->mss == XT_TCPMSS_CLAMP_PMTU && | |
+ (par->hook_mask & ~((1 << NF_INET_FORWARD) | | |
+ (1 << NF_INET_LOCAL_OUT) | | |
+ (1 << NF_INET_POST_ROUTING))) != 0) { | |
+ pr_info("path-MTU clamping only supported in " | |
+ "FORWARD, OUTPUT and POSTROUTING hooks\n"); | |
+ return -EINVAL; | |
+ } | |
+ xt_ematch_foreach(ematch, e) | |
+ if (find_syn_match(ematch)) | |
+ return 0; | |
+ pr_info("Only works on TCP SYN packets\n"); | |
+ return -EINVAL; | |
+} | |
+#endif | |
+ | |
+static struct xt_target tcpmss_tg_reg[] __read_mostly = { | |
+ { | |
+ .family = NFPROTO_IPV4, | |
+ .name = "TCPMSS", | |
+ .checkentry = tcpmss_tg4_check, | |
+ .target = tcpmss_tg4, | |
+ .targetsize = sizeof(struct xt_tcpmss_info), | |
+ .proto = IPPROTO_TCP, | |
+ .me = THIS_MODULE, | |
+ }, | |
+#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | |
+ { | |
+ .family = NFPROTO_IPV6, | |
+ .name = "TCPMSS", | |
+ .checkentry = tcpmss_tg6_check, | |
+ .target = tcpmss_tg6, | |
+ .targetsize = sizeof(struct xt_tcpmss_info), | |
+ .proto = IPPROTO_TCP, | |
+ .me = THIS_MODULE, | |
+ }, | |
+#endif | |
+}; | |
+ | |
+static int __init tcpmss_tg_init(void) | |
+{ | |
+ return xt_register_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg)); | |
+} | |
+ | |
+static void __exit tcpmss_tg_exit(void) | |
+{ | |
+ xt_unregister_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg)); | |
+} | |
+ | |
+module_init(tcpmss_tg_init); | |
+module_exit(tcpmss_tg_exit); | |
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c | |
index 3187684..ece4843 100644 | |
--- a/scripts/mod/modpost.c | |
+++ b/scripts/mod/modpost.c | |
@@ -1855,7 +1855,7 @@ static void add_header(struct buffer *b, struct module *mod) | |
buf_printf(b, "MODULE_INFO(vermagic, VERMAGIC_STRING);\n"); | |
buf_printf(b, "\n"); | |
buf_printf(b, "struct module __this_module\n"); | |
- buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n"); | |
+ buf_printf(b, "__attribute__((externally_visible,section(\".gnu.linkonce.this_module\"))) = {\n"); | |
buf_printf(b, " .name = KBUILD_MODNAME,\n"); | |
if (mod->has_init) | |
buf_printf(b, " .init = init_module,\n"); | |
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c | |
index 6327685..b81ea10 100644 | |
--- a/security/apparmor/domain.c | |
+++ b/security/apparmor/domain.c | |
@@ -394,6 +394,11 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) | |
new_profile = find_attach(ns, &ns->base.profiles, name); | |
if (!new_profile) | |
goto cleanup; | |
+ /* | |
+ * NOTE: Domain transitions from unconfined are allowed | |
+ * even when no_new_privs is set because this aways results | |
+ * in a further reduction of permissions. | |
+ */ | |
goto apply; | |
} | |
@@ -455,6 +460,16 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) | |
/* fail exec */ | |
error = -EACCES; | |
+ /* | |
+ * Policy has specified a domain transition, if no_new_privs then | |
+ * fail the exec. | |
+ */ | |
+ if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) { | |
+ aa_put_profile(new_profile); | |
+ error = -EPERM; | |
+ goto cleanup; | |
+ } | |
+ | |
if (!new_profile) | |
goto audit; | |
@@ -609,6 +624,14 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) | |
const char *target = NULL, *info = NULL; | |
int error = 0; | |
+ /* | |
+ * Fail explicitly requested domain transitions if no_new_privs. | |
+ * There is no exception for unconfined as change_hat is not | |
+ * available. | |
+ */ | |
+ if (current->no_new_privs) | |
+ return -EPERM; | |
+ | |
/* released below */ | |
cred = get_current_cred(); | |
cxt = cred->security; | |
@@ -750,6 +773,18 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec, | |
cxt = cred->security; | |
profile = aa_cred_profile(cred); | |
+ /* | |
+ * Fail explicitly requested domain transitions if no_new_privs | |
+ * and not unconfined. | |
+ * Domain transitions from unconfined are allowed even when | |
+ * no_new_privs is set because this aways results in a reduction | |
+ * of permissions. | |
+ */ | |
+ if (current->no_new_privs && !unconfined(profile)) { | |
+ put_cred(cred); | |
+ return -EPERM; | |
+ } | |
+ | |
if (ns_name) { | |
/* released below */ | |
ns = aa_find_namespace(profile->ns, ns_name); | |
diff --git a/security/commoncap.c b/security/commoncap.c | |
index 0051ac2..98ff463 100644 | |
--- a/security/commoncap.c | |
+++ b/security/commoncap.c | |
@@ -523,14 +523,17 @@ skip: | |
/* Don't let someone trace a set[ug]id/setpcap binary with the revised | |
- * credentials unless they have the appropriate permit | |
+ * credentials unless they have the appropriate permit. | |
+ * | |
+ * In addition, if NO_NEW_PRIVS, then ensure we get no new privs. | |
*/ | |
if ((new->euid != old->uid || | |
new->egid != old->gid || | |
!cap_issubset(new->cap_permitted, old->cap_permitted)) && | |
bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) { | |
/* downgrade; they get no more than they had, and maybe less */ | |
- if (!capable(CAP_SETUID)) { | |
+ if (!capable(CAP_SETUID) || | |
+ (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) { | |
new->euid = new->uid; | |
new->egid = new->gid; | |
} | |
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c | |
new file mode 100644 | |
index 0000000..4ae7304 | |
--- /dev/null | |
+++ b/security/integrity/ima/ima_iint.c | |
@@ -0,0 +1,169 @@ | |
+/* | |
+ * Copyright (C) 2008 IBM Corporation | |
+ * | |
+ * Authors: | |
+ * Mimi Zohar <zohar@us.ibm.com> | |
+ * | |
+ * This program is free software; you can redistribute it and/or | |
+ * modify it under the terms of the GNU General Public License as | |
+ * published by the Free Software Foundation, version 2 of the | |
+ * License. | |
+ * | |
+ * File: ima_iint.c | |
+ * - implements the IMA hooks: ima_inode_alloc, ima_inode_free | |
+ * - cache integrity information associated with an inode | |
+ * using a rbtree tree. | |
+ */ | |
+#include <linux/slab.h> | |
+#include <linux/module.h> | |
+#include <linux/spinlock.h> | |
+#include <linux/rbtree.h> | |
+#include "ima.h" | |
+ | |
+static struct rb_root ima_iint_tree = RB_ROOT; | |
+static DEFINE_SPINLOCK(ima_iint_lock); | |
+static struct kmem_cache *iint_cache __read_mostly; | |
+ | |
+int iint_initialized = 0; | |
+ | |
+/* | |
+ * __ima_iint_find - return the iint associated with an inode | |
+ */ | |
+static struct ima_iint_cache *__ima_iint_find(struct inode *inode) | |
+{ | |
+ struct ima_iint_cache *iint; | |
+ struct rb_node *n = ima_iint_tree.rb_node; | |
+ | |
+ assert_spin_locked(&ima_iint_lock); | |
+ | |
+ while (n) { | |
+ iint = rb_entry(n, struct ima_iint_cache, rb_node); | |
+ | |
+ if (inode < iint->inode) | |
+ n = n->rb_left; | |
+ else if (inode > iint->inode) | |
+ n = n->rb_right; | |
+ else | |
+ break; | |
+ } | |
+ if (!n) | |
+ return NULL; | |
+ | |
+ return iint; | |
+} | |
+ | |
+/* | |
+ * ima_iint_find - return the iint associated with an inode | |
+ */ | |
+struct ima_iint_cache *ima_iint_find(struct inode *inode) | |
+{ | |
+ struct ima_iint_cache *iint; | |
+ | |
+ if (!IS_IMA(inode)) | |
+ return NULL; | |
+ | |
+ spin_lock(&ima_iint_lock); | |
+ iint = __ima_iint_find(inode); | |
+ spin_unlock(&ima_iint_lock); | |
+ | |
+ return iint; | |
+} | |
+ | |
+static void iint_free(struct ima_iint_cache *iint) | |
+{ | |
+ iint->version = 0; | |
+ iint->flags = 0UL; | |
+ kmem_cache_free(iint_cache, iint); | |
+} | |
+ | |
+/** | |
+ * ima_inode_alloc - allocate an iint associated with an inode | |
+ * @inode: pointer to the inode | |
+ */ | |
+int ima_inode_alloc(struct inode *inode) | |
+{ | |
+ struct rb_node **p; | |
+ struct rb_node *new_node, *parent = NULL; | |
+ struct ima_iint_cache *new_iint, *test_iint; | |
+ int rc; | |
+ | |
+ new_iint = kmem_cache_alloc(iint_cache, GFP_NOFS); | |
+ if (!new_iint) | |
+ return -ENOMEM; | |
+ | |
+ new_iint->inode = inode; | |
+ new_node = &new_iint->rb_node; | |
+ | |
+ mutex_lock(&inode->i_mutex); /* i_flags */ | |
+ spin_lock(&ima_iint_lock); | |
+ | |
+ p = &ima_iint_tree.rb_node; | |
+ while (*p) { | |
+ parent = *p; | |
+ test_iint = rb_entry(parent, struct ima_iint_cache, rb_node); | |
+ | |
+ rc = -EEXIST; | |
+ if (inode < test_iint->inode) | |
+ p = &(*p)->rb_left; | |
+ else if (inode > test_iint->inode) | |
+ p = &(*p)->rb_right; | |
+ else | |
+ goto out_err; | |
+ } | |
+ | |
+ inode->i_flags |= S_IMA; | |
+ rb_link_node(new_node, parent, p); | |
+ rb_insert_color(new_node, &ima_iint_tree); | |
+ | |
+ spin_unlock(&ima_iint_lock); | |
+ mutex_unlock(&inode->i_mutex); /* i_flags */ | |
+ | |
+ return 0; | |
+out_err: | |
+ spin_unlock(&ima_iint_lock); | |
+ mutex_unlock(&inode->i_mutex); /* i_flags */ | |
+ iint_free(new_iint); | |
+ | |
+ return rc; | |
+} | |
+ | |
+/** | |
+ * ima_inode_free - called on security_inode_free | |
+ * @inode: pointer to the inode | |
+ * | |
+ * Free the integrity information(iint) associated with an inode. | |
+ */ | |
+void ima_inode_free(struct inode *inode) | |
+{ | |
+ struct ima_iint_cache *iint; | |
+ | |
+ if (!IS_IMA(inode)) | |
+ return; | |
+ | |
+ spin_lock(&ima_iint_lock); | |
+ iint = __ima_iint_find(inode); | |
+ rb_erase(&iint->rb_node, &ima_iint_tree); | |
+ spin_unlock(&ima_iint_lock); | |
+ | |
+ iint_free(iint); | |
+} | |
+ | |
+static void init_once(void *foo) | |
+{ | |
+ struct ima_iint_cache *iint = foo; | |
+ | |
+ memset(iint, 0, sizeof *iint); | |
+ iint->version = 0; | |
+ iint->flags = 0UL; | |
+ mutex_init(&iint->mutex); | |
+} | |
+ | |
+static int __init ima_iintcache_init(void) | |
+{ | |
+ iint_cache = | |
+ kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, | |
+ SLAB_PANIC, init_once); | |
+ iint_initialized = 1; | |
+ return 0; | |
+} | |
+security_initcall(ima_iintcache_init); | |
diff --git a/security/keys/encrypted.c b/security/keys/encrypted.c | |
new file mode 100644 | |
index 0000000..b1cba5b | |
--- /dev/null | |
+++ b/security/keys/encrypted.c | |
@@ -0,0 +1,902 @@ | |
+/* | |
+ * Copyright (C) 2010 IBM Corporation | |
+ * | |
+ * Author: | |
+ * Mimi Zohar <zohar@us.ibm.com> | |
+ * | |
+ * This program is free software; you can redistribute it and/or modify | |
+ * it under the terms of the GNU General Public License as published by | |
+ * the Free Software Foundation, version 2 of the License. | |
+ * | |
+ * See Documentation/security/keys-trusted-encrypted.txt | |
+ */ | |
+ | |
+#include <linux/uaccess.h> | |
+#include <linux/module.h> | |
+#include <linux/init.h> | |
+#include <linux/slab.h> | |
+#include <linux/parser.h> | |
+#include <linux/string.h> | |
+#include <linux/err.h> | |
+#include <keys/user-type.h> | |
+#include <keys/trusted-type.h> | |
+#include <keys/encrypted-type.h> | |
+#include <linux/key-type.h> | |
+#include <linux/random.h> | |
+#include <linux/rcupdate.h> | |
+#include <linux/scatterlist.h> | |
+#include <linux/crypto.h> | |
+#include <crypto/hash.h> | |
+#include <crypto/sha.h> | |
+#include <crypto/aes.h> | |
+ | |
+#include "encrypted.h" | |
+ | |
+static const char KEY_TRUSTED_PREFIX[] = "trusted:"; | |
+static const char KEY_USER_PREFIX[] = "user:"; | |
+static const char hash_alg[] = "sha256"; | |
+static const char hmac_alg[] = "hmac(sha256)"; | |
+static const char blkcipher_alg[] = "cbc(aes)"; | |
+static unsigned int ivsize; | |
+static int blksize; | |
+ | |
+#define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1) | |
+#define KEY_USER_PREFIX_LEN (sizeof (KEY_USER_PREFIX) - 1) | |
+#define HASH_SIZE SHA256_DIGEST_SIZE | |
+#define MAX_DATA_SIZE 4096 | |
+#define MIN_DATA_SIZE 20 | |
+ | |
+struct sdesc { | |
+ struct shash_desc shash; | |
+ char ctx[]; | |
+}; | |
+ | |
+static struct crypto_shash *hashalg; | |
+static struct crypto_shash *hmacalg; | |
+ | |
+enum { | |
+ Opt_err = -1, Opt_new, Opt_load, Opt_update | |
+}; | |
+ | |
+static const match_table_t key_tokens = { | |
+ {Opt_new, "new"}, | |
+ {Opt_load, "load"}, | |
+ {Opt_update, "update"}, | |
+ {Opt_err, NULL} | |
+}; | |
+ | |
+static int aes_get_sizes(void) | |
+{ | |
+ struct crypto_blkcipher *tfm; | |
+ | |
+ tfm = crypto_alloc_blkcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC); | |
+ if (IS_ERR(tfm)) { | |
+ pr_err("encrypted_key: failed to alloc_cipher (%ld)\n", | |
+ PTR_ERR(tfm)); | |
+ return PTR_ERR(tfm); | |
+ } | |
+ ivsize = crypto_blkcipher_ivsize(tfm); | |
+ blksize = crypto_blkcipher_blocksize(tfm); | |
+ crypto_free_blkcipher(tfm); | |
+ return 0; | |
+} | |
+ | |
+/* | |
+ * valid_master_desc - verify the 'key-type:desc' of a new/updated master-key | |
+ * | |
+ * key-type:= "trusted:" | "encrypted:" | |
+ * desc:= master-key description | |
+ * | |
+ * Verify that 'key-type' is valid and that 'desc' exists. On key update, | |
+ * only the master key description is permitted to change, not the key-type. | |
+ * The key-type remains constant. | |
+ * | |
+ * On success returns 0, otherwise -EINVAL. | |
+ */ | |
+static int valid_master_desc(const char *new_desc, const char *orig_desc) | |
+{ | |
+ if (!memcmp(new_desc, KEY_TRUSTED_PREFIX, KEY_TRUSTED_PREFIX_LEN)) { | |
+ if (strlen(new_desc) == KEY_TRUSTED_PREFIX_LEN) | |
+ goto out; | |
+ if (orig_desc) | |
+ if (memcmp(new_desc, orig_desc, KEY_TRUSTED_PREFIX_LEN)) | |
+ goto out; | |
+ } else if (!memcmp(new_desc, KEY_USER_PREFIX, KEY_USER_PREFIX_LEN)) { | |
+ if (strlen(new_desc) == KEY_USER_PREFIX_LEN) | |
+ goto out; | |
+ if (orig_desc) | |
+ if (memcmp(new_desc, orig_desc, KEY_USER_PREFIX_LEN)) | |
+ goto out; | |
+ } else | |
+ goto out; | |
+ return 0; | |
+out: | |
+ return -EINVAL; | |
+} | |
+ | |
+/* | |
+ * datablob_parse - parse the keyctl data | |
+ * | |
+ * datablob format: | |
+ * new <master-key name> <decrypted data length> | |
+ * load <master-key name> <decrypted data length> <encrypted iv + data> | |
+ * update <new-master-key name> | |
+ * | |
+ * Tokenizes a copy of the keyctl data, returning a pointer to each token, | |
+ * which is null terminated. | |
+ * | |
+ * On success returns 0, otherwise -EINVAL. | |
+ */ | |
+static int datablob_parse(char *datablob, char **master_desc, | |
+ char **decrypted_datalen, char **hex_encoded_iv) | |
+{ | |
+ substring_t args[MAX_OPT_ARGS]; | |
+ int ret = -EINVAL; | |
+ int key_cmd; | |
+ char *p; | |
+ | |
+ p = strsep(&datablob, " \t"); | |
+ if (!p) | |
+ return ret; | |
+ key_cmd = match_token(p, key_tokens, args); | |
+ | |
+ *master_desc = strsep(&datablob, " \t"); | |
+ if (!*master_desc) | |
+ goto out; | |
+ | |
+ if (valid_master_desc(*master_desc, NULL) < 0) | |
+ goto out; | |
+ | |
+ if (decrypted_datalen) { | |
+ *decrypted_datalen = strsep(&datablob, " \t"); | |
+ if (!*decrypted_datalen) | |
+ goto out; | |
+ } | |
+ | |
+ switch (key_cmd) { | |
+ case Opt_new: | |
+ if (!decrypted_datalen) | |
+ break; | |
+ ret = 0; | |
+ break; | |
+ case Opt_load: | |
+ if (!decrypted_datalen) | |
+ break; | |
+ *hex_encoded_iv = strsep(&datablob, " \t"); | |
+ if (!*hex_encoded_iv) | |
+ break; | |
+ ret = 0; | |
+ break; | |
+ case Opt_update: | |
+ if (decrypted_datalen) | |
+ break; | |
+ ret = 0; | |
+ break; | |
+ case Opt_err: | |
+ break; | |
+ } | |
+out: | |
+ return ret; | |
+} | |
+ | |
+/* | |
+ * datablob_format - format as an ascii string, before copying to userspace | |
+ */ | |
+static char *datablob_format(struct encrypted_key_payload *epayload, | |
+ size_t asciiblob_len) | |
+{ | |
+ char *ascii_buf, *bufp; | |
+ u8 *iv = epayload->iv; | |
+ int len; | |
+ int i; | |
+ | |
+ ascii_buf = kmalloc(asciiblob_len + 1, GFP_KERNEL); | |
+ if (!ascii_buf) | |
+ goto out; | |
+ | |
+ ascii_buf[asciiblob_len] = '\0'; | |
+ | |
+ /* copy datablob master_desc and datalen strings */ | |
+ len = sprintf(ascii_buf, "%s %s ", epayload->master_desc, | |
+ epayload->datalen); | |
+ | |
+ /* convert the hex encoded iv, encrypted-data and HMAC to ascii */ | |
+ bufp = &ascii_buf[len]; | |
+ for (i = 0; i < (asciiblob_len - len) / 2; i++) | |
+ bufp = pack_hex_byte(bufp, iv[i]); | |
+out: | |
+ return ascii_buf; | |
+} | |
+ | |
+/* | |
+ * request_trusted_key - request the trusted key | |
+ * | |
+ * Trusted keys are sealed to PCRs and other metadata. Although userspace | |
+ * manages both trusted/encrypted key-types, like the encrypted key type | |
+ * data, trusted key type data is not visible decrypted from userspace. | |
+ */ | |
+static struct key *request_trusted_key(const char *trusted_desc, | |
+ u8 **master_key, size_t *master_keylen) | |
+{ | |
+ struct trusted_key_payload *tpayload; | |
+ struct key *tkey; | |
+ | |
+ tkey = request_key(&key_type_trusted, trusted_desc, NULL); | |
+ if (IS_ERR(tkey)) | |
+ goto error; | |
+ | |
+ down_read(&tkey->sem); | |
+ tpayload = rcu_dereference(tkey->payload.data); | |
+ *master_key = tpayload->key; | |
+ *master_keylen = tpayload->key_len; | |
+error: | |
+ return tkey; | |
+} | |
+ | |
+/* | |
+ * request_user_key - request the user key | |
+ * | |
+ * Use a user provided key to encrypt/decrypt an encrypted-key. | |
+ */ | |
+static struct key *request_user_key(const char *master_desc, u8 **master_key, | |
+ size_t *master_keylen) | |
+{ | |
+ struct user_key_payload *upayload; | |
+ struct key *ukey; | |
+ | |
+ ukey = request_key(&key_type_user, master_desc, NULL); | |
+ if (IS_ERR(ukey)) | |
+ goto error; | |
+ | |
+ down_read(&ukey->sem); | |
+ upayload = rcu_dereference(ukey->payload.data); | |
+ *master_key = upayload->data; | |
+ *master_keylen = upayload->datalen; | |
+error: | |
+ return ukey; | |
+} | |
+ | |
+static struct sdesc *alloc_sdesc(struct crypto_shash *alg) | |
+{ | |
+ struct sdesc *sdesc; | |
+ int size; | |
+ | |
+ size = sizeof(struct shash_desc) + crypto_shash_descsize(alg); | |
+ sdesc = kmalloc(size, GFP_KERNEL); | |
+ if (!sdesc) | |
+ return ERR_PTR(-ENOMEM); | |
+ sdesc->shash.tfm = alg; | |
+ sdesc->shash.flags = 0x0; | |
+ return sdesc; | |
+} | |
+ | |
+static int calc_hmac(u8 *digest, const u8 *key, unsigned int keylen, | |
+ const u8 *buf, unsigned int buflen) | |
+{ | |
+ struct sdesc *sdesc; | |
+ int ret; | |
+ | |
+ sdesc = alloc_sdesc(hmacalg); | |
+ if (IS_ERR(sdesc)) { | |
+ pr_info("encrypted_key: can't alloc %s\n", hmac_alg); | |
+ return PTR_ERR(sdesc); | |
+ } | |
+ | |
+ ret = crypto_shash_setkey(hmacalg, key, keylen); | |
+ if (!ret) | |
+ ret = crypto_shash_digest(&sdesc->shash, buf, buflen, digest); | |
+ kfree(sdesc); | |
+ return ret; | |
+} | |
+ | |
+static int calc_hash(u8 *digest, const u8 *buf, unsigned int buflen) | |
+{ | |
+ struct sdesc *sdesc; | |
+ int ret; | |
+ | |
+ sdesc = alloc_sdesc(hashalg); | |
+ if (IS_ERR(sdesc)) { | |
+ pr_info("encrypted_key: can't alloc %s\n", hash_alg); | |
+ return PTR_ERR(sdesc); | |
+ } | |
+ | |
+ ret = crypto_shash_digest(&sdesc->shash, buf, buflen, digest); | |
+ kfree(sdesc); | |
+ return ret; | |
+} | |
+ | |
+enum derived_key_type { ENC_KEY, AUTH_KEY }; | |
+ | |
+/* Derive authentication/encryption key from trusted key */ | |
+static int get_derived_key(u8 *derived_key, enum derived_key_type key_type, | |
+ const u8 *master_key, size_t master_keylen) | |
+{ | |
+ u8 *derived_buf; | |
+ unsigned int derived_buf_len; | |
+ int ret; | |
+ | |
+ derived_buf_len = strlen("AUTH_KEY") + 1 + master_keylen; | |
+ if (derived_buf_len < HASH_SIZE) | |
+ derived_buf_len = HASH_SIZE; | |
+ | |
+ derived_buf = kzalloc(derived_buf_len, GFP_KERNEL); | |
+ if (!derived_buf) { | |
+ pr_err("encrypted_key: out of memory\n"); | |
+ return -ENOMEM; | |
+ } | |
+ if (key_type) | |
+ strcpy(derived_buf, "AUTH_KEY"); | |
+ else | |
+ strcpy(derived_buf, "ENC_KEY"); | |
+ | |
+ memcpy(derived_buf + strlen(derived_buf) + 1, master_key, | |
+ master_keylen); | |
+ ret = calc_hash(derived_key, derived_buf, derived_buf_len); | |
+ kfree(derived_buf); | |
+ return ret; | |
+} | |
+ | |
+static int init_blkcipher_desc(struct blkcipher_desc *desc, const u8 *key, | |
+ unsigned int key_len, const u8 *iv, | |
+ unsigned int ivsize) | |
+{ | |
+ int ret; | |
+ | |
+ desc->tfm = crypto_alloc_blkcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC); | |
+ if (IS_ERR(desc->tfm)) { | |
+ pr_err("encrypted_key: failed to load %s transform (%ld)\n", | |
+ blkcipher_alg, PTR_ERR(desc->tfm)); | |
+ return PTR_ERR(desc->tfm); | |
+ } | |
+ desc->flags = 0; | |
+ | |
+ ret = crypto_blkcipher_setkey(desc->tfm, key, key_len); | |
+ if (ret < 0) { | |
+ pr_err("encrypted_key: failed to setkey (%d)\n", ret); | |
+ crypto_free_blkcipher(desc->tfm); | |
+ return ret; | |
+ } | |
+ crypto_blkcipher_set_iv(desc->tfm, iv, ivsize); | |
+ return 0; | |
+} | |
+ | |
+static struct key *request_master_key(struct encrypted_key_payload *epayload, | |
+ u8 **master_key, size_t *master_keylen) | |
+{ | |
+ struct key *mkey = NULL; | |
+ | |
+ if (!strncmp(epayload->master_desc, KEY_TRUSTED_PREFIX, | |
+ KEY_TRUSTED_PREFIX_LEN)) { | |
+ mkey = request_trusted_key(epayload->master_desc + | |
+ KEY_TRUSTED_PREFIX_LEN, | |
+ master_key, master_keylen); | |
+ } else if (!strncmp(epayload->master_desc, KEY_USER_PREFIX, | |
+ KEY_USER_PREFIX_LEN)) { | |
+ mkey = request_user_key(epayload->master_desc + | |
+ KEY_USER_PREFIX_LEN, | |
+ master_key, master_keylen); | |
+ } else | |
+ goto out; | |
+ | |
+ if (IS_ERR(mkey)) | |
+ pr_info("encrypted_key: key %s not found", | |
+ epayload->master_desc); | |
+ if (mkey) | |
+ dump_master_key(*master_key, *master_keylen); | |
+out: | |
+ return mkey; | |
+} | |
+ | |
+/* Before returning data to userspace, encrypt decrypted data. */ | |
+static int derived_key_encrypt(struct encrypted_key_payload *epayload, | |
+ const u8 *derived_key, | |
+ unsigned int derived_keylen) | |
+{ | |
+ struct scatterlist sg_in[2]; | |
+ struct scatterlist sg_out[1]; | |
+ struct blkcipher_desc desc; | |
+ unsigned int encrypted_datalen; | |
+ unsigned int padlen; | |
+ char pad[16]; | |
+ int ret; | |
+ | |
+ encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); | |
+ padlen = encrypted_datalen - epayload->decrypted_datalen; | |
+ | |
+ ret = init_blkcipher_desc(&desc, derived_key, derived_keylen, | |
+ epayload->iv, ivsize); | |
+ if (ret < 0) | |
+ goto out; | |
+ dump_decrypted_data(epayload); | |
+ | |
+ memset(pad, 0, sizeof pad); | |
+ sg_init_table(sg_in, 2); | |
+ sg_set_buf(&sg_in[0], epayload->decrypted_data, | |
+ epayload->decrypted_datalen); | |
+ sg_set_buf(&sg_in[1], pad, padlen); | |
+ | |
+ sg_init_table(sg_out, 1); | |
+ sg_set_buf(sg_out, epayload->encrypted_data, encrypted_datalen); | |
+ | |
+ ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in, encrypted_datalen); | |
+ crypto_free_blkcipher(desc.tfm); | |
+ if (ret < 0) | |
+ pr_err("encrypted_key: failed to encrypt (%d)\n", ret); | |
+ else | |
+ dump_encrypted_data(epayload, encrypted_datalen); | |
+out: | |
+ return ret; | |
+} | |
+ | |
+static int datablob_hmac_append(struct encrypted_key_payload *epayload, | |
+ const u8 *master_key, size_t master_keylen) | |
+{ | |
+ u8 derived_key[HASH_SIZE]; | |
+ u8 *digest; | |
+ int ret; | |
+ | |
+ ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen); | |
+ if (ret < 0) | |
+ goto out; | |
+ | |
+ digest = epayload->master_desc + epayload->datablob_len; | |
+ ret = calc_hmac(digest, derived_key, sizeof derived_key, | |
+ epayload->master_desc, epayload->datablob_len); | |
+ if (!ret) | |
+ dump_hmac(NULL, digest, HASH_SIZE); | |
+out: | |
+ return ret; | |
+} | |
+ | |
+/* verify HMAC before decrypting encrypted key */ | |
+static int datablob_hmac_verify(struct encrypted_key_payload *epayload, | |
+ const u8 *master_key, size_t master_keylen) | |
+{ | |
+ u8 derived_key[HASH_SIZE]; | |
+ u8 digest[HASH_SIZE]; | |
+ int ret; | |
+ | |
+ ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen); | |
+ if (ret < 0) | |
+ goto out; | |
+ | |
+ ret = calc_hmac(digest, derived_key, sizeof derived_key, | |
+ epayload->master_desc, epayload->datablob_len); | |
+ if (ret < 0) | |
+ goto out; | |
+ ret = memcmp(digest, epayload->master_desc + epayload->datablob_len, | |
+ sizeof digest); | |
+ if (ret) { | |
+ ret = -EINVAL; | |
+ dump_hmac("datablob", | |
+ epayload->master_desc + epayload->datablob_len, | |
+ HASH_SIZE); | |
+ dump_hmac("calc", digest, HASH_SIZE); | |
+ } | |
+out: | |
+ return ret; | |
+} | |
+ | |
+static int derived_key_decrypt(struct encrypted_key_payload *epayload, | |
+ const u8 *derived_key, | |
+ unsigned int derived_keylen) | |
+{ | |
+ struct scatterlist sg_in[1]; | |
+ struct scatterlist sg_out[2]; | |
+ struct blkcipher_desc desc; | |
+ unsigned int encrypted_datalen; | |
+ char pad[16]; | |
+ int ret; | |
+ | |
+ encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); | |
+ ret = init_blkcipher_desc(&desc, derived_key, derived_keylen, | |
+ epayload->iv, ivsize); | |
+ if (ret < 0) | |
+ goto out; | |
+ dump_encrypted_data(epayload, encrypted_datalen); | |
+ | |
+ memset(pad, 0, sizeof pad); | |
+ sg_init_table(sg_in, 1); | |
+ sg_init_table(sg_out, 2); | |
+ sg_set_buf(sg_in, epayload->encrypted_data, encrypted_datalen); | |
+ sg_set_buf(&sg_out[0], epayload->decrypted_data, | |
+ epayload->decrypted_datalen); | |
+ sg_set_buf(&sg_out[1], pad, sizeof pad); | |
+ | |
+ ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, encrypted_datalen); | |
+ crypto_free_blkcipher(desc.tfm); | |
+ if (ret < 0) | |
+ goto out; | |
+ dump_decrypted_data(epayload); | |
+out: | |
+ return ret; | |
+} | |
+ | |
+/* Allocate memory for decrypted key and datablob. */ | |
+static struct encrypted_key_payload *encrypted_key_alloc(struct key *key, | |
+ const char *master_desc, | |
+ const char *datalen) | |
+{ | |
+ struct encrypted_key_payload *epayload = NULL; | |
+ unsigned short datablob_len; | |
+ unsigned short decrypted_datalen; | |
+ unsigned int encrypted_datalen; | |
+ long dlen; | |
+ int ret; | |
+ | |
+ ret = strict_strtol(datalen, 10, &dlen); | |
+ if (ret < 0 || dlen < MIN_DATA_SIZE || dlen > MAX_DATA_SIZE) | |
+ return ERR_PTR(-EINVAL); | |
+ | |
+ decrypted_datalen = dlen; | |
+ encrypted_datalen = roundup(decrypted_datalen, blksize); | |
+ | |
+ datablob_len = strlen(master_desc) + 1 + strlen(datalen) + 1 | |
+ + ivsize + 1 + encrypted_datalen; | |
+ | |
+ ret = key_payload_reserve(key, decrypted_datalen + datablob_len | |
+ + HASH_SIZE + 1); | |
+ if (ret < 0) | |
+ return ERR_PTR(ret); | |
+ | |
+ epayload = kzalloc(sizeof(*epayload) + decrypted_datalen + | |
+ datablob_len + HASH_SIZE + 1, GFP_KERNEL); | |
+ if (!epayload) | |
+ return ERR_PTR(-ENOMEM); | |
+ | |
+ epayload->decrypted_datalen = decrypted_datalen; | |
+ epayload->datablob_len = datablob_len; | |
+ return epayload; | |
+} | |
+ | |
+static int encrypted_key_decrypt(struct encrypted_key_payload *epayload, | |
+ const char *hex_encoded_iv) | |
+{ | |
+ struct key *mkey; | |
+ u8 derived_key[HASH_SIZE]; | |
+ u8 *master_key; | |
+ u8 *hmac; | |
+ const char *hex_encoded_data; | |
+ unsigned int encrypted_datalen; | |
+ size_t master_keylen; | |
+ size_t asciilen; | |
+ int ret; | |
+ | |
+ encrypted_datalen = roundup(epayload->decrypted_datalen, blksize); | |
+ asciilen = (ivsize + 1 + encrypted_datalen + HASH_SIZE) * 2; | |
+ if (strlen(hex_encoded_iv) != asciilen) | |
+ return -EINVAL; | |
+ | |
+ hex_encoded_data = hex_encoded_iv + (2 * ivsize) + 2; | |
+ hex2bin(epayload->iv, hex_encoded_iv, ivsize); | |
+ hex2bin(epayload->encrypted_data, hex_encoded_data, encrypted_datalen); | |
+ | |
+ hmac = epayload->master_desc + epayload->datablob_len; | |
+ hex2bin(hmac, hex_encoded_data + (encrypted_datalen * 2), HASH_SIZE); | |
+ | |
+ mkey = request_master_key(epayload, &master_key, &master_keylen); | |
+ if (IS_ERR(mkey)) | |
+ return PTR_ERR(mkey); | |
+ | |
+ ret = datablob_hmac_verify(epayload, master_key, master_keylen); | |
+ if (ret < 0) { | |
+ pr_err("encrypted_key: bad hmac (%d)\n", ret); | |
+ goto out; | |
+ } | |
+ | |
+ ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen); | |
+ if (ret < 0) | |
+ goto out; | |
+ | |
+ ret = derived_key_decrypt(epayload, derived_key, sizeof derived_key); | |
+ if (ret < 0) | |
+ pr_err("encrypted_key: failed to decrypt key (%d)\n", ret); | |
+out: | |
+ up_read(&mkey->sem); | |
+ key_put(mkey); | |
+ return ret; | |
+} | |
+ | |
+static void __ekey_init(struct encrypted_key_payload *epayload, | |
+ const char *master_desc, const char *datalen) | |
+{ | |
+ epayload->master_desc = epayload->decrypted_data | |
+ + epayload->decrypted_datalen; | |
+ epayload->datalen = epayload->master_desc + strlen(master_desc) + 1; | |
+ epayload->iv = epayload->datalen + strlen(datalen) + 1; | |
+ epayload->encrypted_data = epayload->iv + ivsize + 1; | |
+ | |
+ memcpy(epayload->master_desc, master_desc, strlen(master_desc)); | |
+ memcpy(epayload->datalen, datalen, strlen(datalen)); | |
+} | |
+ | |
+/* | |
+ * encrypted_init - initialize an encrypted key | |
+ * | |
+ * For a new key, use a random number for both the iv and data | |
+ * itself. For an old key, decrypt the hex encoded data. | |
+ */ | |
+static int encrypted_init(struct encrypted_key_payload *epayload, | |
+ const char *master_desc, const char *datalen, | |
+ const char *hex_encoded_iv) | |
+{ | |
+ int ret = 0; | |
+ | |
+ __ekey_init(epayload, master_desc, datalen); | |
+ if (!hex_encoded_iv) { | |
+ get_random_bytes(epayload->iv, ivsize); | |
+ | |
+ get_random_bytes(epayload->decrypted_data, | |
+ epayload->decrypted_datalen); | |
+ } else | |
+ ret = encrypted_key_decrypt(epayload, hex_encoded_iv); | |
+ return ret; | |
+} | |
+ | |
+/* | |
+ * encrypted_instantiate - instantiate an encrypted key | |
+ * | |
+ * Decrypt an existing encrypted datablob or create a new encrypted key | |
+ * based on a kernel random number. | |
+ * | |
+ * On success, return 0. Otherwise return errno. | |
+ */ | |
+static int encrypted_instantiate(struct key *key, const void *data, | |
+ size_t datalen) | |
+{ | |
+ struct encrypted_key_payload *epayload = NULL; | |
+ char *datablob = NULL; | |
+ char *master_desc = NULL; | |
+ char *decrypted_datalen = NULL; | |
+ char *hex_encoded_iv = NULL; | |
+ int ret; | |
+ | |
+ if (datalen <= 0 || datalen > 32767 || !data) | |
+ return -EINVAL; | |
+ | |
+ datablob = kmalloc(datalen + 1, GFP_KERNEL); | |
+ if (!datablob) | |
+ return -ENOMEM; | |
+ datablob[datalen] = 0; | |
+ memcpy(datablob, data, datalen); | |
+ ret = datablob_parse(datablob, &master_desc, &decrypted_datalen, | |
+ &hex_encoded_iv); | |
+ if (ret < 0) | |
+ goto out; | |
+ | |
+ epayload = encrypted_key_alloc(key, master_desc, decrypted_datalen); | |
+ if (IS_ERR(epayload)) { | |
+ ret = PTR_ERR(epayload); | |
+ goto out; | |
+ } | |
+ ret = encrypted_init(epayload, master_desc, decrypted_datalen, | |
+ hex_encoded_iv); | |
+ if (ret < 0) { | |
+ kfree(epayload); | |
+ goto out; | |
+ } | |
+ | |
+ rcu_assign_pointer(key->payload.data, epayload); | |
+out: | |
+ kfree(datablob); | |
+ return ret; | |
+} | |
+ | |
+static void encrypted_rcu_free(struct rcu_head *rcu) | |
+{ | |
+ struct encrypted_key_payload *epayload; | |
+ | |
+ epayload = container_of(rcu, struct encrypted_key_payload, rcu); | |
+ memset(epayload->decrypted_data, 0, epayload->decrypted_datalen); | |
+ kfree(epayload); | |
+} | |
+ | |
+/* | |
+ * encrypted_update - update the master key description | |
+ * | |
+ * Change the master key description for an existing encrypted key. | |
+ * The next read will return an encrypted datablob using the new | |
+ * master key description. | |
+ * | |
+ * On success, return 0. Otherwise return errno. | |
+ */ | |
+static int encrypted_update(struct key *key, const void *data, size_t datalen) | |
+{ | |
+ struct encrypted_key_payload *epayload = key->payload.data; | |
+ struct encrypted_key_payload *new_epayload; | |
+ char *buf; | |
+ char *new_master_desc = NULL; | |
+ int ret = 0; | |
+ | |
+ if (datalen <= 0 || datalen > 32767 || !data) | |
+ return -EINVAL; | |
+ | |
+ buf = kmalloc(datalen + 1, GFP_KERNEL); | |
+ if (!buf) | |
+ return -ENOMEM; | |
+ | |
+ buf[datalen] = 0; | |
+ memcpy(buf, data, datalen); | |
+ ret = datablob_parse(buf, &new_master_desc, NULL, NULL); | |
+ if (ret < 0) | |
+ goto out; | |
+ | |
+ ret = valid_master_desc(new_master_desc, epayload->master_desc); | |
+ if (ret < 0) | |
+ goto out; | |
+ | |
+ new_epayload = encrypted_key_alloc(key, new_master_desc, | |
+ epayload->datalen); | |
+ if (IS_ERR(new_epayload)) { | |
+ ret = PTR_ERR(new_epayload); | |
+ goto out; | |
+ } | |
+ | |
+ __ekey_init(new_epayload, new_master_desc, epayload->datalen); | |
+ | |
+ memcpy(new_epayload->iv, epayload->iv, ivsize); | |
+ memcpy(new_epayload->decrypted_data, epayload->decrypted_data, | |
+ epayload->decrypted_datalen); | |
+ | |
+ rcu_assign_pointer(key->payload.data, new_epayload); | |
+ call_rcu(&epayload->rcu, encrypted_rcu_free); | |
+out: | |
+ kfree(buf); | |
+ return ret; | |
+} | |
+ | |
+/* | |
+ * encrypted_read - format and copy the encrypted data to userspace | |
+ * | |
+ * The resulting datablob format is: | |
+ * <master-key name> <decrypted data length> <encrypted iv> <encrypted data> | |
+ * | |
+ * On success, return to userspace the encrypted key datablob size. | |
+ */ | |
+static long encrypted_read(const struct key *key, char __user *buffer, | |
+ size_t buflen) | |
+{ | |
+ struct encrypted_key_payload *epayload; | |
+ struct key *mkey; | |
+ u8 *master_key; | |
+ size_t master_keylen; | |
+ char derived_key[HASH_SIZE]; | |
+ char *ascii_buf; | |
+ size_t asciiblob_len; | |
+ int ret; | |
+ | |
+ epayload = rcu_dereference_key(key); | |
+ | |
+ /* returns the hex encoded iv, encrypted-data, and hmac as ascii */ | |
+ asciiblob_len = epayload->datablob_len + ivsize + 1 | |
+ + roundup(epayload->decrypted_datalen, blksize) | |
+ + (HASH_SIZE * 2); | |
+ | |
+ if (!buffer || buflen < asciiblob_len) | |
+ return asciiblob_len; | |
+ | |
+ mkey = request_master_key(epayload, &master_key, &master_keylen); | |
+ if (IS_ERR(mkey)) | |
+ return PTR_ERR(mkey); | |
+ | |
+ ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen); | |
+ if (ret < 0) | |
+ goto out; | |
+ | |
+ ret = derived_key_encrypt(epayload, derived_key, sizeof derived_key); | |
+ if (ret < 0) | |
+ goto out; | |
+ | |
+ ret = datablob_hmac_append(epayload, master_key, master_keylen); | |
+ if (ret < 0) | |
+ goto out; | |
+ | |
+ ascii_buf = datablob_format(epayload, asciiblob_len); | |
+ if (!ascii_buf) { | |
+ ret = -ENOMEM; | |
+ goto out; | |
+ } | |
+ | |
+ up_read(&mkey->sem); | |
+ key_put(mkey); | |
+ | |
+ if (copy_to_user(buffer, ascii_buf, asciiblob_len) != 0) | |
+ ret = -EFAULT; | |
+ kfree(ascii_buf); | |
+ | |
+ return asciiblob_len; | |
+out: | |
+ up_read(&mkey->sem); | |
+ key_put(mkey); | |
+ return ret; | |
+} | |
+ | |
+/* | |
+ * encrypted_destroy - before freeing the key, clear the decrypted data | |
+ * | |
+ * Before freeing the key, clear the memory containing the decrypted | |
+ * key data. | |
+ */ | |
+static void encrypted_destroy(struct key *key) | |
+{ | |
+ struct encrypted_key_payload *epayload = key->payload.data; | |
+ | |
+ if (!epayload) | |
+ return; | |
+ | |
+ memset(epayload->decrypted_data, 0, epayload->decrypted_datalen); | |
+ kfree(key->payload.data); | |
+} | |
+ | |
+struct key_type key_type_encrypted = { | |
+ .name = "encrypted", | |
+ .instantiate = encrypted_instantiate, | |
+ .update = encrypted_update, | |
+ .match = user_match, | |
+ .destroy = encrypted_destroy, | |
+ .describe = user_describe, | |
+ .read = encrypted_read, | |
+}; | |
+EXPORT_SYMBOL_GPL(key_type_encrypted); | |
+ | |
+static void encrypted_shash_release(void) | |
+{ | |
+ if (hashalg) | |
+ crypto_free_shash(hashalg); | |
+ if (hmacalg) | |
+ crypto_free_shash(hmacalg); | |
+} | |
+ | |
+static int __init encrypted_shash_alloc(void) | |
+{ | |
+ int ret; | |
+ | |
+ hmacalg = crypto_alloc_shash(hmac_alg, 0, CRYPTO_ALG_ASYNC); | |
+ if (IS_ERR(hmacalg)) { | |
+ pr_info("encrypted_key: could not allocate crypto %s\n", | |
+ hmac_alg); | |
+ return PTR_ERR(hmacalg); | |
+ } | |
+ | |
+ hashalg = crypto_alloc_shash(hash_alg, 0, CRYPTO_ALG_ASYNC); | |
+ if (IS_ERR(hashalg)) { | |
+ pr_info("encrypted_key: could not allocate crypto %s\n", | |
+ hash_alg); | |
+ ret = PTR_ERR(hashalg); | |
+ goto hashalg_fail; | |
+ } | |
+ | |
+ return 0; | |
+ | |
+hashalg_fail: | |
+ crypto_free_shash(hmacalg); | |
+ return ret; | |
+} | |
+ | |
+static int __init init_encrypted(void) | |
+{ | |
+ int ret; | |
+ | |
+ ret = encrypted_shash_alloc(); | |
+ if (ret < 0) | |
+ return ret; | |
+ ret = register_key_type(&key_type_encrypted); | |
+ if (ret < 0) | |
+ goto out; | |
+ return aes_get_sizes(); | |
+out: | |
+ encrypted_shash_release(); | |
+ return ret; | |
+ | |
+} | |
+ | |
+static void __exit cleanup_encrypted(void) | |
+{ | |
+ encrypted_shash_release(); | |
+ unregister_key_type(&key_type_encrypted); | |
+} | |
+ | |
+late_initcall(init_encrypted); | |
+module_exit(cleanup_encrypted); | |
+ | |
+MODULE_LICENSE("GPL"); | |
diff --git a/security/keys/encrypted.h b/security/keys/encrypted.h | |
new file mode 100644 | |
index 0000000..cef5e2f | |
--- /dev/null | |
+++ b/security/keys/encrypted.h | |
@@ -0,0 +1,54 @@ | |
+#ifndef __ENCRYPTED_KEY_H | |
+#define __ENCRYPTED_KEY_H | |
+ | |
+#define ENCRYPTED_DEBUG 0 | |
+ | |
+#if ENCRYPTED_DEBUG | |
+static inline void dump_master_key(const u8 *master_key, size_t master_keylen) | |
+{ | |
+ print_hex_dump(KERN_ERR, "master key: ", DUMP_PREFIX_NONE, 32, 1, | |
+ master_key, master_keylen, 0); | |
+} | |
+ | |
+static inline void dump_decrypted_data(struct encrypted_key_payload *epayload) | |
+{ | |
+ print_hex_dump(KERN_ERR, "decrypted data: ", DUMP_PREFIX_NONE, 32, 1, | |
+ epayload->decrypted_data, | |
+ epayload->decrypted_datalen, 0); | |
+} | |
+ | |
+static inline void dump_encrypted_data(struct encrypted_key_payload *epayload, | |
+ unsigned int encrypted_datalen) | |
+{ | |
+ print_hex_dump(KERN_ERR, "encrypted data: ", DUMP_PREFIX_NONE, 32, 1, | |
+ epayload->encrypted_data, encrypted_datalen, 0); | |
+} | |
+ | |
+static inline void dump_hmac(const char *str, const u8 *digest, | |
+ unsigned int hmac_size) | |
+{ | |
+ if (str) | |
+ pr_info("encrypted_key: %s", str); | |
+ print_hex_dump(KERN_ERR, "hmac: ", DUMP_PREFIX_NONE, 32, 1, digest, | |
+ hmac_size, 0); | |
+} | |
+#else | |
+static inline void dump_master_key(const u8 *master_key, size_t master_keylen) | |
+{ | |
+} | |
+ | |
+static inline void dump_decrypted_data(struct encrypted_key_payload *epayload) | |
+{ | |
+} | |
+ | |
+static inline void dump_encrypted_data(struct encrypted_key_payload *epayload, | |
+ unsigned int encrypted_datalen) | |
+{ | |
+} | |
+ | |
+static inline void dump_hmac(const char *str, const u8 *digest, | |
+ unsigned int hmac_size) | |
+{ | |
+} | |
+#endif | |
+#endif | |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c | |
index 4bbd03a..2347fe2 100644 | |
--- a/security/selinux/hooks.c | |
+++ b/security/selinux/hooks.c | |
@@ -2119,6 +2119,13 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |
new_tsec->sid = old_tsec->exec_sid; | |
/* Reset exec SID on execve. */ | |
new_tsec->exec_sid = 0; | |
+ | |
+ /* | |
+ * Minimize confusion: if no_new_privs and a transition is | |
+ * explicitly requested, then fail the exec. | |
+ */ | |
+ if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) | |
+ return -EPERM; | |
} else { | |
/* Check for a default transition on this program. */ | |
rc = security_transition_sid(old_tsec->sid, isec->sid, | |
@@ -2132,7 +2139,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |
ad.selinux_audit_data = &sad; | |
ad.u.path = bprm->file->f_path; | |
- if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | |
+ if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) || | |
+ (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) | |
new_tsec->sid = old_tsec->sid; | |
if (new_tsec->sid == old_tsec->sid) { | |
diff --git a/security/smc/Makefile b/security/smc/Makefile | |
new file mode 100644 | |
index 0000000..c0b958b | |
--- /dev/null | |
+++ b/security/smc/Makefile | |
@@ -0,0 +1,49 @@ | |
+# | |
+# Copyright (c) 2006-2010 Trusted Logic S.A. | |
+# All Rights Reserved. | |
+# | |
+# This program is free software; you can redistribute it and/or | |
+# modify it under the terms of the GNU General Public License as | |
+# published by the Free Software Foundation; either version 2 of | |
+# the License, or (at your option) any later version. | |
+# | |
+# This program is distributed in the hope that it will be useful, | |
+# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
+# GNU General Public License for more details. | |
+# | |
+# You should have received a copy of the GNU General Public License | |
+# along with this program; if not, write to the Free Software | |
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
+# MA 02111-1307 USA | |
+# | |
+ | |
+ifdef S_VERSION_BUILD | |
+EXTRA_CFLAGS += -DS_VERSION_BUILD=$(S_VERSION_BUILD) | |
+endif | |
+ | |
+plus_sec := $(call as-instr,.arch_extension sec,+sec) | |
+ | |
+EXTRA_CFLAGS += -Iarch/arm/mach-omap2 | |
+EXTRA_CFLAGS += -Iarch/arm/plat-omap/include/plat | |
+EXTRA_CFLAGS += -DCONFIG_TF_TEEC | |
+EXTRA_CFLAGS += -DCONFIG_TF_ION | |
+ | |
+tf_driver-objs += tf_util.o | |
+tf_driver-objs += tf_conn.o | |
+tf_driver-objs += tf_device.o | |
+tf_driver-objs += tf_comm.o | |
+tf_driver-objs += tf_crypto.o | |
+tf_driver-objs += tf_crypto_digest.o | |
+tf_driver-objs += tf_crypto_aes.o | |
+tf_driver-objs += tf_crypto_des.o | |
+tf_driver-objs += tf_dma.o | |
+tf_driver-objs += tf_comm_mshield.o | |
+tf_driver-objs += tf_device_mshield.o | |
+tf_driver-objs += bridge_pub2sec.o | |
+tf_driver-objs += tf_teec.o | |
+ | |
+AFLAGS_bridge_pub2sec.o +=-Wa,-march=armv7-a$(plus_sec) | |
+ | |
+obj-$(CONFIG_SECURITY_MIDDLEWARE_COMPONENT) += tf_driver.o | |
+obj-$(CONFIG_SECURITY_MIDDLEWARE_COMPONENT) += rproc_drm.o | |
-- | |
2.7.4 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment