Merge "ASoC: msm: qdsp6v2: Fix bugs in listen client and server"
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index a41f9d5..c0253da 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -283,6 +283,7 @@
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
+CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
CONFIG_FB=y
CONFIG_FB_VIRTUAL=y
CONFIG_FB_MSM=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index fe77fc4..ce5ee8d 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -282,6 +282,7 @@
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
+CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
CONFIG_FB=y
CONFIG_FB_MSM=y
# CONFIG_FB_MSM_BACKLIGHT is not set
diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c
index bdb5455..5e12a0d 100644
--- a/arch/arm/mach-msm/mdm_common.c
+++ b/arch/arm/mach-msm/mdm_common.c
@@ -138,41 +138,6 @@
spin_unlock_irqrestore(&mdm_devices_lock, flags);
}
-struct mdm_device *mdm_get_device_by_device_id(int device_id)
-{
- unsigned long flags;
- struct mdm_device *mdev = NULL;
-
- spin_lock_irqsave(&mdm_devices_lock, flags);
- list_for_each_entry(mdev, &mdm_devices, link) {
- if (mdev && mdev->mdm_data.device_id == device_id) {
- spin_unlock_irqrestore(&mdm_devices_lock, flags);
- return mdev;
- }
- }
- spin_unlock_irqrestore(&mdm_devices_lock, flags);
- return NULL;
-}
-
-struct mdm_device *mdm_get_device_by_name(const char *name)
-{
- unsigned long flags;
- struct mdm_device *mdev;
-
- if (!name)
- return NULL;
- spin_lock_irqsave(&mdm_devices_lock, flags);
- list_for_each_entry(mdev, &mdm_devices, link) {
- if (mdev && !strncmp(mdev->device_name, name,
- sizeof(mdev->device_name))) {
- spin_unlock_irqrestore(&mdm_devices_lock, flags);
- return mdev;
- }
- }
- spin_unlock_irqrestore(&mdm_devices_lock, flags);
- return NULL;
-}
-
/* If the platform's cascading_ssr flag is set, the subsystem
* restart module will restart the other modems so stop
* monitoring them as well.
@@ -390,19 +355,13 @@
}
}
-long mdm_modem_ioctl(struct file *filp, unsigned int cmd,
+static long mdm_modem_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
int status, ret = 0;
- struct mdm_device *mdev;
+ struct mdm_device *mdev = filp->private_data;
struct mdm_modem_drv *mdm_drv;
- mdev = mdm_get_device_by_name(filp->f_path.dentry->d_iname);
- if (!mdev) {
- pr_err("%s: mdm_device not found\n", __func__);
- return -ENODEV;
- }
-
if (_IOC_TYPE(cmd) != CHARM_CODE) {
pr_err("%s: invalid ioctl code to mdm id %d\n",
__func__, mdev->mdm_data.device_id);
@@ -559,6 +518,11 @@
/* set the mdm_device as the file's private data */
static int mdm_modem_open(struct inode *inode, struct file *file)
{
+ struct miscdevice *misc = file->private_data;
+ struct mdm_device *mdev = container_of(misc,
+ struct mdm_device, misc_device);
+
+ file->private_data = mdev;
return 0;
}
@@ -1072,6 +1036,7 @@
goto init_err;
}
+ platform_set_drvdata(pdev, mdev);
mdm_modem_initialize_data(pdev, mdev);
if (mdm_ops->debug_state_changed_cb)
@@ -1118,10 +1083,7 @@
static int __devexit mdm_modem_remove(struct platform_device *pdev)
{
int ret;
- struct mdm_device *mdev = mdm_get_device_by_device_id(pdev->id);
-
- if (!mdev)
- return -ENODEV;
+ struct mdm_device *mdev = platform_get_drvdata(pdev);
pr_debug("%s: removing device id %d\n",
__func__, mdev->mdm_data.device_id);
@@ -1135,9 +1097,7 @@
static void mdm_modem_shutdown(struct platform_device *pdev)
{
struct mdm_modem_drv *mdm_drv;
- struct mdm_device *mdev = mdm_get_device_by_device_id(pdev->id);
- if (!mdev)
- return;
+ struct mdm_device *mdev = platform_get_drvdata(pdev);
pr_debug("%s: shutting down device id %d\n",
__func__, mdev->mdm_data.device_id);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index d0e3e34..d7bf193 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -603,10 +603,10 @@
static unsigned int _adreno_iommu_setstate_v0(struct kgsl_device *device,
unsigned int *cmds_orig,
- unsigned int pt_val,
+ phys_addr_t pt_val,
int num_iommu_units, uint32_t flags)
{
- unsigned int reg_pt_val;
+ phys_addr_t reg_pt_val;
unsigned int *cmds = cmds_orig;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int i;
@@ -632,8 +632,10 @@
* IOMMU units
*/
for (i = 0; i < num_iommu_units; i++) {
- reg_pt_val = (pt_val + kgsl_mmu_get_pt_lsb(&device->mmu,
- i, KGSL_IOMMU_CONTEXT_USER));
+ reg_pt_val = kgsl_mmu_get_default_ttbr0(&device->mmu,
+ i, KGSL_IOMMU_CONTEXT_USER);
+ reg_pt_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK;
+ reg_pt_val |= (pt_val & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK);
/*
* Set address of the new pagetable by writng to IOMMU
* TTBR0 register
@@ -662,8 +664,11 @@
* tlb flush
*/
for (i = 0; i < num_iommu_units; i++) {
- reg_pt_val = (pt_val + kgsl_mmu_get_pt_lsb(&device->mmu,
+ reg_pt_val = (pt_val + kgsl_mmu_get_default_ttbr0(
+ &device->mmu,
i, KGSL_IOMMU_CONTEXT_USER));
+ reg_pt_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK;
+ reg_pt_val |= (pt_val & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK);
*cmds++ = cp_type3_packet(CP_MEM_WRITE, 2);
*cmds++ = kgsl_mmu_get_reg_gpuaddr(&device->mmu, i,
@@ -707,17 +712,20 @@
static unsigned int _adreno_iommu_setstate_v1(struct kgsl_device *device,
unsigned int *cmds_orig,
- unsigned int pt_val,
+ phys_addr_t pt_val,
int num_iommu_units, uint32_t flags)
{
+ phys_addr_t ttbr0_val;
unsigned int reg_pt_val;
unsigned int *cmds = cmds_orig;
int i;
unsigned int ttbr0, tlbiall, tlbstatus, tlbsync, mmu_ctrl;
for (i = 0; i < num_iommu_units; i++) {
- reg_pt_val = (pt_val + kgsl_mmu_get_pt_lsb(&device->mmu,
- i, KGSL_IOMMU_CONTEXT_USER));
+ ttbr0_val = kgsl_mmu_get_default_ttbr0(&device->mmu,
+ i, KGSL_IOMMU_CONTEXT_USER);
+ ttbr0_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK;
+ ttbr0_val |= (pt_val & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK);
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
mmu_ctrl = kgsl_mmu_get_reg_ahbaddr(
&device->mmu, i,
@@ -753,8 +761,19 @@
KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_IDLE, 0xF);
}
/* set ttbr0 */
- *cmds++ = cp_type0_packet(ttbr0, 1);
- *cmds++ = reg_pt_val;
+ if (sizeof(phys_addr_t) > sizeof(unsigned long)) {
+ reg_pt_val = ttbr0_val & 0xFFFFFFFF;
+ *cmds++ = cp_type0_packet(ttbr0, 1);
+ *cmds++ = reg_pt_val;
+ reg_pt_val = (unsigned int)
+ ((ttbr0_val & 0xFFFFFFFF00000000ULL) >> 32);
+ *cmds++ = cp_type0_packet(ttbr0 + 1, 1);
+ *cmds++ = reg_pt_val;
+ } else {
+ reg_pt_val = ttbr0_val;
+ *cmds++ = cp_type0_packet(ttbr0, 1);
+ *cmds++ = reg_pt_val;
+ }
if (kgsl_mmu_hw_halt_supported(&device->mmu, i)) {
/* unlock the IOMMU lock */
*cmds++ = cp_type3_packet(CP_REG_RMW, 3);
@@ -796,7 +815,7 @@
unsigned int context_id,
uint32_t flags)
{
- unsigned int pt_val;
+ phys_addr_t pt_val;
unsigned int link[230];
unsigned int *cmds = &link[0];
int sizedwords = 0;
@@ -808,7 +827,8 @@
if (!adreno_dev->drawctxt_active ||
KGSL_STATE_ACTIVE != device->state ||
- !device->active_cnt) {
+ !device->active_cnt ||
+ device->cff_dump_enable) {
kgsl_mmu_device_setstate(&device->mmu, flags);
return;
}
@@ -891,7 +911,7 @@
* writes For CFF dump we must idle and use the registers so that it is
* easier to filter out the mmu accesses from the dump
*/
- if (!kgsl_cff_dump_enable && adreno_dev->drawctxt_active) {
+ if (!device->cff_dump_enable && adreno_dev->drawctxt_active) {
context = idr_find(&device->context_idr, context_id);
if (context == NULL)
return;
@@ -1814,7 +1834,7 @@
/* Power down the device */
kgsl_pwrctrl_disable(device);
- kgsl_cffdump_close(device->id);
+ kgsl_cffdump_close(device);
return 0;
}
@@ -1861,11 +1881,11 @@
while ((context = idr_get_next(&device->context_idr, &next))) {
temp_adreno_context = context->devctxt;
if (temp_adreno_context->flags & CTXT_FLAGS_GPU_HANG) {
- kgsl_sharedmem_writel(&device->memstore,
+ kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(context->id,
soptimestamp),
rb->timestamp[context->id]);
- kgsl_sharedmem_writel(&device->memstore,
+ kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(context->id,
eoptimestamp),
rb->timestamp[context->id]);
@@ -2542,7 +2562,7 @@
else
device->mmu.hwpagetable = device->mmu.defaultpagetable;
rb->timestamp[KGSL_MEMSTORE_GLOBAL] = timestamp;
- kgsl_sharedmem_writel(&device->memstore,
+ kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
eoptimestamp),
rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
@@ -2581,7 +2601,7 @@
INIT_COMPLETION(device->ft_gate);
/* Detected a hang */
- kgsl_cffdump_hang(device->id);
+ kgsl_cffdump_hang(device);
/* Run fault tolerance at max power level */
curr_pwrlevel = pwr->active_pwrlevel;
kgsl_pwrctrl_pwrlevel_change(device, pwr->max_pwrlevel);
@@ -2823,7 +2843,7 @@
memset(prev_reg_val, 0, sizeof(prev_reg_val));
- kgsl_cffdump_regpoll(device->id,
+ kgsl_cffdump_regpoll(device,
adreno_dev->gpudev->reg_rbbm_status << 2,
0x00000000, 0x80000000);
@@ -2945,7 +2965,7 @@
/* Find a memory structure attached to an adreno context */
struct kgsl_memdesc *adreno_find_ctxtmem(struct kgsl_device *device,
- unsigned int pt_base, unsigned int gpuaddr, unsigned int size)
+ phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size)
{
struct kgsl_context *context;
struct adreno_context *adreno_context = NULL;
@@ -2977,7 +2997,7 @@
}
struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
- unsigned int pt_base,
+ phys_addr_t pt_base,
unsigned int gpuaddr,
unsigned int size)
{
@@ -3006,7 +3026,7 @@
return adreno_find_ctxtmem(device, pt_base, gpuaddr, size);
}
-uint8_t *adreno_convertaddr(struct kgsl_device *device, unsigned int pt_base,
+uint8_t *adreno_convertaddr(struct kgsl_device *device, phys_addr_t pt_base,
unsigned int gpuaddr, unsigned int size)
{
struct kgsl_memdesc *memdesc;
@@ -3080,7 +3100,7 @@
kgsl_trace_regwrite(device, offsetwords, value);
- kgsl_cffdump_regwrite(device->id, offsetwords << 2, value);
+ kgsl_cffdump_regwrite(device, offsetwords << 2, value);
reg = (unsigned int *)(device->reg_virt + (offsetwords << 2));
/*ensure previous writes post before this one,
@@ -3140,18 +3160,18 @@
/* Make sure the memstore read has posted */
mb();
if (timestamp_cmp(ref_ts, timestamp) >= 0) {
- kgsl_sharedmem_writel(&device->memstore,
+ kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(context_id,
ref_wait_ts), timestamp);
/* Make sure the memstore write is posted */
wmb();
}
} else {
- kgsl_sharedmem_writel(&device->memstore,
+ kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(context_id,
ref_wait_ts), timestamp);
enableflag = 1;
- kgsl_sharedmem_writel(&device->memstore,
+ kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(context_id,
ts_cmp_enable), enableflag);
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 77b654b..816940f 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -302,15 +302,15 @@
*adreno_dev);
struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
- unsigned int pt_base,
+ phys_addr_t pt_base,
unsigned int gpuaddr,
unsigned int size);
uint8_t *adreno_convertaddr(struct kgsl_device *device,
- unsigned int pt_base, unsigned int gpuaddr, unsigned int size);
+ phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size);
struct kgsl_memdesc *adreno_find_ctxtmem(struct kgsl_device *device,
- unsigned int pt_base, unsigned int gpuaddr, unsigned int size);
+ phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size);
void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain,
int hang);
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index dd9bdc3..b0a1fe8 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1364,8 +1364,9 @@
drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
/* blank out gmem shadow. */
- kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
- drawctxt->context_gmem_shadow.size);
+ kgsl_sharedmem_set(drawctxt->dev_priv->device,
+ &drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
+ drawctxt->context_gmem_shadow.size);
/* build quad vertex buffer */
build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
@@ -1388,7 +1389,7 @@
kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
KGSL_CACHE_OP_FLUSH);
- kgsl_cffdump_syncmem(NULL,
+ kgsl_cffdump_syncmem(drawctxt->dev_priv,
&drawctxt->context_gmem_shadow.gmemshadow,
drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
drawctxt->context_gmem_shadow.gmemshadow.size, false);
@@ -1414,8 +1415,8 @@
if (ret)
return ret;
- kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0,
- _context_size(adreno_dev));
+ kgsl_sharedmem_set(drawctxt->dev_priv->device, &drawctxt->gpustate, 0,
+ 0, _context_size(adreno_dev));
tmp_ctx.cmd = tmp_ctx.start
= (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
@@ -1439,7 +1440,7 @@
kgsl_cache_range_op(&drawctxt->gpustate,
KGSL_CACHE_OP_FLUSH);
- kgsl_cffdump_syncmem(NULL, &drawctxt->gpustate,
+ kgsl_cffdump_syncmem(drawctxt->dev_priv, &drawctxt->gpustate,
drawctxt->gpustate.gpuaddr,
drawctxt->gpustate.size, false);
@@ -1515,7 +1516,7 @@
"Current active context has caused gpu hang\n");
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
- kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
context->reg_save[1],
context->reg_save[2] << 2, true);
/* save registers and constants. */
@@ -1524,7 +1525,8 @@
context->reg_save, 3);
if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
- kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ kgsl_cffdump_syncmem(context->dev_priv,
+ &context->gpustate,
context->shader_save[1],
context->shader_save[2] << 2, true);
/* save shader partitioning and instructions. */
@@ -1532,7 +1534,8 @@
KGSL_CMD_FLAGS_PMODE,
context->shader_save, 3);
- kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ kgsl_cffdump_syncmem(context->dev_priv,
+ &context->gpustate,
context->shader_fixup[1],
context->shader_fixup[2] << 2, true);
/*
@@ -1549,7 +1552,7 @@
if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
(context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
- kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
context->context_gmem_shadow.gmem_save[1],
context->context_gmem_shadow.gmem_save[2] << 2, true);
/* save gmem.
@@ -1559,7 +1562,7 @@
KGSL_CMD_FLAGS_PMODE,
context->context_gmem_shadow.gmem_save, 3);
- kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
context->chicken_restore[1],
context->chicken_restore[2] << 2, true);
@@ -1603,7 +1606,7 @@
* (note: changes shader. shader must not already be restored.)
*/
if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
- kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
context->context_gmem_shadow.gmem_restore[1],
context->context_gmem_shadow.gmem_restore[2] << 2,
true);
@@ -1613,7 +1616,8 @@
context->context_gmem_shadow.gmem_restore, 3);
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
- kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ kgsl_cffdump_syncmem(context->dev_priv,
+ &context->gpustate,
context->chicken_restore[1],
context->chicken_restore[2] << 2, true);
@@ -1627,7 +1631,7 @@
}
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
- kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
context->reg_restore[1],
context->reg_restore[2] << 2, true);
@@ -1637,7 +1641,8 @@
/* restore shader instructions & partitioning. */
if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
- kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ kgsl_cffdump_syncmem(context->dev_priv,
+ &context->gpustate,
context->shader_restore[1],
context->shader_restore[2] << 2, true);
@@ -1862,54 +1867,56 @@
cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-19);
- GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 18));
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT,
+ 18));
/* All fields present (bits 9:0) */
- GSL_RB_WRITE(cmds, cmds_gpu, 0x000003ff);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x000003ff);
/* Disable/Enable Real-Time Stream processing (present but ignored) */
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
/* Enable (2D <-> 3D) implicit synchronization (present but ignored) */
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
- GSL_RB_WRITE(cmds, cmds_gpu,
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu,
SUBBLOCK_OFFSET(REG_RB_SURFACE_INFO));
- GSL_RB_WRITE(cmds, cmds_gpu,
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu,
SUBBLOCK_OFFSET(REG_PA_SC_WINDOW_OFFSET));
- GSL_RB_WRITE(cmds, cmds_gpu,
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu,
SUBBLOCK_OFFSET(REG_VGT_MAX_VTX_INDX));
- GSL_RB_WRITE(cmds, cmds_gpu,
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu,
SUBBLOCK_OFFSET(REG_SQ_PROGRAM_CNTL));
- GSL_RB_WRITE(cmds, cmds_gpu,
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu,
SUBBLOCK_OFFSET(REG_RB_DEPTHCONTROL));
- GSL_RB_WRITE(cmds, cmds_gpu,
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu,
SUBBLOCK_OFFSET(REG_PA_SU_POINT_SIZE));
- GSL_RB_WRITE(cmds, cmds_gpu,
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu,
SUBBLOCK_OFFSET(REG_PA_SC_LINE_CNTL));
- GSL_RB_WRITE(cmds, cmds_gpu,
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu,
SUBBLOCK_OFFSET(REG_PA_SU_POLY_OFFSET_FRONT_SCALE));
/* Instruction memory size: */
- GSL_RB_WRITE(cmds, cmds_gpu,
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu,
(adreno_encode_istore_size(adreno_dev)
| adreno_dev->pix_shader_start));
/* Maximum Contexts */
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000001);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000001);
/* Write Confirm Interval and The CP will wait the
* wait_interval * 16 clocks between polling */
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
/* NQ and External Memory Swap */
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
/* Protected mode error checking
* If iommu is used then protection needs to be turned off
* to enable context bank switching */
if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype())
- GSL_RB_WRITE(cmds, cmds_gpu, 0);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0);
else
- GSL_RB_WRITE(cmds, cmds_gpu, GSL_RB_PROTECTED_MODE_CONTROL);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu,
+ GSL_RB_PROTECTED_MODE_CONTROL);
/* Disable header dumping and Header dump address */
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
/* Header dump size */
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
adreno_ringbuffer_submit(rb);
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 1cdc87a..884b72b 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2360,7 +2360,8 @@
if (ret)
return ret;
- kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0, CONTEXT_SIZE);
+ kgsl_sharedmem_set(&adreno_dev->dev, &drawctxt->gpustate, 0, 0,
+ CONTEXT_SIZE);
tmp_ctx.cmd = drawctxt->gpustate.hostptr + CMD_OFFSET;
if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
@@ -2419,7 +2420,7 @@
* already be saved.)
*/
- kgsl_cffdump_syncmem(NULL,
+ kgsl_cffdump_syncmem(context->dev_priv,
&context->gpustate,
context->context_gmem_shadow.gmem_save[1],
context->context_gmem_shadow.gmem_save[2] << 2, true);
@@ -2461,7 +2462,7 @@
*/
if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
- kgsl_cffdump_syncmem(NULL,
+ kgsl_cffdump_syncmem(context->dev_priv,
&context->gpustate,
context->context_gmem_shadow.gmem_restore[1],
context->context_gmem_shadow.gmem_restore[2] << 2,
@@ -2509,25 +2510,26 @@
cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint) * (rb->wptr - 18);
- GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 17));
- GSL_RB_WRITE(cmds, cmds_gpu, 0x000003f7);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000080);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000100);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000180);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00006600);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000150);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x0000014e);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000154);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000001);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu,
+ cp_type3_packet(CP_ME_INIT, 17));
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x000003f7);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000080);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000100);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000180);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00006600);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000150);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x0000014e);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000154);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000001);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
/* Protected mode control - turned off for A3XX */
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
- GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
adreno_ringbuffer_submit(rb);
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 980ff13..12b9e7c 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -19,27 +19,12 @@
#include "kgsl.h"
#include "adreno.h"
+#include "kgsl_cffdump.h"
#include "a2xx_reg.h"
unsigned int kgsl_cff_dump_enable;
-static int kgsl_cff_dump_enable_set(void *data, u64 val)
-{
-#ifdef CONFIG_MSM_KGSL_CFF_DUMP
- kgsl_cff_dump_enable = (val != 0);
- return 0;
-#else
- return -EINVAL;
-#endif
-}
-
-static int kgsl_cff_dump_enable_get(void *data, u64 *val)
-{
- *val = kgsl_cff_dump_enable;
- return 0;
-}
-
DEFINE_SIMPLE_ATTRIBUTE(kgsl_cff_dump_enable_fops, kgsl_cff_dump_enable_get,
kgsl_cff_dump_enable_set, "%llu\n");
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 176717d..b32cdae 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -192,19 +192,20 @@
drawctxt->type =
(*flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT;
+ drawctxt->dev_priv = context->dev_priv;
ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
if (ret)
goto err;
- kgsl_sharedmem_writel(&device->memstore,
+ kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(drawctxt->id, ref_wait_ts),
KGSL_INIT_REFTIMESTAMP);
- kgsl_sharedmem_writel(&device->memstore,
+ kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(drawctxt->id, ts_cmp_enable), 0);
- kgsl_sharedmem_writel(&device->memstore,
+ kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(drawctxt->id, soptimestamp), 0);
- kgsl_sharedmem_writel(&device->memstore,
+ kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(drawctxt->id, eoptimestamp), 0);
context->devctxt = drawctxt;
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index f0f3b6b..2b8e600 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -131,6 +131,7 @@
struct kgsl_memdesc constant_load_commands[3];
struct kgsl_memdesc cond_execs[4];
struct kgsl_memdesc hlsqcontrol_restore_commands[1];
+ struct kgsl_device_private *dev_priv;
};
int adreno_drawctxt_create(struct kgsl_device *device,
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 2249907..c7b6b5b 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -190,8 +190,9 @@
}
}
-static void dump_ib(struct kgsl_device *device, char* buffId, uint32_t pt_base,
- uint32_t base_offset, uint32_t ib_base, uint32_t ib_size, bool dump)
+static void dump_ib(struct kgsl_device *device, char *buffId,
+ phys_addr_t pt_base, uint32_t base_offset, uint32_t ib_base,
+ uint32_t ib_size, bool dump)
{
uint8_t *base_addr = adreno_convertaddr(device, pt_base,
ib_base, ib_size*sizeof(uint32_t));
@@ -214,7 +215,7 @@
uint32_t offsets[IB_LIST_SIZE];
};
-static void dump_ib1(struct kgsl_device *device, uint32_t pt_base,
+static void dump_ib1(struct kgsl_device *device, phys_addr_t pt_base,
uint32_t base_offset,
uint32_t ib1_base, uint32_t ib1_size,
struct ib_list *ib_list, bool dump)
@@ -719,7 +720,7 @@
{
unsigned int cp_ib1_base, cp_ib1_bufsz;
unsigned int cp_ib2_base, cp_ib2_bufsz;
- unsigned int pt_base, cur_pt_base;
+ phys_addr_t pt_base, cur_pt_base;
unsigned int cp_rb_base, cp_rb_ctrl, rb_count;
unsigned int cp_rb_wptr, cp_rb_rptr;
unsigned int i;
@@ -862,20 +863,20 @@
&device->mmu, 0,
KGSL_IOMMU_CONTEXT_USER,
KGSL_IOMMU_CTX_TTBR0), 1))) {
- KGSL_LOG_DUMP(device, "Current pagetable: %x\t"
- "pagetable base: %x\n",
+ KGSL_LOG_DUMP(device,
+ "Current pagetable: %x\t pagetable base: %pa\n",
kgsl_mmu_get_ptname_from_ptbase(&device->mmu,
cur_pt_base),
- cur_pt_base);
+ &cur_pt_base);
/* Set cur_pt_base to the new pagetable base */
cur_pt_base = rb_copy[read_idx++];
- KGSL_LOG_DUMP(device, "New pagetable: %x\t"
- "pagetable base: %x\n",
+ KGSL_LOG_DUMP(device,
+ "New pagetable: %x\t pagetable base: %pa\n",
kgsl_mmu_get_ptname_from_ptbase(&device->mmu,
cur_pt_base),
- cur_pt_base);
+ &cur_pt_base);
}
}
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 61ea916..4e95e93 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -76,7 +76,8 @@
cmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr;
cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*rb->wptr;
- GSL_RB_WRITE(cmds, cmds_gpu, cp_nop_packet(nopcount));
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu,
+ cp_nop_packet(nopcount));
/* Make sure that rptr is not 0 before submitting
* commands at the end of ringbuffer. We do not
@@ -331,10 +332,10 @@
if (rb->flags & KGSL_FLAGS_STARTED)
return 0;
- kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0,
+ kgsl_sharedmem_set(rb->device, &rb->memptrs_desc, 0, 0,
sizeof(struct kgsl_rbmemptrs));
- kgsl_sharedmem_set(&rb->buffer_desc, 0, 0xAA,
+ kgsl_sharedmem_set(rb->device, &rb->buffer_desc, 0, 0xAA,
(rb->sizedwords << 2));
if (adreno_is_a2xx(adreno_dev)) {
@@ -612,12 +613,13 @@
rcmd_gpu = rb->buffer_desc.gpuaddr
+ sizeof(uint)*(rb->wptr-total_sizedwords);
- GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_nop_packet(1));
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER);
if (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE) {
- GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_INTERNAL_IDENTIFIER);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_nop_packet(1));
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
+ KGSL_CMD_INTERNAL_IDENTIFIER);
}
/* always increment the global timestamp. once. */
@@ -636,32 +638,35 @@
timestamp = rb->timestamp[context_id];
/* scratchpad ts for fault tolerance */
- GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
+ cp_type0_packet(REG_CP_TIMESTAMP, 1));
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
+ rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
/* start-of-pipeline timestamp */
- GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_MEM_WRITE, 2));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
+ cp_type3_packet(CP_MEM_WRITE, 2));
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (gpuaddr +
KGSL_MEMSTORE_OFFSET(context_id, soptimestamp)));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, timestamp);
if (flags & KGSL_CMD_FLAGS_PMODE) {
/* disable protected mode error checking */
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type3_packet(CP_SET_PROTECTED_MODE, 1));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, 0);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0);
}
for (i = 0; i < sizedwords; i++) {
- GSL_RB_WRITE(ringcmds, rcmd_gpu, *cmds);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, *cmds);
cmds++;
}
if (flags & KGSL_CMD_FLAGS_PMODE) {
/* re-enable protected mode error checking */
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type3_packet(CP_SET_PROTECTED_MODE, 1));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, 1);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 1);
}
/* HW Workaround for MMU Page fault
@@ -669,9 +674,9 @@
* GPU completes it.
*/
if (adreno_is_a2xx(adreno_dev)) {
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type3_packet(CP_WAIT_FOR_IDLE, 1));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0x00);
}
if (adreno_is_a3xx(adreno_dev)) {
@@ -680,12 +685,13 @@
* resources pending for indirect loads after the timestamp
*/
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type3_packet(CP_EVENT_WRITE, 1));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x07); /* HLSQ_FLUSH */
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds,
+ rcmd_gpu, 0x07); /* HLSQ_FLUSH */
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type3_packet(CP_WAIT_FOR_IDLE, 1));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0x00);
}
/*
@@ -693,62 +699,64 @@
* enabled, then context_id will be KGSL_MEMSTORE_GLOBAL so all
* eop timestamps will work out.
*/
- GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 3));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
- GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
+ cp_type3_packet(CP_EVENT_WRITE, 3));
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (gpuaddr +
KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp)));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, timestamp);
if (KGSL_MEMSTORE_GLOBAL != context_id) {
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type3_packet(CP_MEM_WRITE, 2));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (gpuaddr +
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
eoptimestamp)));
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
}
if (adreno_is_a20x(adreno_dev)) {
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type3_packet(CP_EVENT_WRITE, 1));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, CACHE_FLUSH);
}
if (context) {
/* Conditional execution based on memory values */
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type3_packet(CP_COND_EXEC, 4));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (gpuaddr +
KGSL_MEMSTORE_OFFSET(
context_id, ts_cmp_enable)) >> 2);
- GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (gpuaddr +
KGSL_MEMSTORE_OFFSET(
context_id, ref_wait_ts)) >> 2);
- GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, timestamp);
/* # of conditional command DWORDs */
- GSL_RB_WRITE(ringcmds, rcmd_gpu, 8);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 8);
/* Clear the ts_cmp_enable for the context */
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type3_packet(CP_MEM_WRITE, 2));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, gpuaddr +
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, gpuaddr +
KGSL_MEMSTORE_OFFSET(
context_id, ts_cmp_enable));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x0);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0x0);
/* Clear the ts_cmp_enable for the global timestamp */
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type3_packet(CP_MEM_WRITE, 2));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, gpuaddr +
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, gpuaddr +
KGSL_MEMSTORE_OFFSET(
KGSL_MEMSTORE_GLOBAL, ts_cmp_enable));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x0);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0x0);
/* Trigger the interrupt */
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type3_packet(CP_INTERRUPT, 1));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, CP_INT_CNTL__RB_INT_MASK);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
+ CP_INT_CNTL__RB_INT_MASK);
}
/*
@@ -758,24 +766,25 @@
if ((context) && (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) &&
(flags & (KGSL_CMD_FLAGS_INTERNAL_ISSUE |
KGSL_CMD_FLAGS_GET_INT))) {
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type3_packet(CP_INTERRUPT, 1));
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
CP_INT_CNTL__RB_INT_MASK);
}
if (adreno_is_a3xx(adreno_dev)) {
/* Dummy set-constant to trigger context rollover */
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
cp_type3_packet(CP_SET_CONSTANT, 2));
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
(0x4<<16)|(A3XX_HLSQ_CL_KERNEL_GROUP_X_REG - 0x2000));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, 0);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0);
}
if (flags & KGSL_CMD_FLAGS_EOF) {
- GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1));
- GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_END_OF_FRAME_IDENTIFIER);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_nop_packet(1));
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
+ KGSL_END_OF_FRAME_IDENTIFIER);
}
adreno_ringbuffer_submit(rb);
@@ -1150,7 +1159,8 @@
if (val[i] == cp_nop_packet(4)) {
temp_rb_rptr = adreno_ringbuffer_dec_wrapped(
temp_rb_rptr, size);
- kgsl_sharedmem_writel(&rb->buffer_desc,
+ kgsl_sharedmem_writel(rb->device,
+ &rb->buffer_desc,
temp_rb_rptr, cp_nop_packet(1));
}
KGSL_FT_INFO(rb->device,
@@ -1312,7 +1322,7 @@
ringcmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr;
rcmd_gpu = rb->buffer_desc.gpuaddr + sizeof(unsigned int) * rb->wptr;
for (i = 0; i < num_rb_contents; i++)
- GSL_RB_WRITE(ringcmds, rcmd_gpu, rb_buff[i]);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, rb_buff[i]);
rb->wptr += num_rb_contents;
adreno_ringbuffer_submit(rb);
}
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index e563ec7..115533e 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -60,11 +60,11 @@
};
-#define GSL_RB_WRITE(ring, gpuaddr, data) \
+#define GSL_RB_WRITE(device, ring, gpuaddr, data) \
do { \
*ring = data; \
wmb(); \
- kgsl_cffdump_setmem(gpuaddr, data, 4); \
+ kgsl_cffdump_setmem(device, gpuaddr, data, 4); \
ring++; \
gpuaddr += sizeof(uint); \
} while (0)
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index 144c3d6..d6ce298 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -34,7 +34,7 @@
static struct kgsl_snapshot_obj {
int type;
uint32_t gpuaddr;
- uint32_t ptbase;
+ phys_addr_t ptbase;
void *ptr;
int dwords;
} objbuf[SNAPSHOT_OBJ_BUFSIZE];
@@ -43,7 +43,8 @@
static int objbufptr;
/* Push a new buffer object onto the list */
-static void push_object(struct kgsl_device *device, int type, uint32_t ptbase,
+static void push_object(struct kgsl_device *device, int type,
+ phys_addr_t ptbase,
uint32_t gpuaddr, int dwords)
{
int index;
@@ -94,7 +95,7 @@
* to be dumped
*/
-static int find_object(int type, unsigned int gpuaddr, unsigned int ptbase)
+static int find_object(int type, unsigned int gpuaddr, phys_addr_t ptbase)
{
int index;
@@ -184,7 +185,7 @@
};
static int ib_parse_load_state(struct kgsl_device *device, unsigned int *pkt,
- unsigned int ptbase)
+ phys_addr_t ptbase)
{
unsigned int block, source, type;
int ret = 0;
@@ -243,7 +244,7 @@
*/
static int ib_parse_set_bin_data(struct kgsl_device *device, unsigned int *pkt,
- unsigned int ptbase)
+ phys_addr_t ptbase)
{
int ret;
@@ -276,7 +277,7 @@
*/
static int ib_parse_mem_write(struct kgsl_device *device, unsigned int *pkt,
- unsigned int ptbase)
+ phys_addr_t ptbase)
{
int ret;
@@ -307,7 +308,7 @@
*/
static int ib_parse_draw_indx(struct kgsl_device *device, unsigned int *pkt,
- unsigned int ptbase)
+ phys_addr_t ptbase)
{
int ret = 0, i;
@@ -439,7 +440,7 @@
*/
static int ib_parse_type3(struct kgsl_device *device, unsigned int *ptr,
- unsigned int ptbase)
+ phys_addr_t ptbase)
{
int opcode = cp_type3_opcode(*ptr);
@@ -464,7 +465,7 @@
*/
static void ib_parse_type0(struct kgsl_device *device, unsigned int *ptr,
- unsigned int ptbase)
+ phys_addr_t ptbase)
{
int size = type0_pkt_size(*ptr);
int offset = type0_pkt_offset(*ptr);
@@ -542,12 +543,12 @@
}
}
-static inline int parse_ib(struct kgsl_device *device, unsigned int ptbase,
+static inline int parse_ib(struct kgsl_device *device, phys_addr_t ptbase,
unsigned int gpuaddr, unsigned int dwords);
/* Add an IB as a GPU object, but first, parse it to find more goodies within */
-static int ib_add_gpu_object(struct kgsl_device *device, unsigned int ptbase,
+static int ib_add_gpu_object(struct kgsl_device *device, phys_addr_t ptbase,
unsigned int gpuaddr, unsigned int dwords)
{
int i, ret, rem = dwords;
@@ -625,7 +626,7 @@
* access the dynamic data from the sysfs file. Push all other IBs on the
* dynamic list
*/
-static inline int parse_ib(struct kgsl_device *device, unsigned int ptbase,
+static inline int parse_ib(struct kgsl_device *device, phys_addr_t ptbase,
unsigned int gpuaddr, unsigned int dwords)
{
unsigned int ib1base, ib2base;
@@ -657,7 +658,8 @@
unsigned int *data = snapshot + sizeof(*header);
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
- unsigned int ptbase, rptr, *rbptr, ibbase;
+ unsigned int rptr, *rbptr, ibbase;
+ phys_addr_t ptbase;
int index, size, i;
int parse_ibs = 0, ib_parse_start;
@@ -824,7 +826,7 @@
struct kgsl_snapshot_replay_mem_list *header = snapshot;
struct kgsl_process_private *private = NULL;
struct kgsl_process_private *tmp_private;
- unsigned int ptbase;
+ phys_addr_t ptbase;
struct rb_node *node;
struct kgsl_mem_entry *entry = NULL;
int num_mem;
@@ -861,7 +863,7 @@
return 0;
}
header->num_entries = num_mem;
- header->ptbase = ptbase;
+ header->ptbase = (__u32)ptbase;
/*
* Walk throught the memory list and store the
* tuples(gpuaddr, size, memtype) in snapshot
@@ -897,7 +899,7 @@
/* Write the sub-header for the section */
header->gpuaddr = obj->gpuaddr;
- header->ptbase = obj->ptbase;
+ header->ptbase = (__u32)obj->ptbase;
header->size = obj->dwords;
/* Write the contents of the ib */
@@ -957,8 +959,9 @@
int hang)
{
int i;
- uint32_t ptbase, ibbase, ibsize;
+ uint32_t ibbase, ibsize;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ phys_addr_t ptbase;
/* Reset the list of objects */
objbufptr = 0;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 9b67c61..94754be 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -154,8 +154,8 @@
*/
struct kgsl_mem_entry * __must_check
-kgsl_get_mem_entry(struct kgsl_device *device, unsigned int ptbase,
- unsigned int gpuaddr, unsigned int size)
+kgsl_get_mem_entry(struct kgsl_device *device,
+ phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size)
{
struct kgsl_process_private *priv;
struct kgsl_mem_entry *entry;
@@ -814,6 +814,27 @@
return private;
}
+int kgsl_close_device(struct kgsl_device *device)
+{
+ int result = 0;
+ device->open_count--;
+ if (device->open_count == 0) {
+ BUG_ON(device->active_cnt > 1);
+ result = device->ftbl->stop(device);
+ kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
+ /*
+ * active_cnt special case: we just stopped the device,
+ * so no need to use kgsl_active_count_put()
+ */
+ device->active_cnt--;
+ } else {
+ kgsl_active_count_put(device);
+ }
+ return result;
+
+}
+EXPORT_SYMBOL(kgsl_close_device);
+
static int kgsl_release(struct inode *inodep, struct file *filep)
{
int result = 0;
@@ -833,8 +854,10 @@
if (context == NULL)
break;
- if (context->dev_priv == dev_priv)
+ if (context->dev_priv == dev_priv) {
kgsl_context_detach(context);
+ context->dev_priv = NULL;
+ }
next = next + 1;
}
@@ -846,19 +869,7 @@
*/
kgsl_cancel_events(device, dev_priv);
- device->open_count--;
- if (device->open_count == 0) {
- BUG_ON(device->active_cnt > 1);
- result = device->ftbl->stop(device);
- kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
- /*
- * active_cnt special case: we just stopped the device,
- * so no need to use kgsl_active_count_put()
- */
- device->active_cnt--;
- } else {
- kgsl_active_count_put(device);
- }
+ result = kgsl_close_device(device);
mutex_unlock(&device->mutex);
kfree(dev_priv);
@@ -868,6 +879,43 @@
return result;
}
+int kgsl_open_device(struct kgsl_device *device)
+{
+ int result = 0;
+ if (device->open_count == 0) {
+ /*
+ * active_cnt special case: we are starting up for the first
+ * time, so use this sequence instead of the kgsl_pwrctrl_wake()
+ * which will be called by kgsl_active_count_get().
+ */
+ device->active_cnt++;
+ kgsl_sharedmem_set(device, &device->memstore, 0, 0,
+ device->memstore.size);
+
+ result = device->ftbl->init(device);
+ if (result)
+ goto err;
+
+ result = device->ftbl->start(device);
+ if (result)
+ goto err;
+ /*
+ * Make sure the gates are open, so they don't block until
+ * we start suspend or FT.
+ */
+ complete_all(&device->ft_gate);
+ complete_all(&device->hwaccess_gate);
+ kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
+ kgsl_active_count_put(device);
+ }
+ device->open_count++;
+err:
+ if (result)
+ device->active_cnt--;
+ return result;
+}
+EXPORT_SYMBOL(kgsl_open_device);
+
static int kgsl_open(struct inode *inodep, struct file *filep)
{
int result;
@@ -905,33 +953,9 @@
mutex_lock(&device->mutex);
- if (device->open_count == 0) {
- /*
- * active_cnt special case: we are starting up for the first
- * time, so use this sequence instead of the kgsl_pwrctrl_wake()
- * which will be called by kgsl_active_count_get().
- */
- device->active_cnt++;
- kgsl_sharedmem_set(&device->memstore, 0, 0,
- device->memstore.size);
-
- result = device->ftbl->init(device);
- if (result)
- goto err_freedevpriv;
-
- result = device->ftbl->start(device);
- if (result)
- goto err_freedevpriv;
- /*
- * Make sure the gates are open, so they don't block until
- * we start suspend or FT.
- */
- complete_all(&device->ft_gate);
- complete_all(&device->hwaccess_gate);
- kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE);
- kgsl_active_count_put(device);
- }
- device->open_count++;
+ result = kgsl_open_device(device);
+ if (result)
+ goto err_freedevpriv;
mutex_unlock(&device->mutex);
/*
@@ -959,11 +983,9 @@
kgsl_pwrctrl_enable(device);
result = device->ftbl->stop(device);
kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
+ device->active_cnt--;
}
err_freedevpriv:
- /* only the first open takes an active count */
- if (device->open_count == 0)
- device->active_cnt--;
mutex_unlock(&device->mutex);
filep->private_data = NULL;
kfree(dev_priv);
@@ -2438,7 +2460,8 @@
int result = 0;
struct kgsl_cff_user_event *param = data;
- kgsl_cffdump_user_event(param->cff_opcode, param->op1, param->op2,
+ kgsl_cffdump_user_event(dev_priv->device, param->cff_opcode,
+ param->op1, param->op2,
param->op3, param->op4, param->op5);
return result;
@@ -3309,7 +3332,7 @@
BUG_ON(device == NULL);
- kgsl_cffdump_hang(device->id);
+ kgsl_cffdump_hang(device);
/* For a manual dump, make sure that the system is idle */
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index de3f619..4a1f291 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -207,7 +207,7 @@
int kgsl_postmortem_dump(struct kgsl_device *device, int manual);
struct kgsl_mem_entry *kgsl_get_mem_entry(struct kgsl_device *device,
- unsigned int ptbase, unsigned int gpuaddr, unsigned int size);
+ phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size);
struct kgsl_mem_entry *kgsl_sharedmem_find_region(
struct kgsl_process_private *private, unsigned int gpuaddr,
@@ -238,6 +238,10 @@
unsigned int timestamp, unsigned int flags,
int result, unsigned int type);
+int kgsl_open_device(struct kgsl_device *device);
+
+int kgsl_close_device(struct kgsl_device *device);
+
#ifdef CONFIG_MSM_KGSL_DRM
extern int kgsl_drm_init(struct platform_device *dev);
extern void kgsl_drm_exit(void);
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index c3bdf80..99f4235 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -335,8 +335,6 @@
return;
}
- kgsl_cff_dump_enable = 0;
-
spin_lock_init(&cffdump_lock);
dir = debugfs_create_dir("cff", debugfs_dir);
@@ -360,53 +358,54 @@
void kgsl_cffdump_open(struct kgsl_device *device)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- if (!kgsl_cff_dump_enable)
+ if (!device->cff_dump_enable)
return;
if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) {
- kgsl_cffdump_memory_base(device->id,
+ kgsl_cffdump_memory_base(device,
KGSL_PAGETABLE_BASE,
KGSL_IOMMU_GLOBAL_MEM_BASE +
KGSL_IOMMU_GLOBAL_MEM_SIZE -
KGSL_PAGETABLE_BASE,
adreno_dev->gmem_size);
} else {
- kgsl_cffdump_memory_base(device->id,
+ kgsl_cffdump_memory_base(device,
kgsl_mmu_get_base_addr(&device->mmu),
kgsl_mmu_get_ptsize(&device->mmu),
adreno_dev->gmem_size);
}
}
-void kgsl_cffdump_memory_base(enum kgsl_deviceid device_id, unsigned int base,
+void kgsl_cffdump_memory_base(struct kgsl_device *device, unsigned int base,
unsigned int range, unsigned gmemsize)
{
- if (!kgsl_cff_dump_enable)
+ if (!device->cff_dump_enable)
return;
- cffdump_printline(device_id, CFF_OP_MEMORY_BASE, base,
+ cffdump_printline(device->id, CFF_OP_MEMORY_BASE, base,
range, gmemsize, 0, 0);
}
-void kgsl_cffdump_hang(enum kgsl_deviceid device_id)
+void kgsl_cffdump_hang(struct kgsl_device *device)
{
- if (!kgsl_cff_dump_enable)
+ if (!device->cff_dump_enable)
return;
- cffdump_printline(device_id, CFF_OP_HANG, 0, 0, 0, 0, 0);
+ cffdump_printline(device->id, CFF_OP_HANG, 0, 0, 0, 0, 0);
}
-void kgsl_cffdump_close(enum kgsl_deviceid device_id)
+void kgsl_cffdump_close(struct kgsl_device *device)
{
- if (!kgsl_cff_dump_enable)
+ if (!device->cff_dump_enable)
return;
- cffdump_printline(device_id, CFF_OP_EOF, 0, 0, 0, 0, 0);
+ cffdump_printline(device->id, CFF_OP_EOF, 0, 0, 0, 0, 0);
}
-void kgsl_cffdump_user_event(unsigned int cff_opcode, unsigned int op1,
+void kgsl_cffdump_user_event(struct kgsl_device *device,
+ unsigned int cff_opcode, unsigned int op1,
unsigned int op2, unsigned int op3,
unsigned int op4, unsigned int op5)
{
- if (!kgsl_cff_dump_enable)
+ if (!device->cff_dump_enable)
return;
cffdump_printline(-1, cff_opcode, op1, op2, op3, op4, op5);
}
@@ -415,9 +414,10 @@
struct kgsl_memdesc *memdesc, uint gpuaddr, uint sizebytes,
bool clean_cache)
{
+ struct kgsl_device *device = dev_priv->device;
const void *src;
- if (!kgsl_cff_dump_enable)
+ if (!device->cff_dump_enable)
return;
total_syncmem += sizebytes;
@@ -437,9 +437,9 @@
}
src = (uint *)kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr);
if (memdesc->hostptr == NULL) {
- KGSL_CORE_ERR("no kernel mapping for "
- "gpuaddr: 0x%08x, m->host: 0x%p, phys: 0x%08x\n",
- gpuaddr, memdesc->hostptr, memdesc->physaddr);
+ KGSL_CORE_ERR(
+ "no kernel map for gpuaddr: 0x%08x, m->host: 0x%p, phys: %pa\n",
+ gpuaddr, memdesc->hostptr, &memdesc->physaddr);
return;
}
@@ -465,9 +465,10 @@
0, 0, 0);
}
-void kgsl_cffdump_setmem(uint addr, uint value, uint sizebytes)
+void kgsl_cffdump_setmem(struct kgsl_device *device,
+ uint addr, uint value, uint sizebytes)
{
- if (!kgsl_cff_dump_enable)
+ if (!device || !device->cff_dump_enable)
return;
while (sizebytes > 3) {
@@ -483,37 +484,37 @@
0, 0, 0);
}
-void kgsl_cffdump_regwrite(enum kgsl_deviceid device_id, uint addr,
+void kgsl_cffdump_regwrite(struct kgsl_device *device, uint addr,
uint value)
{
- if (!kgsl_cff_dump_enable)
+ if (!device->cff_dump_enable)
return;
- cffdump_printline(device_id, CFF_OP_WRITE_REG, addr, value,
+ cffdump_printline(device->id, CFF_OP_WRITE_REG, addr, value,
0, 0, 0);
}
-void kgsl_cffdump_regpoll(enum kgsl_deviceid device_id, uint addr,
+void kgsl_cffdump_regpoll(struct kgsl_device *device, uint addr,
uint value, uint mask)
{
- if (!kgsl_cff_dump_enable)
+ if (!device->cff_dump_enable)
return;
- cffdump_printline(device_id, CFF_OP_POLL_REG, addr, value,
+ cffdump_printline(device->id, CFF_OP_POLL_REG, addr, value,
mask, 0, 0);
}
-void kgsl_cffdump_slavewrite(uint addr, uint value)
+void kgsl_cffdump_slavewrite(struct kgsl_device *device, uint addr, uint value)
{
- if (!kgsl_cff_dump_enable)
+ if (!device->cff_dump_enable)
return;
cffdump_printline(-1, CFF_OP_WRITE_REG, addr, value, 0, 0, 0);
}
-int kgsl_cffdump_waitirq(void)
+int kgsl_cffdump_waitirq(struct kgsl_device *device)
{
- if (!kgsl_cff_dump_enable)
+ if (!device->cff_dump_enable)
return 0;
cffdump_printline(-1, CFF_OP_WAIT_IRQ, 0, 0, 0, 0, 0);
@@ -614,3 +615,59 @@
}
}
+int kgsl_cff_dump_enable_set(void *data, u64 val)
+{
+ int ret = 0;
+ struct kgsl_device *device = (struct kgsl_device *)data;
+ int i;
+
+ mutex_lock(&kgsl_driver.devlock);
+ /*
+ * If CFF dump enabled then set active count to prevent device
+ * from restarting because simulator cannot run device restarts
+ */
+ if (val) {
+ /* Check if CFF is on for some other device already */
+ for (i = 0; i < KGSL_DEVICE_MAX; i++) {
+ if (kgsl_driver.devp[i]) {
+ struct kgsl_device *device_temp =
+ kgsl_driver.devp[i];
+ if (device_temp->cff_dump_enable &&
+ device != device_temp) {
+ KGSL_CORE_ERR(
+ "CFF is on for another device %d\n",
+ device_temp->id);
+ ret = -EINVAL;
+ goto done;
+ }
+ }
+ }
+ if (!device->cff_dump_enable) {
+ mutex_lock(&device->mutex);
+ device->cff_dump_enable = 1;
+ ret = kgsl_open_device(device);
+ if (!ret)
+ ret = kgsl_active_count_get(device);
+ if (ret)
+ device->cff_dump_enable = 0;
+ mutex_unlock(&device->mutex);
+ }
+ } else if (device->cff_dump_enable && !val) {
+ mutex_lock(&device->mutex);
+ ret = kgsl_close_device(device);
+ device->cff_dump_enable = 0;
+ mutex_unlock(&device->mutex);
+ }
+done:
+ mutex_unlock(&kgsl_driver.devlock);
+ return ret;
+}
+EXPORT_SYMBOL(kgsl_cff_dump_enable_set);
+
+int kgsl_cff_dump_enable_get(void *data, u64 *val)
+{
+ struct kgsl_device *device = (struct kgsl_device *)data;
+ *val = device->cff_dump_enable;
+ return 0;
+}
+EXPORT_SYMBOL(kgsl_cff_dump_enable_get);
diff --git a/drivers/gpu/msm/kgsl_cffdump.h b/drivers/gpu/msm/kgsl_cffdump.h
index d5656f8..641348e 100644
--- a/drivers/gpu/msm/kgsl_cffdump.h
+++ b/drivers/gpu/msm/kgsl_cffdump.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-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
@@ -14,6 +14,8 @@
#ifndef __KGSL_CFFDUMP_H
#define __KGSL_CFFDUMP_H
+extern unsigned int kgsl_cff_dump_enable;
+
#ifdef CONFIG_MSM_KGSL_CFF_DUMP
#include <linux/types.h>
@@ -23,46 +25,64 @@
void kgsl_cffdump_init(void);
void kgsl_cffdump_destroy(void);
void kgsl_cffdump_open(struct kgsl_device *device);
-void kgsl_cffdump_close(enum kgsl_deviceid device_id);
+void kgsl_cffdump_close(struct kgsl_device *device);
void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
bool clean_cache);
-void kgsl_cffdump_setmem(uint addr, uint value, uint sizebytes);
-void kgsl_cffdump_regwrite(enum kgsl_deviceid device_id, uint addr,
+void kgsl_cffdump_setmem(struct kgsl_device *device, uint addr,
+ uint value, uint sizebytes);
+void kgsl_cffdump_regwrite(struct kgsl_device *device, uint addr,
uint value);
-void kgsl_cffdump_regpoll(enum kgsl_deviceid device_id, uint addr,
+void kgsl_cffdump_regpoll(struct kgsl_device *device, uint addr,
uint value, uint mask);
bool kgsl_cffdump_parse_ibs(struct kgsl_device_private *dev_priv,
const struct kgsl_memdesc *memdesc, uint gpuaddr, int sizedwords,
bool check_only);
-void kgsl_cffdump_user_event(unsigned int cff_opcode, unsigned int op1,
+void kgsl_cffdump_user_event(struct kgsl_device *device,
+ unsigned int cff_opcode, unsigned int op1,
unsigned int op2, unsigned int op3,
unsigned int op4, unsigned int op5);
static inline bool kgsl_cffdump_flags_no_memzero(void) { return true; }
-void kgsl_cffdump_memory_base(enum kgsl_deviceid device_id, unsigned int base,
+void kgsl_cffdump_memory_base(struct kgsl_device *device, unsigned int base,
unsigned int range, unsigned int gmemsize);
-void kgsl_cffdump_hang(enum kgsl_deviceid device_id);
+void kgsl_cffdump_hang(struct kgsl_device *device);
+int kgsl_cff_dump_enable_set(void *data, u64 val);
+int kgsl_cff_dump_enable_get(void *data, u64 *val);
#else
#define kgsl_cffdump_init() (void)0
#define kgsl_cffdump_destroy() (void)0
#define kgsl_cffdump_open(device) (void)0
-#define kgsl_cffdump_close(device_id) (void)0
+#define kgsl_cffdump_close(device) (void)0
#define kgsl_cffdump_syncmem(dev_priv, memdesc, addr, sizebytes, clean_cache) \
(void) 0
-#define kgsl_cffdump_setmem(addr, value, sizebytes) (void)0
-#define kgsl_cffdump_regwrite(device_id, addr, value) (void)0
-#define kgsl_cffdump_regpoll(device_id, addr, value, mask) (void)0
+#define kgsl_cffdump_setmem(device, addr, value, sizebytes) (void)0
+#define kgsl_cffdump_regwrite(device, addr, value) (void)0
+#define kgsl_cffdump_regpoll(device, addr, value, mask) (void)0
#define kgsl_cffdump_parse_ibs(dev_priv, memdesc, gpuaddr, \
sizedwords, check_only) true
#define kgsl_cffdump_flags_no_memzero() true
-#define kgsl_cffdump_memory_base(base, range, gmemsize) (void)0
-#define kgsl_cffdump_hang(device_id) (void)0
-#define kgsl_cffdump_user_event(cff_opcode, op1, op2, op3, op4, op5) \
- (void)param
+#define kgsl_cffdump_memory_base(davice, base, range, gmemsize) (void)0
+#define kgsl_cffdump_hang(device) (void)0
+static inline void kgsl_cffdump_user_event(struct kgsl_device *device,
+ unsigned int cff_opcode, unsigned int op1,
+ unsigned int op2, unsigned int op3,
+ unsigned int op4, unsigned int op5)
+{
+ return;
+}
+static inline int kgsl_cff_dump_enable_set(void *data, u64 val)
+{
+ return -EINVAL;
+}
+
+static inline int kgsl_cff_dump_enable_get(void *data, u64 *val)
+{
+ return -EINVAL;
+}
#endif /* CONFIG_MSM_KGSL_CFF_DUMP */
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 3ee9e4e..6477cbd 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -226,6 +226,7 @@
int pm_ib_enabled;
int reset_counter; /* Track how many GPU core resets have occured */
+ int cff_dump_enable;
};
void kgsl_process_events(struct work_struct *work);
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 6f139b9..68052b1 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -359,7 +359,7 @@
int kgsl_gpummu_pt_equal(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pt,
- unsigned int pt_base)
+ phys_addr_t pt_base)
{
struct kgsl_gpummu_pt *gpummu_pt = pt ? pt->priv : NULL;
return gpummu_pt && pt_base && (gpummu_pt->base.gpuaddr == pt_base);
@@ -458,15 +458,20 @@
if (gpummu_pt->base.hostptr == NULL)
goto err_flushfilter;
+ /* Do a check before truncating phys_addr_t to unsigned 32 */
+ if (sizeof(phys_addr_t) > sizeof(unsigned int)) {
+ WARN_ONCE(1, "Cannot use LPAE with gpummu\n");
+ goto err_flushfilter;
+ }
+ gpummu_pt->base.gpuaddr = gpummu_pt->base.physaddr;
+ gpummu_pt->base.size = KGSL_PAGETABLE_SIZE;
+
/* ptpool allocations are from coherent memory, so update the
device statistics acordingly */
KGSL_STATS_ADD(KGSL_PAGETABLE_SIZE, kgsl_driver.stats.coherent,
kgsl_driver.stats.coherent_max);
- gpummu_pt->base.gpuaddr = gpummu_pt->base.physaddr;
- gpummu_pt->base.size = KGSL_PAGETABLE_SIZE;
-
return (void *)gpummu_pt;
err_flushfilter:
@@ -576,7 +581,7 @@
kgsl_regwrite(device, MH_INTERRUPT_MASK,
GSL_MMU_INT_MASK | MH_INTERRUPT_MASK__MMU_PAGE_FAULT);
- kgsl_sharedmem_set(&mmu->setstate_memory, 0, 0,
+ kgsl_sharedmem_set(device, &mmu->setstate_memory, 0, 0,
mmu->setstate_memory.size);
/* TRAN_ERROR needs a 32 byte (32 byte aligned) chunk of memory
@@ -723,7 +728,7 @@
return 0;
}
-static unsigned int
+static phys_addr_t
kgsl_gpummu_get_current_ptbase(struct kgsl_mmu *mmu)
{
unsigned int ptbase;
@@ -731,7 +736,7 @@
return ptbase;
}
-static unsigned int
+static phys_addr_t
kgsl_gpummu_get_pt_base_addr(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pt)
{
@@ -757,7 +762,7 @@
.mmu_get_pt_base_addr = kgsl_gpummu_get_pt_base_addr,
.mmu_enable_clk = NULL,
.mmu_disable_clk_on_ts = NULL,
- .mmu_get_pt_lsb = NULL,
+ .mmu_get_default_ttbr0 = NULL,
.mmu_get_reg_gpuaddr = NULL,
.mmu_get_reg_ahbaddr = NULL,
.mmu_get_num_iommu_units = kgsl_gpummu_get_num_iommu_units,
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 4fb2f87..b86e0e1 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -609,11 +609,12 @@
*/
static int kgsl_iommu_pt_equal(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pt,
- unsigned int pt_base)
+ phys_addr_t pt_base)
{
struct kgsl_iommu_pt *iommu_pt = pt ? pt->priv : NULL;
- unsigned int domain_ptbase = iommu_pt ?
+ phys_addr_t domain_ptbase = iommu_pt ?
iommu_get_pt_base_addr(iommu_pt->domain) : 0;
+
/* Only compare the valid address bits of the pt_base */
domain_ptbase &= KGSL_IOMMU_CTX_TTBR0_ADDR_MASK;
@@ -1152,7 +1153,7 @@
* Return - actual pagetable address that the ttbr0 register is programmed
* with
*/
-static unsigned int kgsl_iommu_get_pt_base_addr(struct kgsl_mmu *mmu,
+static phys_addr_t kgsl_iommu_get_pt_base_addr(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pt)
{
struct kgsl_iommu_pt *iommu_pt = pt->priv;
@@ -1161,17 +1162,15 @@
}
/*
- * kgsl_iommu_get_pt_lsb - Return the lsb of the ttbr0 IOMMU register
+ * kgsl_iommu_get_default_ttbr0 - Return the ttbr0 value programmed by
+ * iommu driver
* @mmu - Pointer to mmu structure
* @hostptr - Pointer to the IOMMU register map. This is used to match
* the iommu device whose lsb value is to be returned
* @ctx_id - The context bank whose lsb valus is to be returned
- * Return - returns the lsb which is the last 14 bits of the ttbr0 IOMMU
- * register. ttbr0 is the actual PTBR for of the IOMMU. The last 14 bits
- * are only programmed once in the beginning when a domain is attached
- * does not change.
+ * Return - returns the ttbr0 value programmed by iommu driver
*/
-static int kgsl_iommu_get_pt_lsb(struct kgsl_mmu *mmu,
+static phys_addr_t kgsl_iommu_get_default_ttbr0(struct kgsl_mmu *mmu,
unsigned int unit_id,
enum kgsl_iommu_context_id ctx_id)
{
@@ -1182,7 +1181,7 @@
for (j = 0; j < iommu_unit->dev_count; j++)
if (unit_id == i &&
ctx_id == iommu_unit->dev[j].ctx_id)
- return iommu_unit->dev[j].pt_lsb;
+ return iommu_unit->dev[j].default_ttbr0;
}
return 0;
}
@@ -1386,7 +1385,7 @@
/* A nop is required in an indirect buffer when switching
* pagetables in-stream */
- kgsl_sharedmem_writel(&mmu->setstate_memory,
+ kgsl_sharedmem_writel(mmu->device, &mmu->setstate_memory,
KGSL_IOMMU_SETSTATE_NOP_OFFSET,
cp_nop_packet(1));
@@ -1626,18 +1625,26 @@
for (i = 0; i < iommu->unit_count; i++) {
struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i];
for (j = 0; j < iommu_unit->dev_count; j++) {
- iommu_unit->dev[j].pt_lsb = KGSL_IOMMMU_PT_LSB(iommu,
+ if (sizeof(phys_addr_t) > sizeof(unsigned long)) {
+ iommu_unit->dev[j].default_ttbr0 =
+ KGSL_IOMMU_GET_CTX_REG_LL(iommu,
+ iommu_unit,
+ iommu_unit->dev[j].ctx_id,
+ TTBR0);
+ } else {
+ iommu_unit->dev[j].default_ttbr0 =
KGSL_IOMMU_GET_CTX_REG(iommu,
iommu_unit,
iommu_unit->dev[j].ctx_id,
- TTBR0));
+ TTBR0);
+ }
}
}
kgsl_iommu_lock_rb_in_tlb(mmu);
_iommu_unlock();
/* For complete CFF */
- kgsl_cffdump_setmem(mmu->setstate_memory.gpuaddr +
+ kgsl_cffdump_setmem(mmu->device, mmu->setstate_memory.gpuaddr +
KGSL_IOMMU_SETSTATE_NOP_OFFSET,
cp_nop_packet(1), sizeof(unsigned int));
@@ -1806,10 +1813,10 @@
return 0;
}
-static unsigned int
+static phys_addr_t
kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu)
{
- unsigned int pt_base;
+ phys_addr_t pt_base;
struct kgsl_iommu *iommu = mmu->priv;
/* We cannot enable or disable the clocks in interrupt context, this
function is called from interrupt context if there is an axi error */
@@ -1842,16 +1849,14 @@
struct kgsl_iommu *iommu = mmu->priv;
int temp;
int i;
- unsigned int pt_base = kgsl_iommu_get_pt_base_addr(mmu,
+ phys_addr_t pt_base = kgsl_iommu_get_pt_base_addr(mmu,
mmu->hwpagetable);
- unsigned int pt_val;
+ phys_addr_t pt_val;
if (kgsl_iommu_enable_clk(mmu, KGSL_IOMMU_CONTEXT_USER)) {
KGSL_DRV_ERR(mmu->device, "Failed to enable iommu clocks\n");
return;
}
- /* Mask off the lsb of the pt base address since lsb will not change */
- pt_base &= KGSL_IOMMU_CTX_TTBR0_ADDR_MASK;
/* For v0 SMMU GPU needs to be idle for tlb invalidate as well */
if (msm_soc_version_supports_iommu_v0())
@@ -1866,12 +1871,21 @@
for (i = 0; i < iommu->unit_count; i++) {
/* get the lsb value which should not change when
* changing ttbr0 */
- pt_val = kgsl_iommu_get_pt_lsb(mmu, i,
+ pt_val = kgsl_iommu_get_default_ttbr0(mmu, i,
KGSL_IOMMU_CONTEXT_USER);
- pt_val += pt_base;
- KGSL_IOMMU_SET_CTX_REG(iommu, (&iommu->iommu_units[i]),
- KGSL_IOMMU_CONTEXT_USER, TTBR0, pt_val);
+ pt_base &= KGSL_IOMMU_CTX_TTBR0_ADDR_MASK;
+ pt_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK;
+ pt_val |= pt_base;
+ if (sizeof(phys_addr_t) > sizeof(unsigned long)) {
+ KGSL_IOMMU_SET_CTX_REG_LL(iommu,
+ (&iommu->iommu_units[i]),
+ KGSL_IOMMU_CONTEXT_USER, TTBR0, pt_val);
+ } else {
+ KGSL_IOMMU_SET_CTX_REG(iommu,
+ (&iommu->iommu_units[i]),
+ KGSL_IOMMU_CONTEXT_USER, TTBR0, pt_val);
+ }
mb();
temp = KGSL_IOMMU_GET_CTX_REG(iommu,
@@ -1976,7 +1990,7 @@
.mmu_get_current_ptbase = kgsl_iommu_get_current_ptbase,
.mmu_enable_clk = kgsl_iommu_enable_clk,
.mmu_disable_clk_on_ts = kgsl_iommu_disable_clk_on_ts,
- .mmu_get_pt_lsb = kgsl_iommu_get_pt_lsb,
+ .mmu_get_default_ttbr0 = kgsl_iommu_get_default_ttbr0,
.mmu_get_reg_gpuaddr = kgsl_iommu_get_reg_gpuaddr,
.mmu_get_reg_ahbaddr = kgsl_iommu_get_reg_ahbaddr,
.mmu_get_num_iommu_units = kgsl_iommu_get_num_iommu_units,
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
index b1b83c0..53b3946 100644
--- a/drivers/gpu/msm/kgsl_iommu.h
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -47,7 +47,12 @@
#define KGSL_IOMMU_V1_FSYNR0_WNR_SHIFT 4
/* TTBR0 register fields */
+#ifdef CONFIG_ARM_LPAE
+#define KGSL_IOMMU_CTX_TTBR0_ADDR_MASK_LPAE 0x000000FFFFFFFFE0ULL
+#define KGSL_IOMMU_CTX_TTBR0_ADDR_MASK KGSL_IOMMU_CTX_TTBR0_ADDR_MASK_LPAE
+#else
#define KGSL_IOMMU_CTX_TTBR0_ADDR_MASK 0xFFFFC000
+#endif
/* TLBSTATUS register fields */
#define KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE BIT(0)
@@ -102,6 +107,20 @@
#define KGSL_IOMMU_MAX_DEVS_PER_UNIT 2
/* Macros to read/write IOMMU registers */
+#define KGSL_IOMMU_SET_CTX_REG_LL(iommu, iommu_unit, ctx, REG, val) \
+ writell_relaxed(val, \
+ iommu_unit->reg_map.hostptr + \
+ iommu->iommu_reg_list[KGSL_IOMMU_CTX_##REG].reg_offset +\
+ (ctx << KGSL_IOMMU_CTX_SHIFT) + \
+ iommu->ctx_offset)
+
+#define KGSL_IOMMU_GET_CTX_REG_LL(iommu, iommu_unit, ctx, REG) \
+ readl_relaxed( \
+ iommu_unit->reg_map.hostptr + \
+ iommu->iommu_reg_list[KGSL_IOMMU_CTX_##REG].reg_offset +\
+ (ctx << KGSL_IOMMU_CTX_SHIFT) + \
+ iommu->ctx_offset)
+
#define KGSL_IOMMU_SET_CTX_REG(iommu, iommu_unit, ctx, REG, val) \
writel_relaxed(val, \
iommu_unit->reg_map.hostptr + \
@@ -128,8 +147,7 @@
* @dev: Device pointer to iommu context
* @attached: Indicates whether this iommu context is presently attached to
* a pagetable/domain or not
- * @pt_lsb: The LSB of IOMMU_TTBR0 register which is the pagetable
- * register
+ * @default_ttbr0: The TTBR0 value set by iommu driver on start up
* @ctx_id: This iommu units context id. It can be either 0 or 1
* @clk_enabled: If set indicates that iommu clocks of this iommu context
* are on, else the clocks are off
@@ -139,7 +157,7 @@
struct kgsl_iommu_device {
struct device *dev;
bool attached;
- unsigned int pt_lsb;
+ phys_addr_t default_ttbr0;
enum kgsl_iommu_context_id ctx_id;
bool clk_enabled;
struct kgsl_device *kgsldev;
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 3ebfdcd..12a4b25 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -314,7 +314,7 @@
}
int
-kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, unsigned int pt_base)
+kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, phys_addr_t pt_base)
{
struct kgsl_pagetable *pt;
int ptid = -1;
@@ -335,7 +335,7 @@
EXPORT_SYMBOL(kgsl_mmu_get_ptname_from_ptbase);
unsigned int
-kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, unsigned int pt_base,
+kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, phys_addr_t pt_base,
unsigned int addr)
{
struct kgsl_pagetable *pt;
@@ -372,7 +372,7 @@
status = kgsl_allocate_contiguous(&mmu->setstate_memory, PAGE_SIZE);
if (status)
return status;
- kgsl_sharedmem_set(&mmu->setstate_memory, 0, 0,
+ kgsl_sharedmem_set(device, &mmu->setstate_memory, 0, 0,
mmu->setstate_memory.size);
if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type) {
@@ -410,7 +410,8 @@
static void mh_axi_error(struct kgsl_device *device, const char* type)
{
- unsigned int reg, gpu_err, phys_err, pt_base;
+ unsigned int reg, gpu_err, phys_err;
+ phys_addr_t pt_base;
kgsl_regread(device, MH_AXI_ERROR, ®);
pt_base = kgsl_mmu_get_current_ptbase(&device->mmu);
@@ -423,8 +424,8 @@
kgsl_regwrite(device, MH_DEBUG_CTRL, 45);
kgsl_regread(device, MH_DEBUG_DATA, &phys_err);
KGSL_MEM_CRIT(device,
- "axi %s error: %08x pt %08x gpu %08x phys %08x\n",
- type, reg, pt_base, gpu_err, phys_err);
+ "axi %s error: %08x pt %pa gpu %08x phys %08x\n",
+ type, reg, &pt_base, gpu_err, phys_err);
}
void kgsl_mh_intrcallback(struct kgsl_device *device)
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 02cde94..a4fffec 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -139,13 +139,13 @@
void (*mmu_device_setstate) (struct kgsl_mmu *mmu,
uint32_t flags);
void (*mmu_pagefault) (struct kgsl_mmu *mmu);
- unsigned int (*mmu_get_current_ptbase)
+ phys_addr_t (*mmu_get_current_ptbase)
(struct kgsl_mmu *mmu);
void (*mmu_disable_clk_on_ts)
(struct kgsl_mmu *mmu, uint32_t ts, bool ts_valid);
int (*mmu_enable_clk)
(struct kgsl_mmu *mmu, int ctx_id);
- int (*mmu_get_pt_lsb)(struct kgsl_mmu *mmu,
+ phys_addr_t (*mmu_get_default_ttbr0)(struct kgsl_mmu *mmu,
unsigned int unit_id,
enum kgsl_iommu_context_id ctx_id);
unsigned int (*mmu_get_reg_gpuaddr)(struct kgsl_mmu *mmu,
@@ -156,8 +156,8 @@
int (*mmu_get_num_iommu_units)(struct kgsl_mmu *mmu);
int (*mmu_pt_equal) (struct kgsl_mmu *mmu,
struct kgsl_pagetable *pt,
- unsigned int pt_base);
- unsigned int (*mmu_get_pt_base_addr)
+ phys_addr_t pt_base);
+ phys_addr_t (*mmu_get_pt_base_addr)
(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pt);
int (*mmu_setup_pt) (struct kgsl_mmu *mmu,
@@ -228,9 +228,9 @@
void kgsl_setstate(struct kgsl_mmu *mmu, unsigned int context_id,
uint32_t flags);
int kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu,
- unsigned int pt_base);
+ phys_addr_t pt_base);
unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu,
- unsigned int pt_base, unsigned int addr);
+ phys_addr_t pt_base, unsigned int addr);
int kgsl_mmu_pt_get_flags(struct kgsl_pagetable *pt,
enum kgsl_deviceid id);
void kgsl_mmu_ptpool_destroy(void *ptpool);
@@ -246,7 +246,7 @@
* of as wrappers around the actual function
*/
-static inline unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_mmu *mmu)
+static inline phys_addr_t kgsl_mmu_get_current_ptbase(struct kgsl_mmu *mmu)
{
if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_current_ptbase)
return mmu->mmu_ops->mmu_get_current_ptbase(mmu);
@@ -277,7 +277,7 @@
static inline int kgsl_mmu_pt_equal(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pt,
- unsigned int pt_base)
+ phys_addr_t pt_base)
{
if (mmu->mmu_ops && mmu->mmu_ops->mmu_pt_equal)
return mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base);
@@ -285,7 +285,7 @@
return 1;
}
-static inline unsigned int kgsl_mmu_get_pt_base_addr(struct kgsl_mmu *mmu,
+static inline phys_addr_t kgsl_mmu_get_pt_base_addr(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pt)
{
if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_pt_base_addr)
@@ -294,12 +294,13 @@
return 0;
}
-static inline int kgsl_mmu_get_pt_lsb(struct kgsl_mmu *mmu,
+static inline phys_addr_t kgsl_mmu_get_default_ttbr0(struct kgsl_mmu *mmu,
unsigned int unit_id,
enum kgsl_iommu_context_id ctx_id)
{
- if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_pt_lsb)
- return mmu->mmu_ops->mmu_get_pt_lsb(mmu, unit_id, ctx_id);
+ if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_default_ttbr0)
+ return mmu->mmu_ops->mmu_get_default_ttbr0(mmu, unit_id,
+ ctx_id);
else
return 0;
}
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 1691762..01f0768 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -879,7 +879,8 @@
EXPORT_SYMBOL(kgsl_sharedmem_readl);
int
-kgsl_sharedmem_writel(const struct kgsl_memdesc *memdesc,
+kgsl_sharedmem_writel(struct kgsl_device *device,
+ const struct kgsl_memdesc *memdesc,
unsigned int offsetbytes,
uint32_t src)
{
@@ -892,7 +893,8 @@
WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size);
if (offsetbytes + sizeof(uint32_t) > memdesc->size)
return -ERANGE;
- kgsl_cffdump_setmem(memdesc->gpuaddr + offsetbytes,
+ kgsl_cffdump_setmem(device,
+ memdesc->gpuaddr + offsetbytes,
src, sizeof(uint32_t));
dst = (uint32_t *)(memdesc->hostptr + offsetbytes);
*dst = src;
@@ -901,14 +903,16 @@
EXPORT_SYMBOL(kgsl_sharedmem_writel);
int
-kgsl_sharedmem_set(const struct kgsl_memdesc *memdesc, unsigned int offsetbytes,
- unsigned int value, unsigned int sizebytes)
+kgsl_sharedmem_set(struct kgsl_device *device,
+ const struct kgsl_memdesc *memdesc, unsigned int offsetbytes,
+ unsigned int value, unsigned int sizebytes)
{
BUG_ON(memdesc == NULL || memdesc->hostptr == NULL);
BUG_ON(offsetbytes + sizebytes > memdesc->size);
- kgsl_cffdump_setmem(memdesc->gpuaddr + offsetbytes, value,
- sizebytes);
+ kgsl_cffdump_setmem(device,
+ memdesc->gpuaddr + offsetbytes, value,
+ sizebytes);
memset(memdesc->hostptr + offsetbytes, value, sizebytes);
return 0;
}
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 14ae0dc..985b9b8 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -55,11 +55,13 @@
uint32_t *dst,
unsigned int offsetbytes);
-int kgsl_sharedmem_writel(const struct kgsl_memdesc *memdesc,
+int kgsl_sharedmem_writel(struct kgsl_device *device,
+ const struct kgsl_memdesc *memdesc,
unsigned int offsetbytes,
uint32_t src);
-int kgsl_sharedmem_set(const struct kgsl_memdesc *memdesc,
+int kgsl_sharedmem_set(struct kgsl_device *device,
+ const struct kgsl_memdesc *memdesc,
unsigned int offsetbytes, unsigned int value,
unsigned int sizebytes);
@@ -154,7 +156,7 @@
static inline int
memdesc_sg_phys(struct kgsl_memdesc *memdesc,
- unsigned int physaddr, unsigned int size)
+ phys_addr_t physaddr, unsigned int size)
{
memdesc->sg = kgsl_sg_alloc(1);
if (memdesc->sg == NULL)
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 6fcd912..d3edbba 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -27,7 +27,7 @@
struct kgsl_snapshot_object {
unsigned int gpuaddr;
- unsigned int ptbase;
+ phys_addr_t ptbase;
unsigned int size;
unsigned int offset;
int type;
@@ -140,6 +140,7 @@
int hang = (int) priv;
int ctxtcount = 0;
int size = sizeof(*header);
+ phys_addr_t temp_ptbase;
/* Figure out how many active contexts there are - these will
* be appended on the end of the structure */
@@ -181,11 +182,14 @@
kgsl_sharedmem_readl(&device->memstore, &header->current_context,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context));
+
/* Get the current PT base */
- header->ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
+ temp_ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
+ /* Truncate to 32 bits in case LPAE is used */
+ header->ptbase = (__u32)temp_ptbase;
/* And the PID for the task leader */
pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(&device->mmu,
- header->ptbase);
+ temp_ptbase);
task = find_task_by_vpid(pid);
@@ -267,7 +271,7 @@
header.size = ALIGN(obj->size, 4) >> 2;
header.gpuaddr = obj->gpuaddr;
- header.ptbase = obj->ptbase;
+ header.ptbase = (__u32)obj->ptbase;
header.type = obj->type;
ret = obj_itr_out(itr, &header, sizeof(header));
@@ -309,7 +313,7 @@
* Return 1 if the object is already in the list - this can save us from
* having to parse the sme thing over again.
*/
-int kgsl_snapshot_have_object(struct kgsl_device *device, unsigned int ptbase,
+int kgsl_snapshot_have_object(struct kgsl_device *device, phys_addr_t ptbase,
unsigned int gpuaddr, unsigned int size)
{
struct kgsl_snapshot_object *obj;
@@ -339,7 +343,7 @@
* size of the object being frozen
*/
-int kgsl_snapshot_get_object(struct kgsl_device *device, unsigned int ptbase,
+int kgsl_snapshot_get_object(struct kgsl_device *device, phys_addr_t ptbase,
unsigned int gpuaddr, unsigned int size, unsigned int type)
{
struct kgsl_mem_entry *entry;
diff --git a/drivers/gpu/msm/kgsl_snapshot.h b/drivers/gpu/msm/kgsl_snapshot.h
index 4db2815..61a3b22 100644
--- a/drivers/gpu/msm/kgsl_snapshot.h
+++ b/drivers/gpu/msm/kgsl_snapshot.h
@@ -320,10 +320,10 @@
unsigned int data, unsigned int start, unsigned int count);
/* Freeze a GPU buffer so it can be dumped in the snapshot */
-int kgsl_snapshot_get_object(struct kgsl_device *device, unsigned int ptbase,
+int kgsl_snapshot_get_object(struct kgsl_device *device, phys_addr_t ptbase,
unsigned int gpuaddr, unsigned int size, unsigned int type);
-int kgsl_snapshot_have_object(struct kgsl_device *device, unsigned int ptbase,
+int kgsl_snapshot_have_object(struct kgsl_device *device, phys_addr_t ptbase,
unsigned int gpuaddr, unsigned int size);
#endif
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 49265fc..7004ad7 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -467,10 +467,10 @@
addmarker(&z180_dev->ringbuffer, z180_dev->current_timestamp);
/* monkey patch the IB so that it jumps back to the ringbuffer */
- kgsl_sharedmem_writel(&entry->memdesc,
+ kgsl_sharedmem_writel(device, &entry->memdesc,
((sizedwords + 1) * sizeof(unsigned int)),
rb_gpuaddr(z180_dev, z180_dev->current_timestamp));
- kgsl_sharedmem_writel(&entry->memdesc,
+ kgsl_sharedmem_writel(device, &entry->memdesc,
((sizedwords + 2) * sizeof(unsigned int)),
nextcnt);
@@ -710,7 +710,7 @@
BUG_ON(offsetwords*sizeof(uint32_t) >= device->reg_len);
reg = (unsigned int *)(device->reg_virt + (offsetwords << 2));
- kgsl_cffdump_regwrite(device->id, offsetwords << 2, value);
+ kgsl_cffdump_regwrite(device, offsetwords << 2, value);
/*ensure previous writes post before this one,
* i.e. act like normal writel() */
wmb();
diff --git a/drivers/gpu/msm/z180_postmortem.c b/drivers/gpu/msm/z180_postmortem.c
index 55b8faa..5d929cf 100644
--- a/drivers/gpu/msm/z180_postmortem.c
+++ b/drivers/gpu/msm/z180_postmortem.c
@@ -118,7 +118,7 @@
int rb_slot_num = -1;
struct z180_device *z180_dev = Z180_DEVICE(device);
struct kgsl_mem_entry *entry = NULL;
- unsigned int pt_base;
+ phys_addr_t pt_base;
unsigned int i;
unsigned int j;
char linebuf[CHARS_PER_LINE];
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index b8c3c44..bd4344b 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -442,6 +442,45 @@
}
EXPORT_SYMBOL(dvb_dmx_video_pattern_search);
+/**
+ * dvb_dmx_notify_section_event() - Notify demux event for all filters of a
+ * specified section feed.
+ *
+ * @feed: dvb_demux_feed object
+ * @event: demux event to notify
+ * @should_lock: specifies whether the function should lock the demux
+ *
+ * Caller is responsible for locking the demux properly, either by doing the
+ * locking itself and setting 'should_lock' to 0, or have the function do it
+ * by setting 'should_lock' to 1.
+ */
+int dvb_dmx_notify_section_event(struct dvb_demux_feed *feed,
+ struct dmx_data_ready *event, int should_lock)
+{
+ struct dvb_demux_filter *f;
+
+ if (feed == NULL || event == NULL || feed->type != DMX_TYPE_SEC)
+ return -EINVAL;
+
+ if (!should_lock && !spin_is_locked(&feed->demux->lock))
+ return -EINVAL;
+
+ if (should_lock)
+ spin_lock(&feed->demux->lock);
+
+ f = feed->filter;
+ while (f && feed->feed.sec.is_filtering) {
+ feed->data_ready_cb.sec(&f->filter, event);
+ f = f->next;
+ }
+
+ if (should_lock)
+ spin_unlock(&feed->demux->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(dvb_dmx_notify_section_event);
+
static int dvb_dmx_check_pes_end(struct dvb_demux_feed *feed)
{
struct dmx_data_ready data;
@@ -1310,8 +1349,7 @@
dmx_data_ready.scrambling_bits.new_value = scrambling_bits;
if (feed->type == DMX_TYPE_SEC)
- feed->data_ready_cb.sec(&feed->filter->filter,
- &dmx_data_ready);
+ dvb_dmx_notify_section_event(feed, &dmx_data_ready, 0);
else
feed->data_ready_cb.ts(&feed->feed.ts, &dmx_data_ready);
}
@@ -2735,7 +2773,7 @@
struct dvb_demux_feed *feed = (struct dvb_demux_feed *)section_feed;
struct dvb_demux *dvbdmx = feed->demux;
struct dmx_data_ready data;
- int ret;
+ int ret = 0;
data.data_length = 0;
@@ -2760,13 +2798,11 @@
switch (cmd->type) {
case DMX_OOB_CMD_EOS:
data.status = DMX_OK_EOS;
- ret = feed->data_ready_cb.sec(&feed->filter->filter, &data);
break;
case DMX_OOB_CMD_MARKER:
data.status = DMX_OK_MARKER;
data.marker.id = cmd->params.marker.id;
- ret = feed->data_ready_cb.sec(&feed->filter->filter, &data);
break;
default:
@@ -2774,6 +2810,9 @@
break;
}
+ if (!ret)
+ ret = dvb_dmx_notify_section_event(feed, &data, 1);
+
mutex_unlock(&dvbdmx->mutex);
return ret;
}
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index 9fb1a12..aeafa57 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -325,6 +325,8 @@
u64 curr_match_tsp, u64 prev_match_tsp,
u64 curr_pusi_tsp, u64 prev_pusi_tsp);
void dvb_dmx_notify_idx_events(struct dvb_demux_feed *feed);
+int dvb_dmx_notify_section_event(struct dvb_demux_feed *feed,
+ struct dmx_data_ready *event, int should_lock);
/**
* dvb_dmx_is_video_feed - Returns whether the PES feed
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index 88f2f08..74a920c 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -567,11 +567,18 @@
if (buf_state == MSM_ISP_BUFFER_STATE_DIVERTED) {
buf_info = msm_isp_get_buf_ptr(buf_mgr,
info->handle, info->buf_idx);
- if (info->dirty_buf)
- msm_isp_put_buf(buf_mgr, info->handle, info->buf_idx);
- else
- msm_isp_buf_done(buf_mgr, info->handle, info->buf_idx,
- buf_info->tv, buf_info->frame_id);
+ if (info->dirty_buf) {
+ rc = msm_isp_put_buf(buf_mgr,
+ info->handle, info->buf_idx);
+ } else {
+ if (BUF_SRC(bufq->stream_id))
+ pr_err("%s: Invalid native buffer state\n",
+ __func__);
+ else
+ rc = msm_isp_buf_done(buf_mgr,
+ info->handle, info->buf_idx,
+ buf_info->tv, buf_info->frame_id);
+ }
} else {
bufq = msm_isp_get_bufq(buf_mgr, info->handle);
if (BUF_SRC(bufq->stream_id)) {
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 790bbc1..a63fccf 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -4111,7 +4111,7 @@
MPQ_DVB_DBG_PRINT("%s: Notify CRC err event\n", __func__);
event.status = DMX_CRC_ERROR;
event.data_length = 0;
- feed->data_ready_cb.sec(&feed->filter->filter, &event);
+ dvb_dmx_notify_section_event(feed, &event, 1);
}
if (sts->error_indicators & SDMX_FILTER_ERR_D_BUF_FULL)
@@ -4145,12 +4145,7 @@
if (sts->status_indicators & SDMX_FILTER_STATUS_EOS) {
event.data_length = 0;
event.status = DMX_OK_EOS;
- f = feed->filter;
-
- while (f && sec->is_filtering) {
- feed->data_ready_cb.sec(&f->filter, &event);
- f = f->next;
- }
+ dvb_dmx_notify_section_event(feed, &event, 1);
}
}
@@ -4471,10 +4466,12 @@
{
int i;
int j;
+ int sdmx_filters;
struct sdmx_filter_status *sts;
struct mpq_feed *mpq_feed;
- for (i = 0; i < mpq_demux->sdmx_filter_count; i++) {
+ sdmx_filters = mpq_demux->sdmx_filter_count;
+ for (i = 0; i < sdmx_filters; i++) {
/*
* MPQ_TODO: review lookup optimization
* Can have the related mpq_feed index already associated with
@@ -4817,21 +4814,11 @@
event.status = DMX_OK_MARKER;
event.marker.id = cmd->params.marker.id;
- if (feed->type == DMX_TYPE_SEC) {
- struct dvb_demux_filter *f = feed->filter;
- struct dmx_section_feed *sec = &feed->feed.sec;
-
- while (f && sec->is_filtering) {
- ret = feed->data_ready_cb.sec(&f->filter,
- &event);
- if (ret)
- break;
- f = f->next;
- }
- } else {
+ if (feed->type == DMX_TYPE_SEC)
+ ret = dvb_dmx_notify_section_event(feed, &event, 1);
+ else
/* MPQ_TODO: Notify decoder via the stream buffer */
ret = feed->data_ready_cb.ts(&feed->feed.ts, &event);
- }
break;
default:
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index e0fffbd..a395b7c 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -46,6 +46,7 @@
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/string.h>
+#include <mach/msm_bus.h>
/*
* General defines
@@ -437,6 +438,7 @@
struct list_head devlist; /* list of all devices */
struct platform_device *pdev;
void __iomem *base;
+ uint32_t tsif_bus_client;
unsigned int tspp_irq;
unsigned int bam_irq;
u32 bam_handle;
@@ -773,12 +775,24 @@
return -EINVAL;
}
+ if (device->tsif_bus_client) {
+ rc = msm_bus_scale_client_update_request(
+ device->tsif_bus_client, 1);
+ if (rc) {
+ pr_err("tspp: Can't enable bus\n");
+ return -EBUSY;
+ }
+ }
+
if (device->tsif_vreg) {
rc = regulator_set_voltage(device->tsif_vreg,
RPM_REGULATOR_CORNER_SUPER_TURBO,
RPM_REGULATOR_CORNER_SUPER_TURBO);
if (rc) {
pr_err("Unable to set CX voltage.\n");
+ if (device->tsif_bus_client)
+ msm_bus_scale_client_update_request(
+ device->tsif_bus_client, 0);
return rc;
}
}
@@ -791,6 +805,10 @@
RPM_REGULATOR_CORNER_SVS_SOC,
RPM_REGULATOR_CORNER_SUPER_TURBO);
}
+
+ if (device->tsif_bus_client)
+ msm_bus_scale_client_update_request(
+ device->tsif_bus_client, 0);
return -EBUSY;
}
@@ -803,6 +821,10 @@
RPM_REGULATOR_CORNER_SVS_SOC,
RPM_REGULATOR_CORNER_SUPER_TURBO);
}
+
+ if (device->tsif_bus_client)
+ msm_bus_scale_client_update_request(
+ device->tsif_bus_client, 0);
return -EBUSY;
}
@@ -831,6 +853,13 @@
if (rc)
pr_err("Unable to set CX voltage.\n");
}
+
+ if (device->tsif_bus_client) {
+ rc = msm_bus_scale_client_update_request(
+ device->tsif_bus_client, 0);
+ if (rc)
+ pr_err("tspp: Can't disable bus\n");
+ }
}
/*** TSIF functions ***/
@@ -2851,6 +2880,7 @@
struct resource *mem_tspp;
struct resource *mem_bam;
struct tspp_channel *channel;
+ struct msm_bus_scale_pdata *tspp_bus_pdata = NULL;
if (pdev->dev.of_node) {
/* get information from device tree */
@@ -2862,9 +2892,12 @@
pdev->id = -1;
pdev->dev.platform_data = data;
+
+ tspp_bus_pdata = msm_bus_cl_get_pdata(pdev);
} else {
/* must have platform data */
data = pdev->dev.platform_data;
+ tspp_bus_pdata = NULL;
}
if (!data) {
pr_err("tspp: Platform data not available");
@@ -2891,6 +2924,16 @@
device->pdev = pdev;
platform_set_drvdata(pdev, device);
+ /* register bus client */
+ if (tspp_bus_pdata) {
+ device->tsif_bus_client =
+ msm_bus_scale_register_client(tspp_bus_pdata);
+ if (!device->tsif_bus_client)
+ pr_err("tspp: Unable to register bus client\n");
+ } else {
+ device->tsif_bus_client = 0;
+ }
+
/* map regulators */
if (data->tsif_vreg_present) {
device->tsif_vreg = devm_regulator_get(&pdev->dev, "vdd_cx");
@@ -3108,6 +3151,8 @@
if (device->tsif_vreg)
regulator_disable(device->tsif_vreg);
err_regultaor:
+ if (device->tsif_bus_client)
+ msm_bus_scale_unregister_client(device->tsif_bus_client);
kfree(device);
out:
@@ -3143,6 +3188,9 @@
free_irq(device->tsif[i].tsif_irq, &device->tsif[i]);
}
+ if (device->tsif_bus_client)
+ msm_bus_scale_unregister_client(device->tsif_bus_client);
+
wake_lock_destroy(&device->wake_lock);
free_irq(device->tspp_irq, device);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index d872254..3986cdd 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -87,6 +87,10 @@
static int msmsdcc_prep_xfer(struct msmsdcc_host *host, struct mmc_data
*data);
+static void msmsdcc_msm_bus_cancel_work_and_set_vote(struct msmsdcc_host *host,
+ struct mmc_ios *ios);
+static void msmsdcc_msm_bus_queue_work(struct msmsdcc_host *host);
+
static u64 dma_mask = DMA_BIT_MASK(32);
static unsigned int msmsdcc_pwrsave = 1;
@@ -2731,12 +2735,14 @@
int rc = 0;
if (enable && !atomic_read(&host->clks_on)) {
+ msmsdcc_msm_bus_cancel_work_and_set_vote(host, &host->mmc->ios);
+
if (!IS_ERR_OR_NULL(host->bus_clk)) {
rc = clk_prepare_enable(host->bus_clk);
if (rc) {
pr_err("%s: %s: failed to enable the bus-clock with error %d\n",
mmc_hostname(host->mmc), __func__, rc);
- goto out;
+ goto remove_vote;
}
}
if (!IS_ERR(host->pclk)) {
@@ -2764,6 +2770,18 @@
clk_disable_unprepare(host->pclk);
if (!IS_ERR_OR_NULL(host->bus_clk))
clk_disable_unprepare(host->bus_clk);
+
+ /*
+ * If clock gating is enabled, then remove the vote
+ * immediately because clocks will be disabled only
+ * after MSM_MMC_CLK_GATE_DELAY and thus no additional
+ * delay is required to remove the bus vote.
+ */
+ if (host->mmc->clkgate_delay)
+ msmsdcc_msm_bus_cancel_work_and_set_vote(host, NULL);
+ else
+ msmsdcc_msm_bus_queue_work(host);
+
atomic_set(&host->clks_on, 0);
}
goto out;
@@ -2774,6 +2792,8 @@
disable_bus:
if (!IS_ERR_OR_NULL(host->bus_clk))
clk_disable_unprepare(host->bus_clk);
+remove_vote:
+ msmsdcc_msm_bus_cancel_work_and_set_vote(host, NULL);
out:
return rc;
}
@@ -3388,6 +3408,14 @@
(1 + ((3 * USEC_PER_SEC) /
(host->clk_rate ? host->clk_rate :
msmsdcc_get_min_sup_clk_rate(host))));
+ spin_unlock_irqrestore(&host->lock, flags);
+ /*
+ * Update bus vote incase of frequency change due to
+ * clock scaling.
+ */
+ msmsdcc_msm_bus_cancel_work_and_set_vote(host,
+ &mmc->ios);
+ spin_lock_irqsave(&host->lock, flags);
}
/*
* give atleast 2 MCLK cycles delay for clocks
@@ -3625,7 +3653,6 @@
return rc;
}
out:
- msmsdcc_msm_bus_cancel_work_and_set_vote(host, &mmc->ios);
return 0;
}
@@ -3654,7 +3681,6 @@
}
out:
- msmsdcc_msm_bus_queue_work(host);
return rc;
}
#else
@@ -3690,7 +3716,6 @@
msmsdcc_pm_qos_update_latency(host, 0);
return rc;
}
- msmsdcc_msm_bus_cancel_work_and_set_vote(host, &mmc->ios);
return 0;
}
@@ -3713,7 +3738,6 @@
return rc;
}
out:
- msmsdcc_msm_bus_queue_work(host);
return rc;
}
#endif
@@ -6065,6 +6089,17 @@
msmsdcc_get_min_sup_clk_rate(host)));
atomic_set(&host->clks_on, 1);
+
+ ret = msmsdcc_msm_bus_register(host);
+ if (ret)
+ goto clk_disable;
+
+ if (host->msm_bus_vote.client_handle)
+ INIT_DELAYED_WORK(&host->msm_bus_vote.vote_work,
+ msmsdcc_msm_bus_work);
+
+ msmsdcc_msm_bus_cancel_work_and_set_vote(host, &mmc->ios);
+
/* Apply Hard reset to SDCC to put it in power on default state */
msmsdcc_hard_reset(host);
@@ -6077,18 +6112,10 @@
pm_qos_add_request(&host->pm_qos_req_dma,
PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
- ret = msmsdcc_msm_bus_register(host);
- if (ret)
- goto pm_qos_remove;
-
- if (host->msm_bus_vote.client_handle)
- INIT_DELAYED_WORK(&host->msm_bus_vote.vote_work,
- msmsdcc_msm_bus_work);
-
ret = msmsdcc_vreg_init(host, true);
if (ret) {
pr_err("%s: msmsdcc_vreg_init() failed (%d)\n", __func__, ret);
- goto clk_disable;
+ goto pm_qos_remove;
}
@@ -6439,12 +6466,13 @@
msmsdcc_sps_exit(host);
vreg_deinit:
msmsdcc_vreg_init(host, false);
- clk_disable:
- clk_disable_unprepare(host->clk);
- msmsdcc_msm_bus_unregister(host);
pm_qos_remove:
if (host->cpu_dma_latency)
pm_qos_remove_request(&host->pm_qos_req_dma);
+ msmsdcc_msm_bus_cancel_work_and_set_vote(host, NULL);
+ msmsdcc_msm_bus_unregister(host);
+ clk_disable:
+ clk_disable_unprepare(host->clk);
clk_put:
clk_put(host->clk);
pclk_disable:
@@ -6765,8 +6793,13 @@
}
pr_debug("%s: %s: ends with err=%d\n", mmc_hostname(mmc), __func__, rc);
out:
- /* set bus bandwidth to 0 immediately */
- msmsdcc_msm_bus_cancel_work_and_set_vote(host, NULL);
+ /*
+ * Remove the vote immediately only if clocks are off in which
+ * case we might have queued work to remove vote but it may not
+ * be completed before runtime suspend or system suspend.
+ */
+ if (!atomic_read(&host->clks_on))
+ msmsdcc_msm_bus_cancel_work_and_set_vote(host, NULL);
msmsdcc_print_pm_stats(host, start, __func__, rc);
return rc;
}
diff --git a/drivers/spmi/spmi-dbgfs.c b/drivers/spmi/spmi-dbgfs.c
index b825ade..27df09333 100644
--- a/drivers/spmi/spmi-dbgfs.c
+++ b/drivers/spmi/spmi-dbgfs.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
@@ -24,7 +24,6 @@
* /spmi-#
*/
-#define DEBUG
#define pr_fmt(fmt) "%s:%d: " fmt, __func__, __LINE__
#include <linux/kernel.h>
@@ -582,7 +581,7 @@
{
struct dentry *root, *file;
- pr_debug("Creating SPMI debugfs file-system at\n");
+ pr_debug("Creating SPMI debugfs file-system\n");
root = debugfs_create_dir(DFS_ROOT_NAME, NULL);
if (IS_ERR(root)) {
pr_err("Error creating top level directory err:%ld",
@@ -697,6 +696,41 @@
}
/*
+ * spmi_dfs_del_controller: deletes spmi controller entry
+ * @return zero on success
+ */
+int spmi_dfs_del_controller(struct spmi_controller *ctrl)
+{
+ int rc;
+ struct list_head *pos, *tmp;
+ struct spmi_ctrl_data *ctrl_data;
+
+ pr_debug("Deleting controller %s\n", ctrl->dev.kobj.name);
+
+ rc = mutex_lock_interruptible(&dbgfs_data.lock);
+ if (rc)
+ return rc;
+
+ list_for_each_safe(pos, tmp, &dbgfs_data.ctrl) {
+ ctrl_data = list_entry(pos, struct spmi_ctrl_data, node);
+
+ if (ctrl_data->ctrl == ctrl) {
+ debugfs_remove_recursive(ctrl_data->dir);
+ list_del(pos);
+ kfree(ctrl_data);
+ rc = 0;
+ goto done;
+ }
+ }
+ rc = -EINVAL;
+ pr_debug("Unknown controller %s\n", ctrl->dev.kobj.name);
+
+done:
+ mutex_unlock(&dbgfs_data.lock);
+ return rc;
+}
+
+/*
* spmi_dfs_create_file: creates a new file in the SPMI debugfs
* @returns valid dentry pointer on success or NULL
*/
diff --git a/drivers/spmi/spmi-dbgfs.h b/drivers/spmi/spmi-dbgfs.h
index 2a0d815..10e98b9 100644
--- a/drivers/spmi/spmi-dbgfs.h
+++ b/drivers/spmi/spmi-dbgfs.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
@@ -16,8 +16,10 @@
#ifdef CONFIG_DEBUG_FS
int spmi_dfs_add_controller(struct spmi_controller *ctrl);
+int spmi_dfs_del_controller(struct spmi_controller *ctrl);
#else
static int spmi_dfs_add_controller(struct spmi_controller *ctrl) { return 0; }
+static int spmi_dfs_del_controller(struct spmi_controller *ctrl) { return 0; }
#endif
struct dentry *spmi_dfs_create_file(struct spmi_controller *ctrl,
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
index f5c9d2f..fc21fbb 100644
--- a/drivers/spmi/spmi.c
+++ b/drivers/spmi/spmi.c
@@ -32,9 +32,8 @@
static DEFINE_MUTEX(board_lock);
static LIST_HEAD(board_list);
static DEFINE_IDR(ctrl_idr);
-static struct device_type spmi_ctrl_type = { 0 };
-
-#define to_spmi(dev) platform_get_drvdata(to_platform_device(dev))
+static struct device_type spmi_dev_type;
+static struct device_type spmi_ctrl_type;
/* Forward declarations */
struct bus_type spmi_bus_type;
@@ -69,6 +68,9 @@
int id;
int status;
+ if (!ctrl)
+ return -EINVAL;
+
pr_debug("adding controller for bus %d (0x%p)\n", ctrl->nr, ctrl);
if (ctrl->nr & ~MAX_ID_MASK) {
@@ -98,18 +100,70 @@
}
EXPORT_SYMBOL_GPL(spmi_add_controller);
+/* Remove a device associated with a controller */
+static int spmi_ctrl_remove_device(struct device *dev, void *data)
+{
+ struct spmi_device *spmidev = to_spmi_device(dev);
+ struct spmi_controller *ctrl = data;
+
+ if (dev->type == &spmi_dev_type && spmidev->ctrl == ctrl)
+ spmi_remove_device(spmidev);
+
+ return 0;
+}
+
/**
* spmi_del_controller: Controller tear-down.
- * @ctrl: controller to which this device is to be added to.
+ * @ctrl: controller to be removed.
*
* Controller added with the above API is torn down using this API.
*/
int spmi_del_controller(struct spmi_controller *ctrl)
{
- return -ENXIO;
+ struct spmi_controller *found;
+
+ if (!ctrl)
+ return -EINVAL;
+
+ /* Check that the ctrl has been added */
+ mutex_lock(&board_lock);
+ found = idr_find(&ctrl_idr, ctrl->nr);
+ mutex_unlock(&board_lock);
+ if (found != ctrl)
+ return -EINVAL;
+
+ /* Remove all the clients associated with this controller */
+ mutex_lock(&board_lock);
+ bus_for_each_dev(&spmi_bus_type, NULL, ctrl, spmi_ctrl_remove_device);
+ mutex_unlock(&board_lock);
+
+ spmi_dfs_del_controller(ctrl);
+
+ mutex_lock(&board_lock);
+ idr_remove(&ctrl_idr, ctrl->nr);
+ mutex_unlock(&board_lock);
+
+ init_completion(&ctrl->dev_released);
+ device_unregister(&ctrl->dev);
+ wait_for_completion(&ctrl->dev_released);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(spmi_del_controller);
+#define spmi_ctrl_attr_gr NULL
+static void spmi_ctrl_release(struct device *dev)
+{
+ struct spmi_controller *ctrl = to_spmi_controller(dev);
+
+ complete(&ctrl->dev_released);
+}
+
+static struct device_type spmi_ctrl_type = {
+ .groups = spmi_ctrl_attr_gr,
+ .release = spmi_ctrl_release,
+};
+
#define spmi_device_attr_gr NULL
#define spmi_device_uevent NULL
static void spmi_dev_release(struct device *dev)
@@ -141,7 +195,7 @@
{
struct spmi_device *spmidev;
- if (!ctrl) {
+ if (!ctrl || !spmi_busnum_to_ctrl(ctrl->nr)) {
pr_err("Missing SPMI controller\n");
return NULL;
}
@@ -174,12 +228,15 @@
if (dev->bus != &spmi_bus_type || dev->type != &spmi_dev_type)
return NULL;
+ if (!spmidev->ctrl || !spmi_busnum_to_ctrl(spmidev->ctrl->nr))
+ return NULL;
+
return dev;
}
/**
* spmi_add_device: Add a new device without register board info.
- * @ctrl: controller to which this device is to be added to.
+ * @spmi_dev: spmi_device to be added (registered).
*
* Called when device doesn't have an explicit client-driver to be probed, or
* the client-driver is a module installed dynamically.
@@ -190,7 +247,7 @@
struct device *dev = get_valid_device(spmidev);
if (!dev) {
- pr_err("%s: invalid SPMI device\n", __func__);
+ pr_err("invalid SPMI device\n");
return -EINVAL;
}
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 65c9e90..0ff19a2 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -393,7 +393,8 @@
-int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate)
+int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate,
+ int client)
{
int ret = 0;
unsigned long rounded_rate;
@@ -407,6 +408,19 @@
mutex_unlock(&mdp3_res->res_mutex);
return -EINVAL;
}
+ if (clk_type == MDP3_CLK_CORE) {
+ if (client == MDP3_CLIENT_DMA_P) {
+ mdp3_res->dma_core_clk_request = rounded_rate;
+ } else if (client == MDP3_CLIENT_PPP) {
+ mdp3_res->ppp_core_clk_request = rounded_rate;
+ } else {
+ pr_err("unrecognized client=%d\n", client);
+ mutex_unlock(&mdp3_res->res_mutex);
+ return -EINVAL;
+ }
+ rounded_rate = max(mdp3_res->dma_core_clk_request,
+ mdp3_res->ppp_core_clk_request);
+ }
if (rounded_rate != clk_get_rate(clk)) {
ret = clk_set_rate(clk, rounded_rate);
if (ret)
@@ -948,7 +962,7 @@
{
int rc;
rc = mdp3_ctrl_init(mfd);
- rc |= mdp3_ppp_res_init();
+ rc |= mdp3_ppp_res_init(mfd);
return rc;
}
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index e52f7bc..31fcd0e 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -141,7 +141,7 @@
void mdp3_irq_disable(int type);
void mdp3_irq_disable_nosync(int type);
int mdp3_set_intr_callback(u32 type, struct mdp3_intr_cb *cb);
-int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate);
+int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate, int client);
int mdp3_clk_enable(int enable);
int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
int mdp3_put_img(struct mdp3_img_data *data);
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 9c572a5..ce68013 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -130,52 +130,41 @@
return 0;
}
-static int mdp3_ctrl_blit_req(struct msm_fb_data_type *mfd, void __user *p)
+static int mdp3_ctrl_async_blit_req(struct msm_fb_data_type *mfd,
+ void __user *p)
{
- const int MAX_LIST_WINDOW = 16;
- struct mdp_blit_req req_list[MAX_LIST_WINDOW];
- struct mdp_blit_req_list req_list_header;
- int rc, count, i, req_list_count;
+ struct mdp_async_blit_req_list req_list_header;
+ int rc, count;
+ void __user *p_req;
if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
return -EFAULT;
- p += sizeof(req_list_header);
+ p_req = p + sizeof(req_list_header);
count = req_list_header.count;
if (count < 0 || count >= MAX_BLIT_REQ)
return -EINVAL;
- while (count > 0) {
- /*
- * Access the requests through a narrow window to decrease copy
- * overhead and make larger requests accessible to the
- * coherency management code.
- * NOTE: The window size is intended to be larger than the
- * typical request size, but not require more than 2
- * kbytes of stack storage.
- */
- req_list_count = count;
- if (req_list_count > MAX_LIST_WINDOW)
- req_list_count = MAX_LIST_WINDOW;
- if (copy_from_user(&req_list, p,
- sizeof(struct mdp_blit_req)*req_list_count))
- return -EFAULT;
- /*
- * Do the blit DMA, if required -- returning early only if
- * there is a failure.
- */
- for (i = 0; i < req_list_count; i++) {
- if (!(req_list[i].flags & MDP_NO_BLIT)) {
- /* Do the actual blit. */
- rc = mdp3_ppp_start_blit(mfd, &(req_list[i]));
- if (rc)
- return rc;
- }
- }
+ rc = mdp3_ppp_parse_req(p_req, &req_list_header, 1);
+ if (!rc)
+ rc = copy_to_user(p, &req_list_header, sizeof(req_list_header));
+ return rc;
+}
- /* Go to next window of requests. */
- count -= req_list_count;
- p += sizeof(struct mdp_blit_req)*req_list_count;
- }
- return 0;
+static int mdp3_ctrl_blit_req(struct msm_fb_data_type *mfd, void __user *p)
+{
+ struct mdp_async_blit_req_list req_list_header;
+ int rc, count;
+ void __user *p_req;
+
+ if (copy_from_user(&(req_list_header.count), p,
+ sizeof(struct mdp_blit_req_list)))
+ return -EFAULT;
+ p_req = p + sizeof(struct mdp_blit_req_list);
+ count = req_list_header.count;
+ if (count < 0 || count >= MAX_BLIT_REQ)
+ return -EINVAL;
+ req_list_header.sync.acq_fen_fd_cnt = 0;
+ rc = mdp3_ppp_parse_req(p_req, &req_list_header, 0);
+ return rc;
}
static ssize_t mdp3_vsync_show_event(struct device *dev,
@@ -239,8 +228,10 @@
int rc = 0;
if (status) {
- mdp3_clk_set_rate(MDP3_CLK_CORE, MDP_CORE_CLK_RATE);
- mdp3_clk_set_rate(MDP3_CLK_VSYNC, MDP_VSYNC_CLK_RATE);
+ mdp3_clk_set_rate(MDP3_CLK_CORE, MDP_CORE_CLK_RATE,
+ MDP3_CLIENT_DMA_P);
+ mdp3_clk_set_rate(MDP3_CLK_VSYNC, MDP_VSYNC_CLK_RATE,
+ MDP3_CLIENT_DMA_P);
rc = mdp3_clk_enable(true);
if (rc)
@@ -745,6 +736,9 @@
rc = -EFAULT;
}
break;
+ case MSMFB_ASYNC_BLIT:
+ rc = mdp3_ctrl_async_blit_req(mfd, argp);
+ break;
case MSMFB_BLIT:
rc = mdp3_ctrl_blit_req(mfd, argp);
break;
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
index 7164086..3f31932 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.c
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -20,6 +20,8 @@
#include <linux/uaccess.h>
#include <linux/sched.h>
#include <linux/mutex.h>
+#include <linux/sync.h>
+#include <linux/sw_sync.h>
#include "linux/proc_fs.h"
#include "mdss_fb.h"
@@ -28,6 +30,10 @@
#include "mdp3.h"
#define MDP_IS_IMGTYPE_BAD(x) ((x) >= MDP_IMGTYPE_LIMIT)
+#define MDP_BLIT_CLK_RATE 200000000
+#define MDP_PPP_MAX_BPP 4
+#define MDP_PPP_DYNAMIC_FACTOR 3
+#define MDP_PPP_MAX_READ_WRITE 3
static const bool valid_fmt[MDP_IMGTYPE_LIMIT] = {
[MDP_RGB_565] = true,
@@ -47,11 +53,45 @@
[MDP_Y_CRCB_H2V1] = true,
};
+#define MAX_LIST_WINDOW 16
+#define MDP3_PPP_MAX_LIST_REQ 8
+
+struct blit_req_list {
+ int count;
+ struct mdp_blit_req req_list[MAX_LIST_WINDOW];
+ struct mdp3_img_data src_data[MAX_LIST_WINDOW];
+ struct mdp3_img_data dst_data[MAX_LIST_WINDOW];
+ struct sync_fence *acq_fen[MDP_MAX_FENCE_FD];
+ u32 acq_fen_cnt;
+ int cur_rel_fen_fd;
+ struct sync_pt *cur_rel_sync_pt;
+ struct sync_fence *cur_rel_fence;
+ struct sync_fence *last_rel_fence;
+};
+
+struct blit_req_queue {
+ struct blit_req_list req[MDP3_PPP_MAX_LIST_REQ];
+ int count;
+ int push_idx;
+ int pop_idx;
+};
+
struct ppp_status {
int busy;
+ bool wait_for_pop;
spinlock_t ppp_lock;
struct completion ppp_comp;
- struct mutex config_mutex;
+ struct completion pop_q_comp;
+ struct mutex req_mutex; /* Protect request queue */
+ struct mutex config_ppp_mutex; /* Only one client configure register */
+ struct msm_fb_data_type *mfd;
+
+ struct work_struct blit_work;
+ struct blit_req_queue req_q;
+
+ struct sw_sync_timeline *timeline;
+ int timeline_value;
+
};
static struct ppp_status *ppp_stat;
@@ -295,24 +335,22 @@
mdp3_ppp_pipe_wait();
}
-int mdp3_ppp_turnon(struct ppp_blit_op *blit_op, int on_off)
+int mdp3_ppp_turnon(struct msm_fb_data_type *mfd, int on_off)
{
- unsigned long clk_rate = 0, dst_rate = 0, src_rate = 0;
- int ab = 0;
- int ib = 0;
- if (on_off) {
- dst_rate = blit_op->dst.roi.width * blit_op->dst.roi.height;
- src_rate = blit_op->src.roi.width * blit_op->src.roi.height;
- clk_rate = max(dst_rate, src_rate);
- clk_rate = clk_rate * 36 * 12;
+ struct mdss_panel_info *panel_info = mfd->panel_info;
+ int ab = 0, ib = 0;
+ int rate = 0;
- ab = blit_op->dst.roi.width * blit_op->dst.roi.height *
- ppp_bpp(blit_op->dst.color_fmt) * 2 +
- blit_op->src.roi.width * blit_op->src.roi.height *
- ppp_bpp(blit_op->src.color_fmt);
- ab = ab * 120;
+ if (on_off) {
+ rate = MDP_BLIT_CLK_RATE;
+ ab = panel_info->xres * panel_info->yres *
+ panel_info->mipi.frame_rate *
+ MDP_PPP_MAX_BPP *
+ MDP_PPP_DYNAMIC_FACTOR *
+ MDP_PPP_MAX_READ_WRITE;
ib = (ab * 3) / 2;
}
+ mdp3_clk_set_rate(MDP3_CLK_CORE, rate, MDP3_CLIENT_PPP);
mdp3_clk_enable(on_off);
mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib);
return 0;
@@ -322,10 +360,8 @@
{
/* Wait for the pipe to clear */
do { } while (mdp3_ppp_pipe_wait() <= 0);
- mutex_lock(&ppp_stat->config_mutex);
config_ppp_op_mode(blit_op);
mdp3_ppp_kickoff();
- mutex_unlock(&ppp_stat->config_mutex);
}
static void mdp3_ppp_process_req(struct ppp_blit_op *blit_op,
@@ -504,7 +540,7 @@
}
}
-static int mdp3_ppp_blit_addr(struct msm_fb_data_type *mfd,
+static int mdp3_ppp_blit(struct msm_fb_data_type *mfd,
struct mdp_blit_req *req, struct mdp3_img_data *src_data,
struct mdp3_img_data *dst_data)
{
@@ -524,8 +560,6 @@
mdp3_ppp_process_req(&blit_op, req, src_data, dst_data);
- mdp3_ppp_turnon(&blit_op, 1);
-
if (((blit_op.mdp_op & (MDPOP_TRANSP | MDPOP_ALPHAB)) ||
(req->src.format == MDP_ARGB_8888) ||
(req->src.format == MDP_BGRA_8888) ||
@@ -536,41 +570,13 @@
mdp3_start_ppp(&blit_op);
}
- /* MDP cmd block disable */
- mdp3_ppp_turnon(&blit_op, 0);
-
return 0;
}
-static int mdp3_ppp_blit(struct msm_fb_data_type *mfd, struct mdp_blit_req *req)
-{
- struct mdp3_img_data src_data;
- struct mdp3_img_data dst_data;
- int rc;
- mdp3_ppp_iommu_attach();
-
- mdp3_ppp_get_img(&req->src, req, &src_data);
- if (src_data.len == 0) {
- pr_err("mdp_ppp: couldn't retrieve src img from mem\n");
- return -EINVAL;
- }
-
- mdp3_ppp_get_img(&req->dst, req, &dst_data);
- if (dst_data.len == 0) {
- mdp3_put_img(&src_data);
- pr_err("mdp_ppp: couldn't retrieve dest img from mem\n");
- return -EINVAL;
- }
-
- rc = mdp3_ppp_blit_addr(mfd, req, &src_data, &dst_data);
- mdp3_put_img(&src_data);
- mdp3_put_img(&dst_data);
- mdp3_ppp_iommu_dettach();
- return rc;
-}
-
static int mdp3_ppp_blit_workaround(struct msm_fb_data_type *mfd,
- struct mdp_blit_req *req, unsigned int remainder)
+ struct mdp_blit_req *req, unsigned int remainder,
+ struct mdp3_img_data *src_data,
+ struct mdp3_img_data *dst_data)
{
int ret;
struct mdp_blit_req splitreq;
@@ -669,7 +675,7 @@
}
/* No need to split in height */
- ret = mdp3_ppp_blit(mfd, &splitreq);
+ ret = mdp3_ppp_blit(mfd, &splitreq, src_data, dst_data);
if (ret)
return ret;
@@ -698,11 +704,13 @@
}
/* No need to split in height ... just width */
- return mdp3_ppp_blit(mfd, &splitreq);
+ return mdp3_ppp_blit(mfd, &splitreq, src_data, dst_data);
}
int mdp3_ppp_start_blit(struct msm_fb_data_type *mfd,
- struct mdp_blit_req *req)
+ struct mdp_blit_req *req,
+ struct mdp3_img_data *src_data,
+ struct mdp3_img_data *dst_data)
{
int ret;
unsigned int remainder = 0, is_bpp_4 = 0;
@@ -742,19 +750,316 @@
is_bpp_4 = (ret == 4) ? 1 : 0;
if ((is_bpp_4 && (remainder == 6 || remainder == 14)))
- ret = mdp3_ppp_blit_workaround(mfd, req, remainder);
+ ret = mdp3_ppp_blit_workaround(mfd, req, remainder,
+ src_data, dst_data);
else
- ret = mdp3_ppp_blit(mfd, req);
+ ret = mdp3_ppp_blit(mfd, req, src_data, dst_data);
+ mdp3_put_img(src_data);
+ mdp3_put_img(dst_data);
return ret;
}
-int mdp3_ppp_res_init(void)
+void mdp3_ppp_wait_for_fence(struct blit_req_list *req)
{
- ppp_stat = kmalloc(sizeof(struct ppp_status), GFP_KERNEL);
+ int i, ret = 0;
+ /* buf sync */
+ for (i = 0; i < req->acq_fen_cnt; i++) {
+ ret = sync_fence_wait(req->acq_fen[i],
+ WAIT_FENCE_FINAL_TIMEOUT);
+ if (ret < 0) {
+ pr_err("%s: sync_fence_wait failed! ret = %x\n",
+ __func__, ret);
+ break;
+ }
+ sync_fence_put(req->acq_fen[i]);
+ }
+
+ if (ret < 0) {
+ while (i < req->acq_fen_cnt) {
+ sync_fence_put(req->acq_fen[i]);
+ i++;
+ }
+ }
+ req->acq_fen_cnt = 0;
+}
+
+void mdp3_ppp_signal_timeline(struct blit_req_list *req)
+{
+ sw_sync_timeline_inc(ppp_stat->timeline, 1);
+ req->last_rel_fence = req->cur_rel_fence;
+ req->cur_rel_fence = 0;
+}
+
+
+static void mdp3_ppp_deinit_buf_sync(struct blit_req_list *req)
+{
+ int i;
+
+ put_unused_fd(req->cur_rel_fen_fd);
+ sync_fence_put(req->cur_rel_fence);
+ req->cur_rel_fence = NULL;
+ req->cur_rel_fen_fd = 0;
+ ppp_stat->timeline_value--;
+ for (i = 0; i < req->acq_fen_cnt; i++)
+ sync_fence_put(req->acq_fen[i]);
+ req->acq_fen_cnt = 0;
+}
+
+static int mdp3_ppp_handle_buf_sync(struct blit_req_list *req,
+ struct mdp_buf_sync *buf_sync)
+{
+ int i, fence_cnt = 0, ret = 0;
+ int acq_fen_fd[MDP_MAX_FENCE_FD];
+ struct sync_fence *fence;
+
+ if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
+ (ppp_stat->timeline == NULL))
+ return -EINVAL;
+
+ if (buf_sync->acq_fen_fd_cnt)
+ ret = copy_from_user(acq_fen_fd, buf_sync->acq_fen_fd,
+ buf_sync->acq_fen_fd_cnt * sizeof(int));
+ if (ret) {
+ pr_err("%s: copy_from_user failed\n", __func__);
+ return ret;
+ }
+ for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
+ fence = sync_fence_fdget(acq_fen_fd[i]);
+ if (fence == NULL) {
+ pr_info("%s: null fence! i=%d fd=%d\n", __func__, i,
+ acq_fen_fd[i]);
+ ret = -EINVAL;
+ break;
+ }
+ req->acq_fen[i] = fence;
+ }
+ fence_cnt = i;
+ if (ret)
+ goto buf_sync_err_1;
+ req->acq_fen_cnt = fence_cnt;
+ if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
+ mdp3_ppp_wait_for_fence(req);
+
+ req->cur_rel_sync_pt = sw_sync_pt_create(ppp_stat->timeline,
+ ppp_stat->timeline_value++);
+ if (req->cur_rel_sync_pt == NULL) {
+ pr_err("%s: cannot create sync point\n", __func__);
+ ret = -ENOMEM;
+ goto buf_sync_err_2;
+ }
+ /* create fence */
+ req->cur_rel_fence = sync_fence_create("ppp-fence",
+ req->cur_rel_sync_pt);
+ if (req->cur_rel_fence == NULL) {
+ sync_pt_free(req->cur_rel_sync_pt);
+ req->cur_rel_sync_pt = NULL;
+ pr_err("%s: cannot create fence\n", __func__);
+ ret = -ENOMEM;
+ goto buf_sync_err_2;
+ }
+ /* create fd */
+ return ret;
+buf_sync_err_2:
+ ppp_stat->timeline_value--;
+buf_sync_err_1:
+ for (i = 0; i < fence_cnt; i++)
+ sync_fence_put(req->acq_fen[i]);
+ req->acq_fen_cnt = 0;
+ return ret;
+}
+
+void mdp3_ppp_req_push(struct blit_req_queue *req_q, struct blit_req_list *req)
+{
+ int idx = req_q->push_idx;
+ req_q->req[idx] = *req;
+ req_q->count++;
+ req_q->push_idx = (req_q->push_idx + 1) % MDP3_PPP_MAX_LIST_REQ;
+}
+
+struct blit_req_list *mdp3_ppp_next_req(struct blit_req_queue *req_q)
+{
+ struct blit_req_list *req;
+ if (req_q->count == 0)
+ return NULL;
+ req = &req_q->req[req_q->pop_idx];
+ return req;
+}
+
+void mdp3_ppp_req_pop(struct blit_req_queue *req_q)
+{
+ req_q->count--;
+ req_q->pop_idx = (req_q->pop_idx + 1) % MDP3_PPP_MAX_LIST_REQ;
+}
+
+static void mdp3_ppp_blit_wq_handler(struct work_struct *work)
+{
+ struct msm_fb_data_type *mfd = ppp_stat->mfd;
+ struct blit_req_list *req;
+ int i, rc;
+
+ req = mdp3_ppp_next_req(&ppp_stat->req_q);
+ mutex_lock(&ppp_stat->config_ppp_mutex);
+
+ mdp3_ppp_iommu_attach();
+ mdp3_ppp_turnon(mfd, 1);
+ while (req) {
+ mdp3_ppp_wait_for_fence(req);
+ for (i = 0; i < req->count; i++) {
+ if (!(req->req_list[i].flags & MDP_NO_BLIT)) {
+ /* Do the actual blit. */
+ rc = mdp3_ppp_start_blit(mfd,
+ &(req->req_list[i]),
+ &req->src_data[i],
+ &req->dst_data[i]);
+ if (rc)
+ break;
+ }
+ }
+ /* Signal to release fence */
+ mutex_lock(&ppp_stat->req_mutex);
+ mdp3_ppp_signal_timeline(req);
+ mdp3_ppp_req_pop(&ppp_stat->req_q);
+ req = mdp3_ppp_next_req(&ppp_stat->req_q);
+ if (ppp_stat->wait_for_pop)
+ complete(&ppp_stat->pop_q_comp);
+ mutex_unlock(&ppp_stat->req_mutex);
+ }
+ mdp3_ppp_turnon(mfd, 0);
+ mdp3_ppp_iommu_dettach();
+ mutex_unlock(&ppp_stat->config_ppp_mutex);
+}
+
+int mdp3_ppp_parse_req(void __user *p,
+ struct mdp_async_blit_req_list *req_list_header,
+ int async)
+{
+ struct blit_req_list *req;
+ struct blit_req_queue *req_q = &ppp_stat->req_q;
+ struct sync_fence *fence = NULL;
+ int count, rc, idx, i;
+ count = req_list_header->count;
+
+ mutex_lock(&ppp_stat->req_mutex);
+ while (req_q->count >= MDP3_PPP_MAX_LIST_REQ) {
+ ppp_stat->wait_for_pop = true;
+ mutex_unlock(&ppp_stat->req_mutex);
+ rc = wait_for_completion_interruptible_timeout(
+ &ppp_stat->pop_q_comp, 5 * HZ);
+ if (rc == 0) {
+ /* This will only occur if there is serious problem */
+ pr_err("%s: timeout exiting queuing request\n",
+ __func__);
+ return -EBUSY;
+ }
+ mutex_lock(&ppp_stat->req_mutex);
+ ppp_stat->wait_for_pop = false;
+ }
+ idx = req_q->push_idx;
+ req = &req_q->req[idx];
+
+ if (copy_from_user(&req->req_list, p,
+ sizeof(struct mdp_blit_req) * count))
+ return -EFAULT;
+
+ rc = mdp3_ppp_handle_buf_sync(req, &req_list_header->sync);
+ if (rc < 0) {
+ pr_err("%s: Failed create sync point\n", __func__);
+ return rc;
+ }
+ req->count = count;
+
+ /* We need to grab ion handle while client thread */
+ for (i = 0; i < count; i++) {
+ rc = mdp3_ppp_get_img(&req->req_list[i].src,
+ &req->req_list[i], &req->src_data[i]);
+ if (rc < 0 || req->src_data[i].len == 0) {
+ pr_err("mdp_ppp: couldn't retrieve src img from mem\n");
+ goto parse_err_1;
+ }
+
+ rc = mdp3_ppp_get_img(&req->req_list[i].dst,
+ &req->req_list[i], &req->dst_data[i]);
+ if (rc < 0 || req->dst_data[i].len == 0) {
+ mdp3_put_img(&req->src_data[i]);
+ pr_err("mdp_ppp: couldn't retrieve dest img from mem\n");
+ goto parse_err_1;
+ }
+ }
+
+ if (async) {
+ req->cur_rel_fen_fd = get_unused_fd_flags(0);
+ if (req->cur_rel_fen_fd < 0) {
+ pr_err("%s: get_unused_fd_flags failed\n", __func__);
+ rc = -ENOMEM;
+ goto parse_err_2;
+ }
+ sync_fence_install(req->cur_rel_fence, req->cur_rel_fen_fd);
+ rc = copy_to_user(req_list_header->sync.rel_fen_fd,
+ &req->cur_rel_fen_fd, sizeof(int));
+ if (rc) {
+ pr_err("%s:copy_to_user failed\n", __func__);
+ goto parse_err_3;
+ }
+ } else {
+ fence = req->cur_rel_fence;
+ }
+
+ mdp3_ppp_req_push(req_q, req);
+ mutex_unlock(&ppp_stat->req_mutex);
+ schedule_work(&ppp_stat->blit_work);
+ if (!async) {
+ /* wait for release fence */
+ rc = sync_fence_wait(fence,
+ 5 * MSEC_PER_SEC);
+ if (rc < 0)
+ pr_err("%s: sync blit! rc = %x\n", __func__, rc);
+
+ sync_fence_put(fence);
+ fence = NULL;
+ }
+ return 0;
+
+parse_err_3:
+ put_unused_fd(req->cur_rel_fen_fd);
+parse_err_2:
+ sync_fence_put(req->cur_rel_fence);
+ req->cur_rel_fence = NULL;
+ req->cur_rel_fen_fd = 0;
+parse_err_1:
+ for (i--; i >= 0; i--) {
+ mdp3_put_img(&req->src_data[i]);
+ mdp3_put_img(&req->dst_data[i]);
+ }
+ mdp3_ppp_deinit_buf_sync(req);
+ return rc;
+}
+
+int mdp3_ppp_res_init(struct msm_fb_data_type *mfd)
+{
+ const char timeline_name[] = "mdp3_ppp";
+ ppp_stat = kzalloc(sizeof(struct ppp_status), GFP_KERNEL);
+ if (!ppp_stat) {
+ pr_err("%s: kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ /*Setup sync_pt timeline for ppp*/
+ ppp_stat->timeline = sw_sync_timeline_create(timeline_name);
+ if (ppp_stat->timeline == NULL) {
+ pr_err("%s: cannot create time line\n", __func__);
+ return -ENOMEM;
+ } else {
+ ppp_stat->timeline_value = 1;
+ }
+
+ INIT_WORK(&ppp_stat->blit_work, mdp3_ppp_blit_wq_handler);
+ init_completion(&ppp_stat->pop_q_comp);
spin_lock_init(&ppp_stat->ppp_lock);
- mutex_init(&ppp_stat->config_mutex);
+ mutex_init(&ppp_stat->req_mutex);
+ mutex_init(&ppp_stat->config_ppp_mutex);
ppp_stat->busy = false;
+ ppp_stat->mfd = mfd;
mdp3_ppp_callback_setup();
return 0;
}
diff --git a/drivers/video/msm/mdss/mdp3_ppp.h b/drivers/video/msm/mdss/mdp3_ppp.h
index afac419..b4252ca 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.h
+++ b/drivers/video/msm/mdss/mdp3_ppp.h
@@ -18,7 +18,7 @@
#define PPP_WRITEL(val, off) MDP3_REG_WRITE(off, val)
-#define MAX_BLIT_REQ 256
+#define MAX_BLIT_REQ 16
#define PPP_UPSCALE_MAX 64
#define PPP_BLUR_SCALE_MAX 128
#define PPP_LUT_MAX 256
@@ -403,11 +403,12 @@
void ppp_load_x_scale_table(int idx);
void ppp_load_y_scale_table(int idx);
-int mdp3_ppp_start_blit(struct msm_fb_data_type *mfd,
- struct mdp_blit_req *req);
-int mdp3_ppp_res_init(void);
+int mdp3_ppp_res_init(struct msm_fb_data_type *mfd);
int mdp3_ppp_init(void);
int config_ppp_op_mode(struct ppp_blit_op *blit_op);
void ppp_enable(void);
+int mdp3_ppp_parse_req(void __user *p,
+ struct mdp_async_blit_req_list *req_list_header,
+ int async);
#endif
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 58fb5c1..6d41c13 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -78,6 +78,7 @@
#define MSMFB_METADATA_GET _IOW(MSMFB_IOCTL_MAGIC, 166, struct msmfb_metadata)
#define MSMFB_WRITEBACK_SET_MIRRORING_HINT _IOW(MSMFB_IOCTL_MAGIC, 167, \
unsigned int)
+#define MSMFB_ASYNC_BLIT _IOW(MSMFB_IOCTL_MAGIC, 168, unsigned int)
#define FB_TYPE_3D_PANEL 0x10101010
#define MDP_IMGTYPE2_START 0x10000
@@ -766,6 +767,12 @@
int *rel_fen_fd;
};
+struct mdp_async_blit_req_list {
+ struct mdp_buf_sync sync;
+ uint32_t count;
+ struct mdp_blit_req req[];
+};
+
#define MDP_DISPLAY_COMMIT_OVERLAY 1
struct mdp_buf_fence {
uint32_t flags;
diff --git a/include/linux/spmi.h b/include/linux/spmi.h
index 25d937a..e8e932e 100644
--- a/include/linux/spmi.h
+++ b/include/linux/spmi.h
@@ -54,6 +54,7 @@
struct spmi_controller {
struct device dev;
unsigned int nr;
+ struct completion dev_released;
int (*cmd)(struct spmi_controller *, u8 opcode, u8 sid);
int (*read_cmd)(struct spmi_controller *,
u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf);