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

Commit edfbfdbb 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: Program the secvid registers in the soft reset path"

parents 6aa5401d a8fe0d26
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@ msm_adreno-y += \
	adreno_a3xx_snapshot.o \
	adreno_a4xx_snapshot.o \
	adreno_a5xx_snapshot.o \
	adreno_a4xx_preempt.o \
	adreno_a5xx_preempt.o \
	adreno_sysfs.o \
	adreno.o \
	adreno_cp_parser.o \
+2 −0
Original line number Diff line number Diff line
@@ -60,6 +60,8 @@
#define A5XX_CP_RB_BASE                  0x800
#define A5XX_CP_RB_BASE_HI               0x801
#define A5XX_CP_RB_CNTL                  0x802
#define A5XX_CP_RB_RPTR_ADDR_LO          0x804
#define A5XX_CP_RB_RPTR_ADDR_HI          0x805
#define A5XX_CP_RB_RPTR                  0x806
#define A5XX_CP_RB_WPTR                  0x807
#define A5XX_CP_PFP_STAT_ADDR            0x808
+72 −32
Original line number Diff line number Diff line
@@ -170,6 +170,30 @@ void adreno_writereg64(struct adreno_device *adreno_dev,
			gpudev->reg_offsets->offsets[hi], upper_32_bits(val));
}

/**
 * adreno_get_rptr() - Get the current ringbuffer read pointer
 * @rb: Pointer the ringbuffer to query
 *
 * Get the latest rptr
 */
unsigned int adreno_get_rptr(struct adreno_ringbuffer *rb)
{
	struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb);
	unsigned int rptr = 0;

	if (adreno_is_a3xx(adreno_dev))
		adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR,
				&rptr);
	else {
		struct kgsl_device *device = KGSL_DEVICE(adreno_dev);

		kgsl_sharedmem_readl(&device->scratch, &rptr,
				SCRATCH_RPTR_OFFSET(rb->id));
	}

	return rptr;
}

/**
 * adreno_of_read_property() - Adreno read property
 * @node: Device node
@@ -1288,6 +1312,28 @@ static void _update_threshold_count(struct adreno_device *adreno_dev,
		adreno_dev->lm_threshold_cross = adj;
}

static void _set_secvid(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);

	/* Program GPU contect protection init values */
	if (device->mmu.secured) {
		if (adreno_is_a4xx(adreno_dev))
			adreno_writereg(adreno_dev,
				ADRENO_REG_RBBM_SECVID_TRUST_CONFIG, 0x2);
		adreno_writereg(adreno_dev,
				ADRENO_REG_RBBM_SECVID_TSB_CONTROL, 0x0);

		adreno_writereg64(adreno_dev,
			ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE,
			ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE_HI,
			KGSL_IOMMU_SECURE_BASE);
		adreno_writereg(adreno_dev,
			ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE,
			KGSL_IOMMU_SECURE_SIZE);
	}
}

/**
 * _adreno_start - Power up the GPU and prepare to accept commands
 * @adreno_dev: Pointer to an adreno_device structure
@@ -1334,22 +1380,7 @@ static int _adreno_start(struct adreno_device *adreno_dev)
	if (status)
		goto error_pwr_off;

	/* Program GPU contect protection init values */
	if (device->mmu.secured) {
		if (adreno_is_a4xx(adreno_dev))
			adreno_writereg(adreno_dev,
				ADRENO_REG_RBBM_SECVID_TRUST_CONFIG, 0x2);
		adreno_writereg(adreno_dev,
				ADRENO_REG_RBBM_SECVID_TSB_CONTROL, 0x0);

		adreno_writereg64(adreno_dev,
			ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE,
			ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_BASE_HI,
			KGSL_IOMMU_SECURE_BASE);
		adreno_writereg(adreno_dev,
			ADRENO_REG_RBBM_SECVID_TSB_TRUSTED_SIZE,
			KGSL_IOMMU_SECURE_SIZE);
	}
	_set_secvid(device);

	status = adreno_ocmem_malloc(adreno_dev);
	if (status) {
@@ -1531,6 +1562,22 @@ static int adreno_vbif_clear_pending_transactions(struct kgsl_device *device)
	return ret;
}

