mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-25 06:03:36 -04:00
msm: kgsl: Hook preemption sysfs nodes to hwscheduling
With hwscheduling, we need to communicate the preemption parameters to GMU. Also, we need to use GET_VALUE hfi packet to get the number of preemptions since last SLUMBER exit. Change-Id: I2ab342817a3cea4e1d1797369aa272895730357b Signed-off-by: Harshdeep Dhatt <hdhatt@codeaurora.org>
This commit is contained in:
parent
4f3a132f88
commit
2a826db07d
4 changed files with 157 additions and 6 deletions
|
|
@ -78,6 +78,7 @@
|
|||
#define HFI_VALUE_LOG_EVENT_OFF 113
|
||||
#define HFI_VALUE_DCVS_OBJ 114
|
||||
#define HFI_VALUE_LM_CS0 115
|
||||
#define HFI_VALUE_PREEMPT_COUNT 120
|
||||
|
||||
#define HFI_VALUE_GLOBAL_TOKEN 0xFFFFFFFF
|
||||
|
||||
|
|
|
|||
|
|
@ -733,6 +733,26 @@ static void enable_async_hfi(struct adreno_device *adreno_dev)
|
|||
(u32)~hfi->irq_mask);
|
||||
}
|
||||
|
||||
static int enable_preemption(struct adreno_device *adreno_dev)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
if (!adreno_is_preemption_enabled(adreno_dev))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Bits [0:1] contains the preemption level
|
||||
* Bit 2 is to enable/disable gmem save/restore
|
||||
* Bit 3 is to enable/disable skipsaverestore
|
||||
*/
|
||||
data = FIELD_PREP(GENMASK(1, 0), adreno_dev->preempt.preempt_level) |
|
||||
FIELD_PREP(BIT(2), adreno_dev->preempt.usesgmem) |
|
||||
FIELD_PREP(BIT(3), adreno_dev->preempt.skipsaverestore);
|
||||
|
||||
return a6xx_hfi_send_feature_ctrl(adreno_dev, HFI_FEATURE_PREEMPTION, 1,
|
||||
data);
|
||||
}
|
||||
|
||||
int a6xx_hwsched_hfi_start(struct adreno_device *adreno_dev)
|
||||
{
|
||||
struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
|
||||
|
|
@ -771,12 +791,9 @@ int a6xx_hwsched_hfi_start(struct adreno_device *adreno_dev)
|
|||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (adreno_is_preemption_enabled(adreno_dev)) {
|
||||
ret = a6xx_hfi_send_feature_ctrl(adreno_dev,
|
||||
HFI_FEATURE_PREEMPTION, 1, 0);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
ret = enable_preemption(adreno_dev);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = a6xx_hfi_send_core_fw_start(adreno_dev);
|
||||
if (ret)
|
||||
|
|
@ -1336,3 +1353,40 @@ void a6xx_hwsched_context_detach(struct adreno_context *drawctxt)
|
|||
|
||||
mutex_unlock(&device->mutex);
|
||||
}
|
||||
|
||||
int a6xx_hwsched_preempt_count_get(struct adreno_device *adreno_dev)
|
||||
{
|
||||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||
struct hfi_get_value_cmd cmd;
|
||||
struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
|
||||
struct a6xx_hwsched_hfi *hfi = to_a6xx_hwsched_hfi(adreno_dev);
|
||||
u32 seqnum = atomic_inc_return(&gmu->hfi.seqnum);
|
||||
struct pending_cmd pending_ack;
|
||||
int rc;
|
||||
|
||||
if (device->state != KGSL_STATE_ACTIVE)
|
||||
return 0;
|
||||
|
||||
CMD_MSG_HDR(cmd, H2F_MSG_GET_VALUE);
|
||||
|
||||
cmd.hdr = MSG_HDR_SET_SEQNUM(cmd.hdr, seqnum);
|
||||
cmd.type = HFI_VALUE_PREEMPT_COUNT;
|
||||
cmd.subtype = 0;
|
||||
|
||||
add_waiter(hfi, cmd.hdr, &pending_ack);
|
||||
|
||||
rc = a6xx_hfi_cmdq_write(adreno_dev, (u32 *)&cmd);
|
||||
if (rc)
|
||||
goto done;
|
||||
|
||||
rc = wait_ack_completion(adreno_dev, &pending_ack);
|
||||
if (rc)
|
||||
goto done;
|
||||
|
||||
rc = check_ack_failure(adreno_dev, &pending_ack);
|
||||
|
||||
done:
|
||||
del_waiter(hfi, &pending_ack);
|
||||
|
||||
return rc ? rc : pending_ack.results[2];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,4 +217,15 @@ void a6xx_hwsched_context_detach(struct adreno_context *drawctxt);
|
|||
|
||||
/* Helper function to get to a6xx hwsched hfi device from adreno device */
|
||||
struct a6xx_hwsched_hfi *to_a6xx_hwsched_hfi(struct adreno_device *adreno_dev);
|
||||
|
||||
/**
|
||||
* a6xx_hwsched_preempt_count_get - Get preemption count from GMU
|
||||
* @adreno_dev: Pointer to adreno device
|
||||
*
|
||||
* This function sends a GET_VALUE HFI packet to get the number of
|
||||
* preemptions completed since last SLUMBER exit.
|
||||
*
|
||||
* Return: Preemption count on success or negative error on failure
|
||||
*/
|
||||
int a6xx_hwsched_preempt_count_get(struct adreno_device *adreno_dev);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "adreno_a6xx.h"
|
||||
#include "adreno_a6xx_hwsched.h"
|
||||
#include "adreno_snapshot.h"
|
||||
#include "adreno_sysfs.h"
|
||||
#include "adreno_trace.h"
|
||||
|
||||
/* This structure represents inflight command object */
|
||||
|
|
@ -1006,10 +1007,91 @@ void adreno_hwsched_start(struct adreno_device *adreno_dev)
|
|||
adreno_hwsched_trigger(adreno_dev);
|
||||
}
|
||||
|
||||
static int _skipsaverestore_store(struct adreno_device *adreno_dev, bool val)
|
||||
{
|
||||
return adreno_power_cycle_bool(adreno_dev,
|
||||
&adreno_dev->preempt.skipsaverestore, val);
|
||||
}
|
||||
|
||||
static bool _skipsaverestore_show(struct adreno_device *adreno_dev)
|
||||
{
|
||||
return adreno_dev->preempt.skipsaverestore;
|
||||
}
|
||||
|
||||
static int _usesgmem_store(struct adreno_device *adreno_dev, bool val)
|
||||
{
|
||||
return adreno_power_cycle_bool(adreno_dev,
|
||||
&adreno_dev->preempt.usesgmem, val);
|
||||
}
|
||||
|
||||
static bool _usesgmem_show(struct adreno_device *adreno_dev)
|
||||
{
|
||||
return adreno_dev->preempt.usesgmem;
|
||||
}
|
||||
|
||||
static int _preempt_level_store(struct adreno_device *adreno_dev,
|
||||
unsigned int val)
|
||||
{
|
||||
return adreno_power_cycle_u32(adreno_dev,
|
||||
&adreno_dev->preempt.preempt_level,
|
||||
min_t(unsigned int, val, 2));
|
||||
}
|
||||
|
||||
static unsigned int _preempt_level_show(struct adreno_device *adreno_dev)
|
||||
{
|
||||
return adreno_dev->preempt.preempt_level;
|
||||
}
|
||||
|
||||
static void change_preemption(struct adreno_device *adreno_dev, void *priv)
|
||||
{
|
||||
change_bit(ADRENO_DEVICE_PREEMPTION, &adreno_dev->priv);
|
||||
}
|
||||
|
||||
static int _preemption_store(struct adreno_device *adreno_dev, bool val)
|
||||
{
|
||||
if (!(ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION)) ||
|
||||
(test_bit(ADRENO_DEVICE_PREEMPTION,
|
||||
&adreno_dev->priv) == val))
|
||||
return 0;
|
||||
|
||||
return adreno_power_cycle(adreno_dev, change_preemption, NULL);
|
||||
}
|
||||
|
||||
static bool _preemption_show(struct adreno_device *adreno_dev)
|
||||
{
|
||||
return adreno_is_preemption_enabled(adreno_dev);
|
||||
}
|
||||
|
||||
static unsigned int _preempt_count_show(struct adreno_device *adreno_dev)
|
||||
{
|
||||
int count = a6xx_hwsched_preempt_count_get(adreno_dev);
|
||||
|
||||
return count < 0 ? 0 : count;
|
||||
}
|
||||
|
||||
static ADRENO_SYSFS_BOOL(preemption);
|
||||
static ADRENO_SYSFS_U32(preempt_level);
|
||||
static ADRENO_SYSFS_BOOL(usesgmem);
|
||||
static ADRENO_SYSFS_BOOL(skipsaverestore);
|
||||
static ADRENO_SYSFS_RO_U32(preempt_count);
|
||||
|
||||
static const struct attribute *_preempt_attr_list[] = {
|
||||
&adreno_attr_preemption.attr.attr,
|
||||
&adreno_attr_preempt_level.attr.attr,
|
||||
&adreno_attr_usesgmem.attr.attr,
|
||||
&adreno_attr_skipsaverestore.attr.attr,
|
||||
&adreno_attr_preempt_count.attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void adreno_hwsched_dispatcher_close(struct adreno_device *adreno_dev)
|
||||
{
|
||||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||
|
||||
kmem_cache_destroy(jobs_cache);
|
||||
kmem_cache_destroy(obj_cache);
|
||||
|
||||
sysfs_remove_files(&device->dev->kobj, _preempt_attr_list);
|
||||
}
|
||||
|
||||
static void adreno_hwsched_init_replay(struct adreno_hwsched *hwsched)
|
||||
|
|
@ -1231,6 +1313,7 @@ static void adreno_hwsched_work(struct kthread_work *work)
|
|||
|
||||
void adreno_hwsched_init(struct adreno_device *adreno_dev)
|
||||
{
|
||||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||
struct adreno_hwsched *hwsched = to_hwsched(adreno_dev);
|
||||
int i;
|
||||
|
||||
|
|
@ -1249,6 +1332,8 @@ void adreno_hwsched_init(struct adreno_device *adreno_dev)
|
|||
init_llist_head(&hwsched->jobs[i]);
|
||||
init_llist_head(&hwsched->requeue[i]);
|
||||
}
|
||||
|
||||
sysfs_create_files(&device->dev->kobj, _preempt_attr_list);
|
||||
}
|
||||
|
||||
void adreno_hwsched_mark_drawobj(struct adreno_device *adreno_dev,
|
||||
|
|
|
|||
Loading…
Reference in a new issue