Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6f82220 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Make fast hang detect generic"

parents 032938f8 bd411b48
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -883,7 +883,6 @@
#define A310_RBBM_GPR0_CTL_DEFAULT    0x000000AA

/* COUNTABLE FOR SP PERFCOUNTER */
#define SP_FS_FULL_ALU_INSTRUCTIONS    0x0E
#define SP_ALU_ACTIVE_CYCLES           0x1D
#define SP0_ICL1_MISSES                0x1A
#define SP_FS_CFLOW_INSTRUCTIONS       0x0C
+116 −29
Original line number Diff line number Diff line
@@ -94,7 +94,21 @@ static struct adreno_device device_3d0 = {
		adreno_input_work),
};

unsigned int ft_detect_regs[FT_DETECT_REGS_COUNT];
/* Ptr to array for the current set of fault detect registers */
unsigned int *adreno_ft_regs;
/* Total number of fault detect registers */
unsigned int adreno_ft_regs_num;
/* Ptr to array for the current fault detect registers values */
unsigned int *adreno_ft_regs_val;
/* Array of default fault detect registers */
static unsigned int adreno_ft_regs_default[] = {
	ADRENO_REG_RBBM_STATUS,
	ADRENO_REG_CP_RB_RPTR,
	ADRENO_REG_CP_IB1_BASE,
	ADRENO_REG_CP_IB1_BUFSZ,
	ADRENO_REG_CP_IB2_BASE,
	ADRENO_REG_CP_IB2_BUFSZ
};

static struct workqueue_struct *adreno_wq;

@@ -104,6 +118,86 @@ static unsigned int _wake_nice = -7;
/* Number of milliseconds to stay active active after a wake on touch */
static unsigned int _wake_timeout = 100;


static int _get_counter(struct adreno_device *adreno_dev,
		int group, int countable, unsigned int *lo,
		unsigned int *hi)
{
	int ret = 0;

	if (*lo == 0) {

		ret = adreno_perfcounter_get(adreno_dev, group, countable,
			lo, hi, PERFCOUNTER_FLAG_KERNEL);

		if (ret) {
			struct kgsl_device *device = &adreno_dev->dev;

			KGSL_DRV_ERR(device,
				"Unable to allocate fault detect performance counter %d/%d\n",
				group, countable);
			KGSL_DRV_ERR(device,
				"GPU fault detect will be less reliable\n");
		}
	}

	return ret;
}

static inline void _put_counter(struct adreno_device *adreno_dev,
		int group, int countable, unsigned int *lo,
		unsigned int *hi)
{
	if (*lo != 0)
		adreno_perfcounter_put(adreno_dev, group, countable,
			PERFCOUNTER_FLAG_KERNEL);

	*lo = 0;
	*hi = 0;
}

/**
 * adreno_fault_detect_start() - Allocate performance counters
 * used for fast fault detection
 * @adreno_dev: Pointer to an adreno_device structure
 *
 * Allocate the series of performance counters that should be periodically
 * checked to verify that the GPU is still moving
 */
void adreno_fault_detect_start(struct adreno_device *adreno_dev)
{
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	unsigned int i, j = ARRAY_SIZE(adreno_ft_regs_default);

	for (i = 0; i < gpudev->ft_perf_counters_count; i++) {
		_get_counter(adreno_dev, gpudev->ft_perf_counters[i].counter,
			 gpudev->ft_perf_counters[i].countable,
			 &adreno_ft_regs[j + (i * 2)],
			 &adreno_ft_regs[j + ((i * 2) + 1)]);
	}
}

/**
 * adreno_fault_detect_stop() - Release performance counters
 * used for fast fault detection
 * @adreno_dev: Pointer to an adreno_device structure
 *
 * Release the counters allocated in adreno_fault_detect_start
 */
void adreno_fault_detect_stop(struct adreno_device *adreno_dev)
{
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	unsigned int i, j = ARRAY_SIZE(adreno_ft_regs_default);

	for (i = 0; i < gpudev->ft_perf_counters_count; i++) {
		_put_counter(adreno_dev, gpudev->ft_perf_counters[i].counter,
			 gpudev->ft_perf_counters[i].countable,
			 &adreno_ft_regs[j + (i * 2)],
			 &adreno_ft_regs[j + ((i * 2) + 1)]);

	}
}