static void adreno_set_active_ctxs_null(struct adreno_device *adreno_dev)
{
	int i;
	struct adreno_ringbuffer *rb;

	FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
		if (rb->drawctxt_active)
			kgsl_context_put(&(rb->drawctxt_active->base));
		rb->drawctxt_active = NULL;

		kgsl_sharedmem_writel(KGSL_DEVICE(adreno_dev),
			&rb->pagetable_desc, PT_INFO_OFFSET(current_rb_ptname),
			0);
	}
}

static int adreno_stop(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
@@ -1647,10 +1694,7 @@ int adreno_reset(struct kgsl_device *device, int fault)

	/* Set the page table back to the default page table */
	kgsl_mmu_set_pt(&device->mmu, device->mmu.defaultpagetable);
	kgsl_sharedmem_writel(device,
		&adreno_dev->ringbuffers[0].pagetable_desc,
		offsetof(struct adreno_ringbuffer_pagetable_info,
			current_global_ptname), 0);
	adreno_ringbuffer_set_global(adreno_dev, 0);

	return ret;
}
@@ -2097,6 +2141,8 @@ static int adreno_soft_reset(struct kgsl_device *device)
	/* start of new CFF after reset */
	kgsl_cffdump_open(device);

	_set_secvid(device);

	/* Enable 64 bit gpu addr if feature is set */
	if (gpudev->enable_64bit &&
			adreno_support_64bit(adreno_dev))
@@ -2149,8 +2195,6 @@ bool adreno_isidle(struct kgsl_device *device)
	if (!kgsl_state_is_awake(device))
		return true;

	adreno_get_rptr(ADRENO_CURRENT_RINGBUFFER(adreno_dev));

	/*
	 * wptr is updated when we add commands to ringbuffer, add a barrier
	 * to make sure updated wptr is compared to rptr
@@ -2161,15 +2205,13 @@ bool adreno_isidle(struct kgsl_device *device)
	 * ringbuffer is truly idle when all ringbuffers read and write
	 * pointers are equal
	 */

	FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
		if (rb->rptr != rb->wptr)
			break;
		if (!adreno_rb_empty(rb))
			return false;
	}

	if (i == adreno_dev->num_ringbuffers)
	return adreno_hw_isidle(adreno_dev);

	return false;
}

/**
@@ -2278,10 +2320,8 @@ static int adreno_suspend_context(struct kgsl_device *device)
		return status;
	/* set the device to default pagetable */
	kgsl_mmu_set_pt(&device->mmu, device->mmu.defaultpagetable);
	kgsl_sharedmem_writel(device,
		&adreno_dev->ringbuffers[0].pagetable_desc,
		offsetof(struct adreno_ringbuffer_pagetable_info,
			current_global_ptname), 0);
	adreno_ringbuffer_set_global(adreno_dev, 0);

	/* set ringbuffers to NULL ctxt */
	adreno_set_active_ctxs_null(adreno_dev);

