diff options
Diffstat (limited to 'drivers/gpu/msm')
| -rw-r--r-- | drivers/gpu/msm/adreno-gpulist.h | 18 | ||||
| -rw-r--r-- | drivers/gpu/msm/adreno.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/msm/adreno.h | 4 | ||||
| -rw-r--r-- | drivers/gpu/msm/adreno_a5xx.c | 40 | ||||
| -rw-r--r-- | drivers/gpu/msm/adreno_a5xx_snapshot.c | 119 | ||||
| -rw-r--r-- | drivers/gpu/msm/adreno_dispatch.c | 12 | ||||
| -rw-r--r-- | drivers/gpu/msm/adreno_dispatch.h | 5 | ||||
| -rw-r--r-- | drivers/gpu/msm/kgsl.c | 28 | ||||
| -rw-r--r-- | drivers/gpu/msm/kgsl.h | 5 | ||||
| -rw-r--r-- | drivers/gpu/msm/kgsl_device.h | 6 | ||||
| -rw-r--r-- | drivers/gpu/msm/kgsl_pwrctrl.c | 6 |
11 files changed, 171 insertions, 74 deletions
diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h index 4ec04001ae7e..bc3f794555a5 100644 --- a/drivers/gpu/msm/adreno-gpulist.h +++ b/drivers/gpu/msm/adreno-gpulist.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2007-2018, 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 @@ -300,6 +300,22 @@ static const struct adreno_gpu_core adreno_gpulist[] = { .busy_mask = 0xFFFFFFFE, }, { + .gpurev = ADRENO_REV_A509, + .core = 5, + .major = 0, + .minor = 9, + .patchid = ANY_ID, + .features = ADRENO_PREEMPTION | ADRENO_64BIT | + ADRENO_CONTENT_PROTECTION | ADRENO_CPZ_RETENTION, + .pm4fw_name = "a530_pm4.fw", + .pfpfw_name = "a530_pfp.fw", + .zap_name = "a512_zap", + .gpudev = &adreno_a5xx_gpudev, + .gmem_size = (SZ_256K + SZ_16K), + .num_protected_regs = 0x20, + .busy_mask = 0xFFFFFFFE, + }, + { .gpurev = ADRENO_REV_A508, .core = 5, .major = 0, diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index f96a7a2cee21..7af2af483f10 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -2839,6 +2839,8 @@ static const struct kgsl_functable adreno_functable = { .clk_set_options = adreno_clk_set_options, .gpu_model = adreno_gpu_model, .stop_fault_timer = adreno_dispatcher_stop_fault_timer, + .dispatcher_halt = adreno_dispatcher_halt, + .dispatcher_unhalt = adreno_dispatcher_unhalt, }; static struct platform_driver adreno_platform_driver = { diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 305163147c1a..9ea50007ec38 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2018, 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 @@ -170,6 +170,7 @@ enum adreno_gpurev { ADRENO_REV_A505 = 505, ADRENO_REV_A506 = 506, ADRENO_REV_A508 = 508, + ADRENO_REV_A509 = 509, ADRENO_REV_A510 = 510, ADRENO_REV_A512 = 512, ADRENO_REV_A530 = 530, @@ -1007,6 +1008,7 @@ static inline int adreno_is_a5xx(struct adreno_device *adreno_dev) ADRENO_TARGET(a505, ADRENO_REV_A505) ADRENO_TARGET(a506, ADRENO_REV_A506) ADRENO_TARGET(a508, ADRENO_REV_A508) +ADRENO_TARGET(a509, ADRENO_REV_A509) ADRENO_TARGET(a510, ADRENO_REV_A510) ADRENO_TARGET(a512, ADRENO_REV_A512) ADRENO_TARGET(a530, ADRENO_REV_A530) diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c index 2b8c593076cb..4daf1fad6ee1 100644 --- a/drivers/gpu/msm/adreno_a5xx.c +++ b/drivers/gpu/msm/adreno_a5xx.c @@ -59,6 +59,7 @@ static const struct adreno_vbif_platform a5xx_vbif_platforms[] = { { adreno_is_a530, a530_vbif }, { adreno_is_a512, a540_vbif }, { adreno_is_a510, a530_vbif }, + { adreno_is_a509, a540_vbif }, { adreno_is_a508, a530_vbif }, { adreno_is_a505, a530_vbif }, { adreno_is_a506, a530_vbif }, @@ -161,6 +162,7 @@ static const struct { { adreno_is_a530, a530_efuse_speed_bin }, { adreno_is_a505, a530_efuse_speed_bin }, { adreno_is_a512, a530_efuse_speed_bin }, + { adreno_is_a509, a530_efuse_speed_bin }, { adreno_is_a508, a530_efuse_speed_bin }, }; @@ -201,7 +203,8 @@ static void a5xx_platform_setup(struct adreno_device *adreno_dev) gpudev->vbif_xin_halt_ctrl0_mask = A510_VBIF_XIN_HALT_CTRL0_MASK; } else if (adreno_is_a540(adreno_dev) || - adreno_is_a512(adreno_dev)) { + adreno_is_a512(adreno_dev) || + adreno_is_a509(adreno_dev)) { gpudev->snapshot_data->sect_sizes->cp_merciu = 1024; } @@ -539,7 +542,8 @@ static void a5xx_regulator_disable(struct adreno_device *adreno_dev) unsigned int reg; struct kgsl_device *device = KGSL_DEVICE(adreno_dev); - if (adreno_is_a512(adreno_dev) || adreno_is_a508(adreno_dev)) + if (adreno_is_a512(adreno_dev) || adreno_is_a509(adreno_dev) || + adreno_is_a508(adreno_dev)) return; /* If feature is not supported or not enabled */ @@ -1199,6 +1203,7 @@ static const struct { { adreno_is_a540, a540_hwcg_regs, ARRAY_SIZE(a540_hwcg_regs) }, { adreno_is_a530, a530_hwcg_regs, ARRAY_SIZE(a530_hwcg_regs) }, { adreno_is_a512, a512_hwcg_regs, ARRAY_SIZE(a512_hwcg_regs) }, + { adreno_is_a509, a512_hwcg_regs, ARRAY_SIZE(a512_hwcg_regs) }, { adreno_is_a510, a510_hwcg_regs, ARRAY_SIZE(a510_hwcg_regs) }, { adreno_is_a505, a50x_hwcg_regs, ARRAY_SIZE(a50x_hwcg_regs) }, { adreno_is_a506, a50x_hwcg_regs, ARRAY_SIZE(a50x_hwcg_regs) }, @@ -1376,31 +1381,27 @@ static int _execute_reg_sequence(struct adreno_device *adreno_dev, /* todo double check the reg writes */ while ((cur - opcode) < length) { - switch (cur[0]) { - /* Write a 32 bit value to a 64 bit reg */ - case 1: + if (cur[0] == 1 && (length - (cur - opcode) >= 4)) { + /* Write a 32 bit value to a 64 bit reg */ reg = cur[2]; reg = (reg << 32) | cur[1]; kgsl_regwrite(KGSL_DEVICE(adreno_dev), reg, cur[3]); cur += 4; - break; - /* Write a 64 bit value to a 64 bit reg */ - case 2: + } else if (cur[0] == 2 && (length - (cur - opcode) >= 5)) { + /* Write a 64 bit value to a 64 bit reg */ reg = cur[2]; reg = (reg << 32) | cur[1]; val = cur[4]; val = (val << 32) | cur[3]; kgsl_regwrite(KGSL_DEVICE(adreno_dev), reg, val); cur += 5; - break; - /* Delay for X usec */ - case 3: + } else if (cur[0] == 3 && (length - (cur - opcode) >= 2)) { + /* Delay for X usec */ udelay(cur[1]); cur += 2; - break; - default: + } else return -EINVAL; - } } + } return 0; } @@ -1655,7 +1656,7 @@ static void a5xx_clk_set_options(struct adreno_device *adreno_dev, { if (!adreno_is_a540(adreno_dev) && !adreno_is_a512(adreno_dev) && - !adreno_is_a508(adreno_dev)) + !adreno_is_a508(adreno_dev) && !adreno_is_a509(adreno_dev)) return; /* Handle clock settings for GFX PSCBCs */ @@ -1961,7 +1962,8 @@ static void a5xx_start(struct adreno_device *adreno_dev) kgsl_regwrite(device, A5XX_CP_MERCIU_SIZE, 0x20); kgsl_regwrite(device, A5XX_CP_ROQ_THRESHOLDS_2, 0x40000030); kgsl_regwrite(device, A5XX_CP_ROQ_THRESHOLDS_1, 0x20100D0A); - } else if (adreno_is_a540(adreno_dev) || adreno_is_a512(adreno_dev)) { + } else if (adreno_is_a540(adreno_dev) || adreno_is_a512(adreno_dev) || + adreno_is_a509(adreno_dev)) { kgsl_regwrite(device, A5XX_CP_MEQ_THRESHOLDS, 0x40); kgsl_regwrite(device, A5XX_CP_MERCIU_SIZE, 0x400); kgsl_regwrite(device, A5XX_CP_ROQ_THRESHOLDS_2, 0x80000060); @@ -1980,7 +1982,8 @@ static void a5xx_start(struct adreno_device *adreno_dev) if (adreno_is_a505_or_a506(adreno_dev) || adreno_is_a508(adreno_dev)) kgsl_regwrite(device, A5XX_PC_DBG_ECO_CNTL, (0x100 << 11 | 0x100 << 22)); - else if (adreno_is_a510(adreno_dev) || adreno_is_a512(adreno_dev)) + else if (adreno_is_a510(adreno_dev) || adreno_is_a512(adreno_dev) || + adreno_is_a509(adreno_dev)) kgsl_regwrite(device, A5XX_PC_DBG_ECO_CNTL, (0x200 << 11 | 0x200 << 22)); else @@ -2073,7 +2076,8 @@ static void a5xx_start(struct adreno_device *adreno_dev) kgsl_regwrite(device, A5XX_TPL1_MODE_CNTL, bit << 7); kgsl_regwrite(device, A5XX_RB_MODE_CNTL, bit << 1); if (adreno_is_a540(adreno_dev) || - adreno_is_a512(adreno_dev)) + adreno_is_a512(adreno_dev) || + adreno_is_a509(adreno_dev)) kgsl_regwrite(device, A5XX_UCHE_DBG_ECO_CNTL_2, bit); } diff --git a/drivers/gpu/msm/adreno_a5xx_snapshot.c b/drivers/gpu/msm/adreno_a5xx_snapshot.c index 49560d704537..fb4cebe2cf40 100644 --- a/drivers/gpu/msm/adreno_a5xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a5xx_snapshot.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, 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 @@ -410,6 +410,15 @@ static const unsigned int a5xx_registers[] = { 0xEC00, 0xEC05, 0xEC08, 0xECE9, 0xECF0, 0xECF0, /* VPC CTX 1 */ 0xEA80, 0xEA80, 0xEA82, 0xEAA3, 0xEAA5, 0xEAC2, +}; + +/* + * GPMU registers to dump for A5XX on snapshot. + * Registers in pairs - first value is the start offset, second + * is the stop offset (inclusive) + */ + +static const unsigned int a5xx_gpmu_registers[] = { /* GPMU */ 0xA800, 0xA8FF, 0xAC60, 0xAC60, }; @@ -662,24 +671,23 @@ static size_t a5xx_snapshot_pre_crashdump_regs(struct kgsl_device *device, return kgsl_snapshot_dump_registers(device, buf, remain, &pre_cdregs); } +struct registers { + const unsigned int *regs; + size_t size; +}; + static size_t a5xx_legacy_snapshot_registers(struct kgsl_device *device, - u8 *buf, size_t remain) + u8 *buf, size_t remain, const unsigned int *regs, size_t size) { - struct kgsl_snapshot_registers regs = { - .regs = a5xx_registers, - .count = ARRAY_SIZE(a5xx_registers) / 2, + struct kgsl_snapshot_registers snapshot_regs = { + .regs = regs, + .count = size / 2, }; - return kgsl_snapshot_dump_registers(device, buf, remain, ®s); + return kgsl_snapshot_dump_registers(device, buf, remain, + &snapshot_regs); } -static struct cdregs { - const unsigned int *regs; - unsigned int size; -} _a5xx_cd_registers[] = { - { a5xx_registers, ARRAY_SIZE(a5xx_registers) }, -}; - #define REG_PAIR_COUNT(_a, _i) \ (((_a)[(2 * (_i)) + 1] - (_a)[2 * (_i)]) + 1) @@ -689,11 +697,13 @@ static size_t a5xx_snapshot_registers(struct kgsl_device *device, u8 *buf, struct kgsl_snapshot_regs *header = (struct kgsl_snapshot_regs *)buf; unsigned int *data = (unsigned int *)(buf + sizeof(*header)); unsigned int *src = (unsigned int *) registers.hostptr; - unsigned int i, j, k; + struct registers *regs = (struct registers *)priv; + unsigned int j, k; unsigned int count = 0; if (crash_dump_valid == false) - return a5xx_legacy_snapshot_registers(device, buf, remain); + return a5xx_legacy_snapshot_registers(device, buf, remain, + regs->regs, regs->size); if (remain < sizeof(*header)) { SNAPSHOT_ERR_NOMEM(device, "REGISTERS"); @@ -702,24 +712,20 @@ static size_t a5xx_snapshot_registers(struct kgsl_device *device, u8 *buf, remain -= sizeof(*header); - for (i = 0; i < ARRAY_SIZE(_a5xx_cd_registers); i++) { - struct cdregs *regs = &_a5xx_cd_registers[i]; + for (j = 0; j < regs->size / 2; j++) { + unsigned int start = regs->regs[2 * j]; + unsigned int end = regs->regs[(2 * j) + 1]; - for (j = 0; j < regs->size / 2; j++) { - unsigned int start = regs->regs[2 * j]; - unsigned int end = regs->regs[(2 * j) + 1]; - - if (remain < ((end - start) + 1) * 8) { - SNAPSHOT_ERR_NOMEM(device, "REGISTERS"); - goto out; - } + if (remain < ((end - start) + 1) * 8) { + SNAPSHOT_ERR_NOMEM(device, "REGISTERS"); + goto out; + } - remain -= ((end - start) + 1) * 8; + remain -= ((end - start) + 1) * 8; - for (k = start; k <= end; k++, count++) { - *data++ = k; - *data++ = *src++; - } + for (k = start; k <= end; k++, count++) { + *data++ = k; + *data++ = *src++; } } @@ -859,6 +865,7 @@ void a5xx_snapshot(struct adreno_device *adreno_dev, struct adreno_snapshot_data *snap_data = gpudev->snapshot_data; unsigned int reg, i; struct adreno_ringbuffer *rb; + struct registers regs; /* Disable Clock gating temporarily for the debug bus to work */ a5xx_hwcg_set(adreno_dev, false); @@ -875,8 +882,20 @@ void a5xx_snapshot(struct adreno_device *adreno_dev, /* Try to run the crash dumper */ _a5xx_do_crashdump(device); - kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, - snapshot, a5xx_snapshot_registers, NULL); + regs.regs = a5xx_registers; + regs.size = ARRAY_SIZE(a5xx_registers); + + kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, snapshot, + a5xx_snapshot_registers, ®s); + + if (ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) { + regs.regs = a5xx_gpmu_registers; + regs.size = ARRAY_SIZE(a5xx_gpmu_registers); + + kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, + snapshot, a5xx_snapshot_registers, ®s); + } + /* Dump SP TP HLSQ registers */ kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS, snapshot, @@ -1033,17 +1052,23 @@ void a5xx_crashdump_init(struct adreno_device *adreno_dev) * To save the registers, we need 16 bytes per register pair for the * script and a dword for each register int the data */ - for (i = 0; i < ARRAY_SIZE(_a5xx_cd_registers); i++) { - struct cdregs *regs = &_a5xx_cd_registers[i]; + /* Each pair needs 16 bytes (2 qwords) */ + script_size += (ARRAY_SIZE(a5xx_registers) / 2) * 16; + + /* Each register needs a dword in the data */ + for (j = 0; j < ARRAY_SIZE(a5xx_registers) / 2; j++) + data_size += REG_PAIR_COUNT(a5xx_registers, j) * + sizeof(unsigned int); + + if (ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) { /* Each pair needs 16 bytes (2 qwords) */ - script_size += (regs->size / 2) * 16; + script_size += (ARRAY_SIZE(a5xx_gpmu_registers) / 2) * 16; /* Each register needs a dword in the data */ - for (j = 0; j < regs->size / 2; j++) - data_size += REG_PAIR_COUNT(regs->regs, j) * + for (j = 0; j < ARRAY_SIZE(a5xx_gpmu_registers) / 2; j++) + data_size += REG_PAIR_COUNT(a5xx_gpmu_registers, j) * sizeof(unsigned int); - } /* @@ -1081,13 +1106,21 @@ void a5xx_crashdump_init(struct adreno_device *adreno_dev) ptr = (uint64_t *) capturescript.hostptr; /* For the registers, program a read command for each pair */ - for (i = 0; i < ARRAY_SIZE(_a5xx_cd_registers); i++) { - struct cdregs *regs = &_a5xx_cd_registers[i]; - for (j = 0; j < regs->size / 2; j++) { - unsigned int r = REG_PAIR_COUNT(regs->regs, j); + for (j = 0; j < ARRAY_SIZE(a5xx_registers) / 2; j++) { + unsigned int r = REG_PAIR_COUNT(a5xx_registers, j); + *ptr++ = registers.gpuaddr + offset; + *ptr++ = (((uint64_t) a5xx_registers[2 * j]) << 44) + | r; + offset += r * sizeof(unsigned int); + } + + if (ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) { + for (j = 0; j < ARRAY_SIZE(a5xx_gpmu_registers) / 2; j++) { + unsigned int r = REG_PAIR_COUNT(a5xx_gpmu_registers, j); *ptr++ = registers.gpuaddr + offset; - *ptr++ = (((uint64_t) regs->regs[2 * j]) << 44) | r; + *ptr++ = (((uint64_t) a5xx_gpmu_registers[2 * j]) << 44) + | r; offset += r * sizeof(unsigned int); } } diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index fc7799722026..6dd9f6040fae 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, 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 @@ -2816,6 +2816,16 @@ int adreno_dispatcher_init(struct adreno_device *adreno_dev) return ret; } +void adreno_dispatcher_halt(struct kgsl_device *device) +{ + adreno_get_gpu_halt(ADRENO_DEVICE(device)); +} + +void adreno_dispatcher_unhalt(struct kgsl_device *device) +{ + adreno_put_gpu_halt(ADRENO_DEVICE(device)); +} + /* * adreno_dispatcher_idle() - Wait for dispatcher to idle * @adreno_dev: Adreno device whose dispatcher needs to idle diff --git a/drivers/gpu/msm/adreno_dispatch.h b/drivers/gpu/msm/adreno_dispatch.h index 48f0cdc546ff..f55f8cbf928b 100644 --- a/drivers/gpu/msm/adreno_dispatch.h +++ b/drivers/gpu/msm/adreno_dispatch.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2018, 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 @@ -103,6 +103,9 @@ enum adreno_dispatcher_flags { }; void adreno_dispatcher_start(struct kgsl_device *device); +void adreno_dispatcher_halt(struct kgsl_device *device); +void adreno_dispatcher_unhalt(struct kgsl_device *device); + int adreno_dispatcher_init(struct adreno_device *adreno_dev); void adreno_dispatcher_close(struct adreno_device *adreno_dev); int adreno_dispatcher_idle(struct adreno_device *adreno_dev); diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index cc3e79dc29bf..db9e5f7d6d6b 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -530,6 +530,16 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv, struct kgsl_device *device = dev_priv->device; char name[64]; int ret = 0, id; + struct kgsl_process_private *proc_priv = dev_priv->process_priv; + + if (atomic_read(&proc_priv->ctxt_count) > KGSL_MAX_CONTEXTS_PER_PROC) { + KGSL_DRV_ERR(device, + "Per process context limit reached for pid %u", + dev_priv->process_priv->pid); + return -ENOSPC; + } + + atomic_inc(&proc_priv->ctxt_count); id = _kgsl_get_context_id(device); if (id == -ENOSPC) { @@ -548,7 +558,7 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv, KGSL_DRV_INFO(device, "cannot have more than %zu contexts due to memstore limitation\n", KGSL_MEMSTORE_MAX); - + atomic_dec(&proc_priv->ctxt_count); return id; } @@ -579,6 +589,7 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv, out: if (ret) { + atomic_dec(&proc_priv->ctxt_count); write_lock(&device->context_lock); idr_remove(&dev_priv->device->context_idr, id); write_unlock(&device->context_lock); @@ -662,6 +673,7 @@ kgsl_context_destroy(struct kref *kref) device->pwrctrl.constraint.type = KGSL_CONSTRAINT_NONE; } + atomic_dec(&context->proc_priv->ctxt_count); idr_remove(&device->context_idr, context->id); context->id = KGSL_CONTEXT_INVALID; } @@ -734,6 +746,8 @@ static int kgsl_suspend_device(struct kgsl_device *device, pm_message_t state) mutex_lock(&device->mutex); status = kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND); + if (status == 0) + device->ftbl->dispatcher_halt(device); mutex_unlock(&device->mutex); KGSL_PWR_WARN(device, "suspend end\n"); @@ -748,6 +762,7 @@ static int kgsl_resume_device(struct kgsl_device *device) KGSL_PWR_WARN(device, "resume start\n"); mutex_lock(&device->mutex); if (device->state == KGSL_STATE_SUSPEND) { + device->ftbl->dispatcher_unhalt(device); kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); } else if (device->state != KGSL_STATE_INIT) { /* @@ -3977,6 +3992,7 @@ long kgsl_ioctl_gpuobj_set_info(struct kgsl_device_private *dev_priv, struct kgsl_process_private *private = dev_priv->process_priv; struct kgsl_gpuobj_set_info *param = data; struct kgsl_mem_entry *entry; + int ret = 0; if (param->id == 0) return -EINVAL; @@ -3989,12 +4005,16 @@ long kgsl_ioctl_gpuobj_set_info(struct kgsl_device_private *dev_priv, copy_metadata(entry, param->metadata, param->metadata_len); if (param->flags & KGSL_GPUOBJ_SET_INFO_TYPE) { - entry->memdesc.flags &= ~((uint64_t) KGSL_MEMTYPE_MASK); - entry->memdesc.flags |= param->type << KGSL_MEMTYPE_SHIFT; + if (param->type <= (KGSL_MEMTYPE_MASK >> KGSL_MEMTYPE_SHIFT)) { + entry->memdesc.flags &= ~((uint64_t) KGSL_MEMTYPE_MASK); + entry->memdesc.flags |= (uint64_t)((param->type << + KGSL_MEMTYPE_SHIFT) & KGSL_MEMTYPE_MASK); + } else + ret = -EINVAL; } kgsl_mem_entry_put(entry); - return 0; + return ret; } long kgsl_ioctl_cff_syncmem(struct kgsl_device_private *dev_priv, diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index faf38d1d2293..a486d9a86f9d 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2016, 2018, 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 @@ -51,11 +51,12 @@ /* The number of memstore arrays limits the number of contexts allowed. * If more contexts are needed, update multiple for MEMSTORE_SIZE */ -#define KGSL_MEMSTORE_SIZE ((int)(PAGE_SIZE * 2)) +#define KGSL_MEMSTORE_SIZE ((int)(PAGE_SIZE * 8)) #define KGSL_MEMSTORE_GLOBAL (0) #define KGSL_PRIORITY_MAX_RB_LEVELS 4 #define KGSL_MEMSTORE_MAX (KGSL_MEMSTORE_SIZE / \ sizeof(struct kgsl_devmemstore) - 1 - KGSL_PRIORITY_MAX_RB_LEVELS) +#define KGSL_MAX_CONTEXTS_PER_PROC 200 #define MEMSTORE_RB_OFFSET(rb, field) \ KGSL_MEMSTORE_OFFSET(((rb)->id + KGSL_MEMSTORE_MAX), field) diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 64dd45a30612..57d4fe4d9120 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2007-2018, 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 @@ -171,6 +171,8 @@ struct kgsl_functable { void (*gpu_model)(struct kgsl_device *device, char *str, size_t bufsz); void (*stop_fault_timer)(struct kgsl_device *device); + void (*dispatcher_halt)(struct kgsl_device *device); + void (*dispatcher_unhalt)(struct kgsl_device *device); }; struct kgsl_ioctl { @@ -417,6 +419,7 @@ struct kgsl_context { * @syncsource_idr: sync sources created by this process * @syncsource_lock: Spinlock to protect the syncsource idr * @fd_count: Counter for the number of FDs for this process + * @ctxt_count: Count for the number of contexts for this process */ struct kgsl_process_private { unsigned long priv; @@ -436,6 +439,7 @@ struct kgsl_process_private { struct idr syncsource_idr; spinlock_t syncsource_lock; int fd_count; + atomic_t ctxt_count; }; /** diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index ff6fae7c739b..b1b0b69d55ba 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -2675,6 +2675,7 @@ _aware(struct kgsl_device *device) break; default: status = -EINVAL; + return status; } if (status) kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); @@ -2781,8 +2782,9 @@ static int _suspend(struct kgsl_device *device) { int ret = 0; - if ((KGSL_STATE_NONE == device->state) || - (KGSL_STATE_INIT == device->state)) + if ((device->state == KGSL_STATE_NONE) || + (device->state == KGSL_STATE_INIT) || + (device->state == KGSL_STATE_SUSPEND)) return ret; /* drain to prevent from more commands being submitted */ |