/*
 * A workqueue callback responsible for actually turning on the GPU after a
 * touch event. kgsl_pwrctrl_change_state(ACTIVE) is used without any
@@ -1269,21 +1363,20 @@ static int adreno_init(struct kgsl_device *device)
			adreno_dev->gpucore->sync_lock_pfp_ver) >= 0))
		device->mmu.flags |= KGSL_MMU_FLAGS_IOMMU_SYNC;

	/* Initialize ft detection register offsets */
	ft_detect_regs[0] = adreno_getreg(adreno_dev,
						ADRENO_REG_RBBM_STATUS);
	ft_detect_regs[1] = adreno_getreg(adreno_dev,
						ADRENO_REG_CP_RB_RPTR);
	ft_detect_regs[2] = adreno_getreg(adreno_dev,
						ADRENO_REG_CP_IB1_BASE);
	ft_detect_regs[3] = adreno_getreg(adreno_dev,
						ADRENO_REG_CP_IB1_BUFSZ);
	ft_detect_regs[4] = adreno_getreg(adreno_dev,
						ADRENO_REG_CP_IB2_BASE);
	ft_detect_regs[5] = adreno_getreg(adreno_dev,
						ADRENO_REG_CP_IB2_BUFSZ);
	for (i = 6; i < FT_DETECT_REGS_COUNT; i++)
		ft_detect_regs[i] = 0;
	adreno_ft_regs_num = (ARRAY_SIZE(adreno_ft_regs_default) +
				   gpudev->ft_perf_counters_count*2);

	adreno_ft_regs = kzalloc(adreno_ft_regs_num, GFP_KERNEL);
	if (!adreno_ft_regs)
		return -ENOMEM;

	adreno_ft_regs_val = kzalloc(adreno_ft_regs_num, GFP_KERNEL);
	if (!adreno_ft_regs_val)
		return -ENOMEM;

	for (i = 0; i < ARRAY_SIZE(adreno_ft_regs_default); i++)
		adreno_ft_regs[i] = adreno_getreg(adreno_dev,
					adreno_ft_regs_default[i]);

	/* turn on hang interrupt for A4XX and a330v2 by default */
	if ((adreno_is_a4xx(adreno_dev)) || (adreno_is_a330v2(adreno_dev)))