+105 −50
Original line number Diff line number Diff line
@@ -191,6 +191,47 @@ enum adreno_gpurev {

struct adreno_gpudev;

/* Time to allow preemption to complete (in ms) */
#define ADRENO_PREEMPT_TIMEOUT 10000

/**
 * enum adreno_preempt_states
 * ADRENO_PREEMPT_NONE: No preemption is scheduled
 * ADRENO_PREEMPT_START: The S/W has started
 * ADRENO_PREEMPT_TRIGGERED: A preeempt has been triggered in the HW
 * ADRENO_PREEMPT_FAULTED: The preempt timer has fired
 * ADRENO_PREEMPT_PENDING: The H/W has signaled preemption complete
 * ADRENO_PREEMPT_COMPLETE: Preemption could not be finished in the IRQ handler,
 * worker has been scheduled
 */
enum adreno_preempt_states {
	ADRENO_PREEMPT_NONE = 0,
	ADRENO_PREEMPT_START,
	ADRENO_PREEMPT_TRIGGERED,
	ADRENO_PREEMPT_FAULTED,
	ADRENO_PREEMPT_PENDING,
	ADRENO_PREEMPT_COMPLETE,
};

/**
 * struct adreno_preemption
 * @state: The current state of preemption
 * @counters: Memory descriptor for the memory where the GPU writes the
 * preemption counters on switch
 * @timer: A timer to make sure preemption doesn't stall
 * @work: A work struct for the preemption worker (for 5XX)
 * @token_submit: Indicates if a preempt token has been submitted in
 * current ringbuffer (for 4XX)
 */
struct adreno_preemption {
	atomic_t state;
	struct kgsl_memdesc counters;
	struct timer_list timer;
	struct work_struct work;
	bool token_submit;
};


struct adreno_busy_data {
	unsigned int gpu_busy;
	unsigned int vbif_ram_cycles;
@@ -366,7 +407,7 @@ struct adreno_device {
	const struct firmware *lm_fw;
	uint32_t *lm_sequence;
	uint32_t lm_size;
	struct kgsl_memdesc preemption_counters;
	struct adreno_preemption preempt;
	struct work_struct gpmu_work;
	uint32_t lm_leakage;
	uint32_t lm_limit;
@@ -456,6 +497,8 @@ enum adreno_regs {
	ADRENO_REG_CP_WFI_PEND_CTR,
	ADRENO_REG_CP_RB_BASE,
	ADRENO_REG_CP_RB_BASE_HI,
	ADRENO_REG_CP_RB_RPTR_ADDR_LO,
	ADRENO_REG_CP_RB_RPTR_ADDR_HI,
	ADRENO_REG_CP_RB_RPTR,
	ADRENO_REG_CP_RB_WPTR,
	ADRENO_REG_CP_CNTL,
@@ -707,17 +750,12 @@ struct adreno_gpudev {
	void (*pwrlevel_change_settings)(struct adreno_device *,
				unsigned int prelevel, unsigned int postlevel,
				bool post);
	int (*preemption_pre_ibsubmit)(struct adreno_device *,
				struct adreno_ringbuffer *, unsigned int *,
				struct kgsl_context *, uint64_t cond_addr,
				struct kgsl_memobj_node *);
	unsigned int (*preemption_pre_ibsubmit)(struct adreno_device *,
				struct adreno_ringbuffer *rb,
				unsigned int *, struct kgsl_context *);
	int (*preemption_yield_enable)(unsigned int *);
	int (*preemption_post_ibsubmit)(struct adreno_device *,
				struct adreno_ringbuffer *, unsigned int *,
				struct kgsl_context *);
	int (*preemption_token)(struct adreno_device *,
				struct adreno_ringbuffer *, unsigned int *,
				uint64_t gpuaddr);
	unsigned int (*preemption_post_ibsubmit)(struct adreno_device *,
				unsigned int *);
	int (*preemption_init)(struct adreno_device *);
	void (*preemption_schedule)(struct adreno_device *);
	void (*enable_64bit)(struct adreno_device *);
@@ -1258,34 +1296,32 @@ static inline int adreno_bootstrap_ucode(struct adreno_device *adreno_dev)
}

/**
 * adreno_preempt_state() - Check if preemption state is equal to given state
 * adreno_in_preempt_state() - Check if preemption state is equal to given state
 * @adreno_dev: Device whose preemption state is checked
 * @state: State to compare against
 */
static inline unsigned int adreno_preempt_state(
			struct adreno_device *adreno_dev,
			enum adreno_dispatcher_preempt_states state)
static inline bool adreno_in_preempt_state(struct adreno_device *adreno_dev,
			enum adreno_preempt_states state)
{
	return atomic_read(&adreno_dev->dispatcher.preemption_state) ==
		state;
	return atomic_read(&adreno_dev->preempt.state) == state;
}

/**
 * adreno_get_rptr() - Get the current ringbuffer read pointer
 * @rb: Pointer the ringbuffer to query
 *
 * Get the current read pointer from the GPU register.
 * adreno_set_preempt_state() - Set the specified preemption state
 * @adreno_dev: Device to change preemption state
 * @state: State to set
 */
static inline unsigned int
adreno_get_rptr(struct adreno_ringbuffer *rb)
static inline void adreno_set_preempt_state(struct adreno_device *adreno_dev,
		enum adreno_preempt_states state)
{
	struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb);
	if (adreno_dev->cur_rb == rb &&
		adreno_preempt_state(adreno_dev,
			ADRENO_DISPATCHER_PREEMPT_CLEAR))
		adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR, &(rb->rptr));
	/*
	 * atomic_set doesn't use barriers, so we need to do it ourselves.  One
	 * before...
	 */
	smp_wmb();
	atomic_set(&adreno_dev->preempt.state, state);

	return rb->rptr;
	/* ... and one after */
	smp_wmb();
}

static inline bool adreno_is_preemption_enabled(
@@ -1293,7 +1329,6 @@ static inline bool adreno_is_preemption_enabled(
{
	return test_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv);
}

/**
 * adreno_ctx_get_rb() - Return the ringbuffer that a context should
 * use based on priority
@@ -1330,25 +1365,6 @@ static inline struct adreno_ringbuffer *adreno_ctx_get_rb(
		return &(adreno_dev->ringbuffers[
				adreno_dev->num_ringbuffers - 1]);
}
/*
 * adreno_set_active_ctxs_null() - Put back reference to any active context
 * and set the active context to NULL
 * @adreno_dev: The adreno device
 */
static inline void adreno_set_active_ctxs_null(struct adreno_device *adreno_dev)
{
	int i;
	struct adreno_ringbuffer *rb;
	FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
		if (rb->drawctxt_active)
			kgsl_context_put(&(rb->drawctxt_active->base));
		rb->drawctxt_active = NULL;
		kgsl_sharedmem_writel(KGSL_DEVICE(adreno_dev),
			&rb->pagetable_desc,
			offsetof(struct adreno_ringbuffer_pagetable_info,
				current_rb_ptname), 0);
	}
}

/*
 * adreno_compare_prio_level() - Compares 2 priority levels based on enum values
@@ -1369,6 +1385,13 @@ void adreno_readreg64(struct adreno_device *adreno_dev,
void adreno_writereg64(struct adreno_device *adreno_dev,
		enum adreno_regs lo, enum adreno_regs hi, uint64_t val);

unsigned int adreno_get_rptr(struct adreno_ringbuffer *rb);

static inline bool adreno_rb_empty(struct adreno_ringbuffer *rb)
{
	return (adreno_get_rptr(rb) == rb->wptr);
}

static inline bool adreno_soft_fault_detect(struct adreno_device *adreno_dev)
{
	return adreno_dev->fast_hang_detect &&
@@ -1398,4 +1421,36 @@ static inline bool adreno_support_64bit(struct adreno_device *adreno_dev)
}
#endif /*BITS_PER_LONG*/

static inline void adreno_ringbuffer_set_global(
		struct adreno_device *adreno_dev, int name)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);

	kgsl_sharedmem_writel(device,
		&adreno_dev->ringbuffers[0].pagetable_desc,
		PT_INFO_OFFSET(current_global_ptname), name);
}

