Skip to content

Instantly share code, notes, and snippets.

@Ahmed-Hady
Created October 15, 2016 18:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ahmed-Hady/f3e0963fa8afce52b0c2ec46be9f7257 to your computer and use it in GitHub Desktop.
Save Ahmed-Hady/f3e0963fa8afce52b0c2ec46be9f7257 to your computer and use it in GitHub Desktop.
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, &param);
- 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,
&reg_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