msm: kgsl: Add return value for perfcounter enable function

Add return value for adreno_perfcounter_enable function because it can
fail. Also, some perfcounter enable functions were receiving incorrect
parameter, fixed this by passing the right parameter to these enable
functions.

Change-Id: Ia47e9eab7833c44fcc0dc389ac8afce425f0a28e
Signed-off-by: Shubhraprakash Das <sadas@codeaurora.org>
This commit is contained in:
Shubhraprakash Das 2013-09-11 15:25:01 -07:00 committed by Iliyan Malchev
parent d66d7c0426
commit 8a7e71b9b5
3 changed files with 137 additions and 58 deletions

View file

@ -228,14 +228,28 @@ static const struct {
* performance counters will remain active as long as the device is alive.
*/
static void adreno_perfcounter_init(struct kgsl_device *device)
static int adreno_perfcounter_init(struct kgsl_device *device)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
if (adreno_dev->gpudev->perfcounter_init)
adreno_dev->gpudev->perfcounter_init(adreno_dev);
return adreno_dev->gpudev->perfcounter_init(adreno_dev);
return 0;
};
/**
* adreno_perfcounter_close: Release counters initialized by
* adreno_perfcounter_init
* @device: device to realease counters for
*
*/
static void adreno_perfcounter_close(struct kgsl_device *device)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
if (adreno_dev->gpudev->perfcounter_close)
return adreno_dev->gpudev->perfcounter_close(adreno_dev);
}
/**
* adreno_perfcounter_start: Enable performance counters
* @adreno_dev: Adreno device to configure
@ -243,16 +257,18 @@ static void adreno_perfcounter_init(struct kgsl_device *device)
* Ensure all performance counters are enabled that are allocated. Since
* the device was most likely stopped, we can't trust that the counters
* are still valid so make it so.
* Returns 0 on success else error code
*/
static void adreno_perfcounter_start(struct adreno_device *adreno_dev)
static int adreno_perfcounter_start(struct adreno_device *adreno_dev)
{
struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters;
struct adreno_perfcount_group *group;
unsigned int i, j;
int ret = 0;
if (NULL == counters)
return;
return 0;
/* group id iter */
for (i = 0; i < counters->group_count; i++) {
group = &(counters->groups[i]);
@ -266,11 +282,15 @@ static void adreno_perfcounter_start(struct adreno_device *adreno_dev)
continue;
if (adreno_dev->gpudev->perfcounter_enable)
adreno_dev->gpudev->perfcounter_enable(
ret = adreno_dev->gpudev->perfcounter_enable(
adreno_dev, i, j,
group->regs[j].countable);
if (ret)
goto done;
}
}
done:
return ret;
}
/**
@ -292,8 +312,7 @@ int adreno_perfcounter_read_group(struct adreno_device *adreno_dev,
unsigned int i, j;
int ret = 0;
/* perfcounter get/put/query/read not allowed on a2xx */
if (adreno_is_a2xx(adreno_dev))
if (NULL == counters)
return -EINVAL;
/* sanity check for later */
@ -371,8 +390,7 @@ int adreno_perfcounter_query_group(struct adreno_device *adreno_dev,
*max_counters = 0;
/* perfcounter get/put/query not allowed on a2xx */
if (adreno_is_a2xx(adreno_dev))
if (NULL == counters)
return -EINVAL;
if (groupid >= counters->group_count)
@ -421,13 +439,13 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev,
struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters;
struct adreno_perfcount_group *group;
unsigned int i, empty = -1;
int ret = 0;
/* always clear return variables */
if (offset)
*offset = 0;
/* perfcounter get/put/query not allowed on a2xx */
if (adreno_is_a2xx(adreno_dev))
if (NULL == counters)
return -EINVAL;
if (groupid >= counters->group_count)
@ -462,6 +480,11 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev,
if (empty == -1)
return -EBUSY;
/* enable the new counter */
ret = adreno_dev->gpudev->perfcounter_enable(adreno_dev, groupid, empty,
countable);
if (ret)
return ret;
/* initialize the new counter */
group->regs[empty].countable = countable;
@ -474,14 +497,10 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev,
group->regs[empty].usercount = 1;
}
/* enable the new counter */
adreno_dev->gpudev->perfcounter_enable(adreno_dev, groupid, empty,
countable);
if (offset)
*offset = group->regs[empty].offset;
return 0;
return ret;
}
@ -503,8 +522,7 @@ int adreno_perfcounter_put(struct adreno_device *adreno_dev,
unsigned int i;
/* perfcounter get/put/query not allowed on a2xx */
if (adreno_is_a2xx(adreno_dev))
if (NULL == counters)
return -EINVAL;
if (groupid >= counters->group_count)
@ -1556,6 +1574,7 @@ static int __devexit adreno_remove(struct platform_device *pdev)
adreno_dispatcher_close(adreno_dev);
adreno_ringbuffer_close(&adreno_dev->ringbuffer);
adreno_perfcounter_close(device);
kgsl_device_platform_remove(device);
clear_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv);
@ -1568,6 +1587,7 @@ static int adreno_init(struct kgsl_device *device)
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
int i;
int ret;
kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
/*
@ -1631,18 +1651,21 @@ static int adreno_init(struct kgsl_device *device)
for (i = 6; i < FT_DETECT_REGS_COUNT; i++)
ft_detect_regs[i] = 0;
adreno_perfcounter_init(device);
ret = adreno_perfcounter_init(device);
/* Power down the device */
kgsl_pwrctrl_disable(device);
if (ret)
goto done;
/* Certain targets need the fixup. You know who you are */
if (adreno_is_a330v2(adreno_dev))
adreno_a3xx_pwron_fixup_init(adreno_dev);
set_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv);
return 0;
done:
return ret;
}
static int adreno_start(struct kgsl_device *device)
@ -1711,15 +1734,19 @@ static int adreno_start(struct kgsl_device *device)
if (status)
goto error_irq_off;
status = adreno_perfcounter_start(adreno_dev);
if (status)
goto error_rb_stop;
/* Start the dispatcher */
adreno_dispatcher_start(adreno_dev);
adreno_perfcounter_start(adreno_dev);
device->reset_counter++;
return 0;
error_rb_stop:
adreno_ringbuffer_stop(&adreno_dev->ringbuffer);
error_irq_off:
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);