@@ -1760,15 +1853,12 @@ static ssize_t _ft_fast_hang_detect_store(struct device *dev,

	if (tmp != adreno_dev->fast_hang_detect) {
		if (adreno_dev->fast_hang_detect) {
			if (gpudev->fault_detect_start &&
				!kgsl_active_count_get(&adreno_dev->dev)) {
				gpudev->fault_detect_start(adreno_dev);
			if (kgsl_active_count_get(&adreno_dev->dev)) {
				adreno_fault_detect_start(adreno_dev);
				kgsl_active_count_put(&adreno_dev->dev);
			}
		} else {
			if (gpudev->fault_detect_stop)
				gpudev->fault_detect_stop(adreno_dev);
		}
		} else
			adreno_fault_detect_stop(adreno_dev);
	}

	mutex_unlock(&adreno_dev->dev.mutex);
@@ -2345,7 +2435,6 @@ static int adreno_setproperty(struct kgsl_device_private *dev_priv,
	int status = -EINVAL;
	struct kgsl_device *device = dev_priv->device;
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);

	switch (type) {
	case KGSL_PROP_PWRCTRL: {
@@ -2365,9 +2454,8 @@ static int adreno_setproperty(struct kgsl_device_private *dev_priv,
				device->pwrctrl.ctrl_flags = 0;
				adreno_dev->fast_hang_detect = 1;

				if (gpudev->fault_detect_start &&
				!kgsl_active_count_get(&adreno_dev->dev)) {
					gpudev->fault_detect_start(adreno_dev);
				if (!kgsl_active_count_get(&adreno_dev->dev)) {
					adreno_fault_detect_start(adreno_dev);
					kgsl_active_count_put(&adreno_dev->dev);
				}

@@ -2377,8 +2465,7 @@ static int adreno_setproperty(struct kgsl_device_private *dev_priv,
							KGSL_STATE_ACTIVE);
				device->pwrctrl.ctrl_flags = KGSL_PWR_ON;
				adreno_dev->fast_hang_detect = 0;
				if (gpudev->fault_detect_stop)
					gpudev->fault_detect_stop(adreno_dev);
				adreno_fault_detect_stop(adreno_dev);
				kgsl_pwrscale_disable(device);
			}

+14 −6
Original line number Diff line number Diff line
@@ -591,6 +591,8 @@ struct adreno_gpudev {
	 * so define them in the structure and use them as variables.
	 */
	const struct adreno_reg_offsets *reg_offsets;
	const struct adreno_ft_perf_counters *ft_perf_counters;
	unsigned int ft_perf_counters_count;

	struct adreno_perfcounters *perfcounters;
	const struct adreno_invalid_countables
@@ -612,8 +614,6 @@ struct adreno_gpudev {
	void (*perfcounter_close)(struct adreno_device *);
	void (*perfcounter_save)(struct adreno_device *);
	void (*perfcounter_restore)(struct adreno_device *);
	void (*fault_detect_start)(struct adreno_device *);
	void (*fault_detect_stop)(struct adreno_device *);
	void (*start)(struct adreno_device *);
	void (*busy_cycles)(struct adreno_device *, struct adreno_busy_data *);
	int (*perfcounter_enable)(struct adreno_device *, unsigned int group,
@@ -629,8 +629,6 @@ struct adreno_gpudev {
	void (*regulator_disable)(struct adreno_device *);
};

#define FT_DETECT_REGS_COUNT 14

struct log_field {
	bool show;
	const char *display;
@@ -678,6 +676,15 @@ struct log_field {
		(_i) < (_dev)->num_ringbuffers;			\
		(_i)++, (_rb)++)

struct adreno_ft_perf_counters {
	unsigned int counter;
	unsigned int countable;
};

extern unsigned int *adreno_ft_regs;
extern unsigned int adreno_ft_regs_num;
extern unsigned int *adreno_ft_regs_val;

extern struct adreno_gpudev adreno_a3xx_gpudev;
extern struct adreno_gpudev adreno_a4xx_gpudev;

@@ -705,8 +712,6 @@ extern const struct adreno_vbif_snapshot_registers
				a4xx_vbif_snapshot_registers[];
extern const unsigned int a4xx_vbif_snapshot_reg_cnt;

extern unsigned int ft_detect_regs[];

int adreno_spin_idle(struct kgsl_device *device);
int adreno_idle(struct kgsl_device *device);
bool adreno_isidle(struct kgsl_device *device);
@@ -788,6 +793,9 @@ int adreno_iommu_set_pt(struct adreno_ringbuffer *rb,
void adreno_iommu_set_pt_generate_rb_cmds(struct adreno_ringbuffer *rb,
					struct kgsl_pagetable *pt);

void adreno_fault_detect_start(struct adreno_device *adreno_dev);
void adreno_fault_detect_stop(struct adreno_device *adreno_dev);

static inline int adreno_is_a3xx(struct adreno_device *adreno_dev)
{
	return ((ADRENO_GPUREV(adreno_dev) >= 300) &&
+11 −93
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@

#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/msm_kgsl.h>

#include "kgsl.h"
#include "adreno.h"
@@ -2074,95 +2075,12 @@ static struct adreno_perfcounters a3xx_perfcounters = {
	ARRAY_SIZE(a3xx_perfcounter_groups),
};

static inline int _get_counter(struct adreno_device *adreno_dev,
		int group, int countable, unsigned int *lo,
		unsigned int *hi)
{
	int ret = 0;

	if (*lo == 0) {

		ret = adreno_perfcounter_get(adreno_dev, group, countable,
			lo, hi, PERFCOUNTER_FLAG_KERNEL);

		if (ret) {
			struct kgsl_device *device = &adreno_dev->dev;

			KGSL_DRV_ERR(device,
				"Unable to allocate fault detect performance counter %d/%d\n",
				group, countable);
			KGSL_DRV_ERR(device,
				"GPU fault detect will be less reliable\n");
		}
	}

	return ret;
}

static inline void _put_counter(struct adreno_device *adreno_dev,
		int group, int countable, unsigned int *lo,
		unsigned int *hi)
{
	if (*lo != 0) {
		adreno_perfcounter_put(adreno_dev, group, countable,
			PERFCOUNTER_FLAG_KERNEL);
	}

	*lo = 0;
	*hi = 0;
}

/**
 * a3xx_fault_detect_start() - Allocate performance counters used for fast fault
 * detection
 * @adreno_dev: Pointer to an adreno_device structure
 *
 * Allocate the series of performance counters that should be periodically
 * checked to verify that the GPU is still moving
 */
void a3xx_fault_detect_start(struct adreno_device *adreno_dev)
{
	_get_counter(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
		SP_ALU_ACTIVE_CYCLES,
		&ft_detect_regs[6], &ft_detect_regs[7]);

	_get_counter(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
		SP0_ICL1_MISSES,
		&ft_detect_regs[8], &ft_detect_regs[9]);

	_get_counter(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
		SP_FS_CFLOW_INSTRUCTIONS,
		&ft_detect_regs[10], &ft_detect_regs[11]);

	_get_counter(adreno_dev, KGSL_PERFCOUNTER_GROUP_TSE,
		TSE_INPUT_PRIM_NUM,
		&ft_detect_regs[12], &ft_detect_regs[13]);
}
/**
 * a3xx_fault_detect_stop() - Release performance counters used for fast fault
 * detection
 * @adreno_dev: Pointer to an adreno_device structure
 *
 * Release the counters allocated in a3xx_fault_detect_start
 */
void a3xx_fault_detect_stop(struct adreno_device *adreno_dev)
{
	_put_counter(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
		SP_ALU_ACTIVE_CYCLES,
		&ft_detect_regs[6], &ft_detect_regs[7]);

	_put_counter(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
		SP0_ICL1_MISSES,
		&ft_detect_regs[8], &ft_detect_regs[9]);

	_put_counter(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
		SP_FS_CFLOW_INSTRUCTIONS,
		&ft_detect_regs[10], &ft_detect_regs[11]);

	_put_counter(adreno_dev, KGSL_PERFCOUNTER_GROUP_TSE,
		TSE_INPUT_PRIM_NUM,
		&ft_detect_regs[12], &ft_detect_regs[13]);
}
struct adreno_ft_perf_counters a3xx_ft_perf_counters[] = {
	{KGSL_PERFCOUNTER_GROUP_SP, SP_ALU_ACTIVE_CYCLES},
	{KGSL_PERFCOUNTER_GROUP_SP, SP0_ICL1_MISSES},
	{KGSL_PERFCOUNTER_GROUP_SP, SP_FS_CFLOW_INSTRUCTIONS},
	{KGSL_PERFCOUNTER_GROUP_TSE, TSE_INPUT_PRIM_NUM},
};

/**
 * a3xx_perfcounter_close() - Put counters that were initialized in
@@ -2175,7 +2093,7 @@ void a3xx_perfcounter_close(struct adreno_device *adreno_dev)
		PERFCOUNTER_FLAG_KERNEL);

	if (adreno_dev->fast_hang_detect)
		a3xx_fault_detect_stop(adreno_dev);
		adreno_fault_detect_stop(adreno_dev);
}

/**
@@ -2203,7 +2121,7 @@ int a3xx_perfcounter_init(struct adreno_device *adreno_dev)
	}

	if (adreno_dev->fast_hang_detect)
		a3xx_fault_detect_start(adreno_dev);
		adreno_fault_detect_start(adreno_dev);

	/* Turn on the GPU busy counter(s) and let them run free */
	/* GPU busy counts */
@@ -2483,6 +2401,8 @@ static struct adreno_snapshot_data a3xx_snapshot_data = {

struct adreno_gpudev adreno_a3xx_gpudev = {
	.reg_offsets = &a3xx_reg_offsets,
	.ft_perf_counters = a3xx_ft_perf_counters,
	.ft_perf_counters_count = ARRAY_SIZE(a3xx_ft_perf_counters),
	.perfcounters = &a3xx_perfcounters,
	.irq = &a3xx_irq,
	.snapshot_data = &a3xx_snapshot_data,
@@ -2503,7 +2423,5 @@ struct adreno_gpudev adreno_a3xx_gpudev = {
	.perfcounter_enable = a3xx_perfcounter_enable,
	.perfcounter_read = a3xx_perfcounter_read,
	.perfcounter_write = a3xx_perfcounter_write,
	.fault_detect_start = a3xx_fault_detect_start,
	.fault_detect_stop = a3xx_fault_detect_stop,
	.coresight = &a3xx_coresight,
};
+0 −3
Original line number Diff line number Diff line
@@ -34,9 +34,6 @@ void a3xx_a4xx_err_callback(struct adreno_device *adreno_dev, int bit);
void a3xx_fatal_err_callback(struct adreno_device *adreno_dev, int bit);
void a3xx_cp_callback(struct adreno_device *adreno_dev, int irq);

void a3xx_fault_detect_start(struct adreno_device *adreno_dev);
void a3xx_fault_detect_stop(struct adreno_device *adreno_dev);

void a3xx_snapshot(struct adreno_device *adreno_dev,
		struct kgsl_snapshot *snapshot);
#endif /*__A3XX_H */
Loading