static inline void adreno_ringbuffer_set_pagetable(struct adreno_ringbuffer *rb,
		struct kgsl_pagetable *pt)
{
	struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb);
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	unsigned long flags;

	spin_lock_irqsave(&rb->preempt_lock, flags);

	kgsl_sharedmem_writel(device, &rb->pagetable_desc,
		PT_INFO_OFFSET(current_rb_ptname), pt->name);

	kgsl_sharedmem_writeq(device, &rb->pagetable_desc,
		PT_INFO_OFFSET(ttbr0), kgsl_mmu_pagetable_get_ttbr0(pt));

	kgsl_sharedmem_writel(device, &rb->pagetable_desc,
		PT_INFO_OFFSET(contextidr),
		kgsl_mmu_pagetable_get_contextidr(pt));

	spin_unlock_irqrestore(&rb->preempt_lock, flags);
}

#endif /*__ADRENO_H */
+2 −2
Original line number Diff line number Diff line
@@ -1756,9 +1756,9 @@ static int _ringbuffer_bootstrap_ucode(struct adreno_device *adreno_dev,
		*cmds++ = cp_type3_packet(CP_INTERRUPT, 1);
		*cmds++ = 0;

		rb->wptr = rb->wptr - 2;
		rb->_wptr = rb->_wptr - 2;
		adreno_ringbuffer_submit(rb, NULL);
		rb->wptr = rb->wptr + 2;
		rb->_wptr = rb->_wptr + 2;
	} else {
		for (i = pfp_idx; i < adreno_dev->pfp_fw_size; i++)
			*cmds++ = adreno_dev->pfp_fw[i];
Loading