View file

@ -364,10 +364,11 @@ struct adreno_gpudev {
unsigned int (*irq_pending)(struct adreno_device *);
void * (*snapshot)(struct adreno_device *, void *, int *, int);
int (*rb_init)(struct adreno_device *, struct adreno_ringbuffer *);
void (*perfcounter_init)(struct adreno_device *);
int (*perfcounter_init)(struct adreno_device *);
void (*perfcounter_close)(struct adreno_device *);
void (*start)(struct adreno_device *);
unsigned int (*busy_cycles)(struct adreno_device *);
void (*perfcounter_enable)(struct adreno_device *, unsigned int group,
int (*perfcounter_enable)(struct adreno_device *, unsigned int group,
unsigned int counter, unsigned int countable);
uint64_t (*perfcounter_read)(struct adreno_device *adreno_dev,
unsigned int group, unsigned int counter);

View file

@ -3148,41 +3148,41 @@ static void a3xx_cp_callback(struct adreno_device *adreno_dev, int irq)
}
static void a3xx_perfcounter_enable_pwr(struct kgsl_device *device,
unsigned int countable)
static int a3xx_perfcounter_enable_pwr(struct kgsl_device *device,
unsigned int counter)
{
unsigned int in, out;
if (countable > 1)
return;
if (counter > 1)
return -EINVAL;
kgsl_regread(device, A3XX_RBBM_RBBM_CTL, &in);
if (countable == 0)
if (counter == 0)
out = in | RBBM_RBBM_CTL_RESET_PWR_CTR0;
else
out = in | RBBM_RBBM_CTL_RESET_PWR_CTR1;
kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, out);
if (countable == 0)
if (counter == 0)
out = in | RBBM_RBBM_CTL_ENABLE_PWR_CTR0;
else
out = in | RBBM_RBBM_CTL_ENABLE_PWR_CTR1;
kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, out);
return;
return 0;
}
static void a3xx_perfcounter_enable_vbif(struct kgsl_device *device,
static int a3xx_perfcounter_enable_vbif(struct kgsl_device *device,
unsigned int counter,
unsigned int countable)
{
unsigned int in, out, bit, sel;
if (counter > 1 || countable > 0x7f)
return;
return -EINVAL;
kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
kgsl_regread(device, A3XX_VBIF_PERF_CNT_SEL, &sel);
@ -3204,20 +3204,21 @@ static void a3xx_perfcounter_enable_vbif(struct kgsl_device *device,
kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
return 0;
}
static void a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device,
unsigned int countable)
static int a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device,
unsigned int counter)
{
unsigned int in, out, bit;
if (countable > 2)
return;
if (counter > 2)
return -EINVAL;
kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in);
if (countable == 0)
if (counter == 0)
bit = VBIF_PERF_PWR_CNT_0;
else if (countable == 1)
else if (counter == 1)
bit = VBIF_PERF_PWR_CNT_1;
else
bit = VBIF_PERF_PWR_CNT_2;
@ -3228,6 +3229,7 @@ static void a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device,
kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0);
kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out);
return 0;
}
/*
@ -3238,9 +3240,10 @@ static void a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device,
* @countable - Desired countable
*
* Physically set up a counter within a group with the desired countable
* Return 0 on success else error code
*/
static void a3xx_perfcounter_enable(struct adreno_device *adreno_dev,
static int a3xx_perfcounter_enable(struct adreno_device *adreno_dev,
unsigned int group, unsigned int counter, unsigned int countable)
{
struct kgsl_device *device = &adreno_dev->dev;
@ -3249,18 +3252,20 @@ static void a3xx_perfcounter_enable(struct adreno_device *adreno_dev,
/* Special cases */
if (group == KGSL_PERFCOUNTER_GROUP_PWR)
return a3xx_perfcounter_enable_pwr(device, countable);
return a3xx_perfcounter_enable_pwr(device, counter);
else if (group == KGSL_PERFCOUNTER_GROUP_VBIF)
return a3xx_perfcounter_enable_vbif(device, counter, countable);
return a3xx_perfcounter_enable_vbif(device, counter,
countable);
else if (group == KGSL_PERFCOUNTER_GROUP_VBIF_PWR)
return a3xx_perfcounter_enable_vbif_pwr(device, countable);
return a3xx_perfcounter_enable_vbif_pwr(device, counter);
if (group >= adreno_dev->gpudev->perfcounters->group_count)
return;
return -EINVAL;
if (counter >=
adreno_dev->gpudev->perfcounters->groups[group].reg_count)
return;
if ((0 == adreno_dev->gpudev->perfcounters->groups[group].reg_count) ||
(counter >=
adreno_dev->gpudev->perfcounters->groups[group].reg_count))
return -EINVAL;
reg = &(adreno_dev->gpudev->perfcounters->groups[group].regs[counter]);
@ -3268,12 +3273,15 @@ static void a3xx_perfcounter_enable(struct adreno_device *adreno_dev,
kgsl_regwrite(device, reg->select, countable);
if (reg->load_bit < 32) {
val = 1 << reg->load_bit;
kgsl_regread(device, A3XX_RBBM_PERFCTR_LOAD_CMD0, &val);
val |= (1 << reg->load_bit);
kgsl_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD0, val);
} else {
val = 1 << (reg->load_bit - 32);
kgsl_regread(device, A3XX_RBBM_PERFCTR_LOAD_CMD1, &val);
val |= (1 << (reg->load_bit - 32));
kgsl_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD1, val);
}
return 0;
}
static uint64_t a3xx_perfcounter_read_pwr(struct adreno_device *adreno_dev,
@ -3384,8 +3392,9 @@ static uint64_t a3xx_perfcounter_read(struct adreno_device *adreno_dev,
if (group >= adreno_dev->gpudev->perfcounters->group_count)
return 0;
if (counter >=
adreno_dev->gpudev->perfcounters->groups[group].reg_count)
if ((0 == adreno_dev->gpudev->perfcounters->groups[group].reg_count) ||
(counter >=
adreno_dev->gpudev->perfcounters->groups[group].reg_count))
return 0;
reg = &(adreno_dev->gpudev->perfcounters->groups[group].regs[counter]);
@ -3838,8 +3847,30 @@ static struct adreno_perfcounters a3xx_perfcounters = {
ARRAY_SIZE(a3xx_perfcounter_groups),
};
static void a3xx_perfcounter_init(struct adreno_device *adreno_dev)
/*
* a3xx_perfcounter_close() - Return counters that were initialized in
* a3xx_perfcounter_init
* @adreno_dev: The device for which counters were initialized
*/
static void a3xx_perfcounter_close(struct adreno_device *adreno_dev)
{
adreno_perfcounter_put(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
SP_FS_FULL_ALU_INSTRUCTIONS,
PERFCOUNTER_FLAG_KERNEL);
adreno_perfcounter_put(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
SP_FS_CFLOW_INSTRUCTIONS,
PERFCOUNTER_FLAG_KERNEL);
adreno_perfcounter_put(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
SP0_ICL1_MISSES,
PERFCOUNTER_FLAG_KERNEL);
adreno_perfcounter_put(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
SP_ALU_ACTIVE_CYCLES,
PERFCOUNTER_FLAG_KERNEL);
}
static int a3xx_perfcounter_init(struct adreno_device *adreno_dev)
{
int ret;
/* SP[3] counter is broken on a330 so disable it if a330 device */
if (adreno_is_a330(adreno_dev))
a3xx_perfcounters_sp[3].countable = KGSL_PERFCOUNTER_BROKEN;
@ -3854,26 +3885,45 @@ static void a3xx_perfcounter_init(struct adreno_device *adreno_dev)
* we will use this to augment our hang detection
*/
if (adreno_dev->fast_hang_detect) {
adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
ret = adreno_perfcounter_get(adreno_dev,
KGSL_PERFCOUNTER_GROUP_SP,
SP_ALU_ACTIVE_CYCLES, &ft_detect_regs[6],
PERFCOUNTER_FLAG_KERNEL);
if (ret)
goto err;
ft_detect_regs[7] = ft_detect_regs[6] + 1;
adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
ret = adreno_perfcounter_get(adreno_dev,
KGSL_PERFCOUNTER_GROUP_SP,
SP0_ICL1_MISSES, &ft_detect_regs[8],
PERFCOUNTER_FLAG_KERNEL);
if (ret)
goto err;
ft_detect_regs[9] = ft_detect_regs[8] + 1;
adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
ret = adreno_perfcounter_get(adreno_dev,
KGSL_PERFCOUNTER_GROUP_SP,
SP_FS_CFLOW_INSTRUCTIONS, &ft_detect_regs[10],
PERFCOUNTER_FLAG_KERNEL);
if (ret)
goto err;
ft_detect_regs[11] = ft_detect_regs[10] + 1;
}
adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
SP_FS_FULL_ALU_INSTRUCTIONS, NULL, PERFCOUNTER_FLAG_KERNEL);
if (ret)
goto err;
/* Reserve and start countable 1 in the PWR perfcounter group */
adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_PWR, 1,
ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_PWR, 1,
NULL, PERFCOUNTER_FLAG_KERNEL);
if (ret)
goto err;
return ret;
err:
a3xx_perfcounter_close(adreno_dev);
return ret;
}
/**
@ -4341,6 +4391,7 @@ struct adreno_gpudev adreno_a3xx_gpudev = {
.ctxt_draw_workaround = NULL,
.rb_init = a3xx_rb_init,
.perfcounter_init = a3xx_perfcounter_init,
.perfcounter_close = a3xx_perfcounter_close,
.irq_control = a3xx_irq_control,
.irq_handler = a3xx_irq_handler,
.irq_pending = a3xx_irq_pending,