From 5dadc0852f902889741fa62cfdffbb2aa7cb59a8 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 14 Oct 2019 10:41:10 -0600 Subject: [PATCH] msm: kgsl: Set up the adreno device at runtime Instead of doing the adreno device setup at compile time with some ugly macros, do it at the beginning of device probe. This allows us to retry probe without having to worry about coming back through probe with a partially modified data structure. Change-Id: Ic0dedbad09fa37e2a1a8161e7d54c676d42151e8 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/adreno.c | 88 +++++++++++++++------------ drivers/gpu/msm/adreno.h | 23 +++---- drivers/gpu/msm/adreno_a6xx.c | 4 ++ drivers/gpu/msm/adreno_a6xx_preempt.c | 14 +++-- drivers/gpu/msm/adreno_sysfs.c | 6 +- drivers/gpu/msm/kgsl_device.h | 14 ----- drivers/gpu/msm/kgsl_pwrctrl.c | 12 ++-- drivers/gpu/msm/kgsl_pwrctrl.h | 1 - drivers/gpu/msm/kgsl_pwrscale.c | 81 ++++++++++++++---------- drivers/gpu/msm/kgsl_pwrscale.h | 16 ----- 10 files changed, 129 insertions(+), 130 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index fdb0d8003e40..6a3c1332f19d 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -32,43 +32,7 @@ static void adreno_input_work(struct work_struct *work); static unsigned int counter_delta(struct kgsl_device *device, unsigned int reg, unsigned int *counter); -static struct devfreq_msm_adreno_tz_data adreno_tz_data = { - .bus = { - .max = 350, - .floating = true, - }, - .device_id = 0, -}; - -static const struct kgsl_functable adreno_functable; - -static struct adreno_device device_3d0 = { - .dev = { - KGSL_DEVICE_COMMON_INIT(device_3d0.dev), - .pwrscale = KGSL_PWRSCALE_INIT(&adreno_tz_data), - .name = DEVICE_3D0_NAME, - .id = 0, - .iomemname = "kgsl_3d0_reg_memory", - .ftbl = &adreno_functable, - }, - .ft_policy = KGSL_FT_DEFAULT_POLICY, - .ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY, - .long_ib_detect = 1, - .input_work = __WORK_INITIALIZER(device_3d0.input_work, - adreno_input_work), - .pwrctrl_flag = BIT(ADRENO_SPTP_PC_CTRL) | - BIT(ADRENO_THROTTLING_CTRL) | BIT(ADRENO_HWCG_CTRL), - .profile.enabled = false, - .active_list = LIST_HEAD_INIT(device_3d0.active_list), - .active_list_lock = __SPIN_LOCK_UNLOCKED(device_3d0.active_list_lock), - .gpu_llc_slice_enable = true, - .gpuhtw_llc_slice_enable = true, - .preempt = { - .preempt_level = 1, - .skipsaverestore = 1, - .usesgmem = 1, - }, -}; +static struct adreno_device device_3d0; /* Ptr to array for the current set of fault detect registers */ unsigned int *adreno_ft_regs; @@ -858,7 +822,7 @@ static int adreno_identify_gpu(struct adreno_device *adreno_dev) } static const struct platform_device_id adreno_id_table[] = { - { DEVICE_3D0_NAME, (unsigned long) &device_3d0, }, + { "kgsl-3d0", (unsigned long) &device_3d0, }, {}, }; @@ -1140,7 +1104,8 @@ static int adreno_of_get_power(struct adreno_device *adreno_dev, /* Get starting physical address of device registers */ res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM, - device->iomemname); + "kgsl_3d0_reg_memory"); + if (res == NULL) { dev_err(device->dev, "platform_get_resource_byname failed\n"); @@ -1356,6 +1321,47 @@ static int adreno_probe_efuse(struct platform_device *pdev, return 0; } +static const struct kgsl_functable adreno_functable; + +static void adreno_setup_device(struct adreno_device *adreno_dev) +{ + memset(adreno_dev, 0, sizeof(*adreno_dev)); + + adreno_dev->dev.name = "kgsl-3d0"; + adreno_dev->dev.ftbl = &adreno_functable; + + init_completion(&adreno_dev->dev.hwaccess_gate); + init_completion(&adreno_dev->dev.halt_gate); + + idr_init(&adreno_dev->dev.context_idr); + + mutex_init(&adreno_dev->dev.mutex); + INIT_LIST_HEAD(&adreno_dev->dev.globals); + + /* Set the fault tolerance policy to replay, skip, throttle */ + adreno_dev->ft_policy = BIT(KGSL_FT_REPLAY) | + BIT(KGSL_FT_SKIPCMD) | BIT(KGSL_FT_THROTTLE); + + /* Enable command timeouts by default */ + adreno_dev->long_ib_detect = true; + + INIT_WORK(&adreno_dev->input_work, adreno_input_work); + + /* + * Enable SPTP power collapse, throttling and hardware clock gating by + * default where applicable + */ + adreno_dev->pwrctrl_flag = BIT(ADRENO_SPTP_PC_CTRL) | + BIT(ADRENO_THROTTLING_CTRL) | BIT(ADRENO_HWCG_CTRL); + + INIT_LIST_HEAD(&adreno_dev->active_list); + spin_lock_init(&adreno_dev->active_list_lock); + + /* Enable use of the LLC slices where applicable */ + adreno_dev->gpu_llc_slice_enable = true; + adreno_dev->gpuhtw_llc_slice_enable = true; +} + static int adreno_probe(struct platform_device *pdev) { const struct of_device_id *of_id; @@ -1370,6 +1376,10 @@ static int adreno_probe(struct platform_device *pdev) return -EINVAL; adreno_dev = (struct adreno_device *) of_id->data; + + /* Initialize the adreno device structure */ + adreno_setup_device(adreno_dev); + device = KGSL_DEVICE(adreno_dev); device->pdev = pdev; diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 89ddfbea4a0d..ca6c1bb5ba22 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -13,8 +13,6 @@ #include "adreno_ringbuffer.h" #include "kgsl_sharedmem.h" -#define DEVICE_3D0_NAME "kgsl-3d0" - /* ADRENO_DEVICE - Given a kgsl_device return the adreno device struct */ #define ADRENO_DEVICE(device) \ container_of(device, struct adreno_device, dev) @@ -476,7 +474,7 @@ struct adreno_device { struct adreno_ringbuffer *prev_rb; unsigned int fast_hang_detect; unsigned long ft_policy; - unsigned int long_ib_detect; + bool long_ib_detect; unsigned long ft_pf_policy; bool cooperative_reset; struct adreno_profile profile; @@ -839,13 +837,13 @@ struct adreno_gpudev { */ enum kgsl_ft_policy_bits { KGSL_FT_OFF = 0, - KGSL_FT_REPLAY = 1, - KGSL_FT_SKIPIB = 2, - KGSL_FT_SKIPFRAME = 3, - KGSL_FT_DISABLE = 4, - KGSL_FT_TEMP_DISABLE = 5, - KGSL_FT_THROTTLE = 6, - KGSL_FT_SKIPCMD = 7, + KGSL_FT_REPLAY, + KGSL_FT_SKIPIB, + KGSL_FT_SKIPFRAME, + KGSL_FT_DISABLE, + KGSL_FT_TEMP_DISABLE, + KGSL_FT_THROTTLE, + KGSL_FT_SKIPCMD, /* KGSL_FT_MAX_BITS is used to calculate the mask */ KGSL_FT_MAX_BITS, /* Internal bits - set during GFT */ @@ -855,11 +853,6 @@ enum kgsl_ft_policy_bits { #define KGSL_FT_POLICY_MASK GENMASK(KGSL_FT_MAX_BITS - 1, 0) -#define KGSL_FT_DEFAULT_POLICY \ - (BIT(KGSL_FT_REPLAY) | \ - BIT(KGSL_FT_SKIPCMD) | \ - BIT(KGSL_FT_THROTTLE)) - /** * enum kgsl_ft_pagefault_policy_bits - KGSL pagefault policy bits * @KGSL_FT_PAGEFAULT_INT_ENABLE: No longer used, but retained for compatibility diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c index 03eaf8d59416..745960a00be9 100644 --- a/drivers/gpu/msm/adreno_a6xx.c +++ b/drivers/gpu/msm/adreno_a6xx.c @@ -2205,6 +2205,10 @@ static void a6xx_platform_setup(struct adreno_device *adreno_dev) { struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); + adreno_dev->preempt.preempt_level = 1; + adreno_dev->preempt.skipsaverestore = true; + adreno_dev->preempt.usesgmem = true; + if (adreno_has_gbif(adreno_dev)) { a6xx_perfcounter_groups[KGSL_PERFCOUNTER_GROUP_VBIF].regs = a6xx_perfcounters_gbif; diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c index eae0b10b0490..920b7038352e 100644 --- a/drivers/gpu/msm/adreno_a6xx_preempt.c +++ b/drivers/gpu/msm/adreno_a6xx_preempt.c @@ -210,10 +210,6 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev) unsigned long flags; struct adreno_preemption *preempt = &adreno_dev->preempt; - cntl = (((preempt->preempt_level << 6) & 0xC0) | - ((preempt->skipsaverestore << 9) & 0x200) | - ((preempt->usesgmem << 8) & 0x100) | 0x1); - /* Put ourselves into a possible trigger state */ if (!adreno_move_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE, ADRENO_PREEMPT_START)) @@ -352,6 +348,16 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev) mod_timer(&adreno_dev->preempt.timer, jiffies + msecs_to_jiffies(ADRENO_PREEMPT_TIMEOUT)); + cntl = (preempt->preempt_level << 6) | 0x01; + + /* Skip save/restore during L1 preemption */ + if (preempt->skipsaverestore) + cntl |= (1 << 9); + + /* Enable GMEM save/restore across preemption */ + if (preempt->usesgmem) + cntl |= (1 << 8); + trace_adreno_preempt_trigger(adreno_dev->cur_rb, adreno_dev->next_rb, cntl); diff --git a/drivers/gpu/msm/adreno_sysfs.c b/drivers/gpu/msm/adreno_sysfs.c index 53ee73c31a67..5256c25be624 100644 --- a/drivers/gpu/msm/adreno_sysfs.c +++ b/drivers/gpu/msm/adreno_sysfs.c @@ -50,7 +50,7 @@ static int _usesgmem_store(struct adreno_device *adreno_dev, bool val) { struct adreno_preemption *preempt = &adreno_dev->preempt; - preempt->usesgmem = val ? 1 : 0; + preempt->usesgmem = val ? true : false; return 0; } @@ -63,7 +63,7 @@ static int _skipsaverestore_store(struct adreno_device *adreno_dev, bool val) { struct adreno_preemption *preempt = &adreno_dev->preempt; - preempt->skipsaverestore = val ? 1 : 0; + preempt->skipsaverestore = val ? true : false; return 0; } @@ -124,7 +124,7 @@ static bool _gpuhtw_llc_slice_enable_show(struct adreno_device *adreno_dev) static int _ft_long_ib_detect_store(struct adreno_device *adreno_dev, bool val) { - adreno_dev->long_ib_detect = val; + adreno_dev->long_ib_detect = val ? true : false; return 0; } diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 7bac20d42d44..cf027138e151 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -263,7 +263,6 @@ struct kgsl_device { atomic_t active_cnt; - wait_queue_head_t wait_queue; wait_queue_head_t active_cnt_wq; struct platform_device *pdev; struct dentry *d_debugfs; @@ -320,19 +319,6 @@ struct kgsl_device { #define KGSL_MMU_DEVICE(_mmu) \ container_of((_mmu), struct kgsl_device, mmu) -#define KGSL_DEVICE_COMMON_INIT(_dev) \ - .hwaccess_gate = COMPLETION_INITIALIZER((_dev).hwaccess_gate),\ - .halt_gate = COMPLETION_INITIALIZER((_dev).halt_gate),\ - .idle_check_ws = __WORK_INITIALIZER((_dev).idle_check_ws,\ - kgsl_idle_check),\ - .context_idr = IDR_INIT((_dev).context_idr),\ - .wait_queue = __WAIT_QUEUE_HEAD_INITIALIZER((_dev).wait_queue),\ - .active_cnt_wq = __WAIT_QUEUE_HEAD_INITIALIZER((_dev).active_cnt_wq),\ - .mutex = __MUTEX_INITIALIZER((_dev).mutex),\ - .state = KGSL_STATE_NONE, \ - .globals = LIST_HEAD_INIT((_dev).globals) - - /** * enum bits for struct kgsl_context.priv * @KGSL_CONTEXT_PRIV_SUBMITTED - The context has submitted commands to gpu. diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index c09d17456f70..c9b06047512c 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1643,6 +1643,8 @@ static u32 *kgsl_bus_get_table(struct platform_device *pdev, int *count) return levels; } +static void kgsl_idle_check(struct work_struct *work); + int kgsl_pwrctrl_init(struct kgsl_device *device) { int i, result, freq, levels_count; @@ -1679,6 +1681,9 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) return -EINVAL; } + INIT_WORK(&device->idle_check_ws, kgsl_idle_check); + init_waitqueue_head(&device->active_cnt_wq); + /* Initialize the user and thermal clock constraints */ pwr->max_pwrlevel = 0; @@ -1786,15 +1791,12 @@ void kgsl_pwrctrl_close(struct kgsl_device *device) pm_runtime_disable(&device->pdev->dev); } -/** - * kgsl_idle_check() - Work function for GPU interrupts and idle timeouts. - * @device: The device - * +/* * This function is called for work that is queued by the interrupt * handler or the idle timer. It attempts to transition to a clocks * off state if the active_cnt is 0 and the hardware is idle. */ -void kgsl_idle_check(struct work_struct *work) +static void kgsl_idle_check(struct work_struct *work) { struct kgsl_device *device = container_of(work, struct kgsl_device, idle_check_ws); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index 659dcb38818a..e75e37008ed0 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -158,7 +158,6 @@ struct kgsl_pwrctrl { int kgsl_pwrctrl_init(struct kgsl_device *device); void kgsl_pwrctrl_close(struct kgsl_device *device); void kgsl_timer(struct timer_list *t); -void kgsl_idle_check(struct work_struct *work); void kgsl_pre_hwaccess(struct kgsl_device *device); void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device, unsigned int level); diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c index 435082d5e247..671b7eae4974 100644 --- a/drivers/gpu/msm/kgsl_pwrscale.c +++ b/drivers/gpu/msm/kgsl_pwrscale.c @@ -10,6 +10,13 @@ #include "kgsl_pwrscale.h" #include "kgsl_trace.h" +static struct devfreq_msm_adreno_tz_data adreno_tz_data = { + .bus = { + .max = 350, + .floating = true, + }, +}; + /** * struct kgsl_midframe_info - midframe power stats sampling info * @timer - midframe sampling timer @@ -660,11 +667,19 @@ static void pwrscale_busmon_create(struct kgsl_device *device, struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct kgsl_pwrscale *pwrscale = &device->pwrscale; struct device *dev = &pwrscale->busmondev; + struct msm_busmon_extended_profile *bus_profile; struct devfreq *bus_devfreq; int i; - pwrscale->bus_profile.profile.max_state = pwr->num_pwrlevels - 1; - pwrscale->bus_profile.profile.freq_table = table; + bus_profile = &pwrscale->bus_profile; + bus_profile->private_data = &adreno_tz_data; + + bus_profile->profile.target = kgsl_busmon_target; + bus_profile->profile.get_dev_status = kgsl_busmon_get_dev_status; + bus_profile->profile.get_cur_freq = kgsl_busmon_get_cur_freq; + + bus_profile->profile.max_state = pwr->num_pwrlevels - 1; + bus_profile->profile.freq_table = table; dev->parent = &pdev->dev; @@ -695,18 +710,25 @@ static void pwrscale_busmon_create(struct kgsl_device *device, int kgsl_pwrscale_init(struct kgsl_device *device, struct platform_device *pdev, const char *governor) { - struct kgsl_pwrscale *pwrscale; - struct kgsl_pwrctrl *pwr; + struct kgsl_pwrscale *pwrscale = &device->pwrscale; + struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct devfreq *devfreq; struct msm_adreno_extended_profile *gpu_profile; - struct devfreq_dev_profile *profile; - struct devfreq_msm_adreno_tz_data *data; int i, ret; - pwrscale = &device->pwrscale; - pwr = &device->pwrctrl; + pwrscale->enabled = true; + gpu_profile = &pwrscale->gpu_profile; - profile = &pwrscale->gpu_profile.profile; + gpu_profile->private_data = &adreno_tz_data; + + gpu_profile->profile.target = kgsl_devfreq_target; + gpu_profile->profile.get_dev_status = kgsl_devfreq_get_dev_status; + gpu_profile->profile.get_cur_freq = kgsl_devfreq_get_cur_freq; + + gpu_profile->profile.initial_freq = + pwr->pwrlevels[pwr->default_pwrlevel].gpu_freq; + + gpu_profile->profile.polling_ms = 10; pwr->nb.notifier_call = opp_notify; @@ -714,39 +736,33 @@ int kgsl_pwrscale_init(struct kgsl_device *device, struct platform_device *pdev, srcu_init_notifier_head(&pwrscale->nh); - profile->initial_freq = - pwr->pwrlevels[pwr->default_pwrlevel].gpu_freq; - /* Let's start with 10 ms and tune in later */ - profile->polling_ms = 10; /* do not include the 'off' level or duplicate freq. levels */ for (i = 0; i < (pwr->num_pwrlevels - 1); i++) - pwrscale->freq_table[out++] = pwr->pwrlevels[i].gpu_freq; + pwrscale->freq_table[i] = pwr->pwrlevels[i].gpu_freq; /* * Max_state is the number of valid power levels. * The valid power levels range from 0 - (max_state - 1) */ - profile->max_state = pwr->num_pwrlevels - 1; + gpu_profile->profile.max_state = pwr->num_pwrlevels - 1; /* link storage array to the devfreq profile pointer */ - profile->freq_table = pwrscale->freq_table; + gpu_profile->profile.freq_table = pwrscale->freq_table; /* if there is only 1 freq, no point in running a governor */ - if (profile->max_state == 1) + if (gpu_profile->profile.max_state == 1) governor = "performance"; /* initialize msm-adreno-tz governor specific data here */ - data = gpu_profile->private_data; - - data->disable_busy_time_burst = + adreno_tz_data.disable_busy_time_burst = of_property_read_bool(pdev->dev.of_node, "qcom,disable-busy-time-burst"); if (pwrscale->ctxt_aware_enable) { - data->ctxt_aware_enable = pwrscale->ctxt_aware_enable; - data->bin.ctxt_aware_target_pwrlevel = + adreno_tz_data.ctxt_aware_enable = pwrscale->ctxt_aware_enable; + adreno_tz_data.bin.ctxt_aware_target_pwrlevel = pwrscale->ctxt_aware_target_pwrlevel; - data->bin.ctxt_aware_busy_penalty = + adreno_tz_data.bin.ctxt_aware_busy_penalty = pwrscale->ctxt_aware_busy_penalty; } @@ -771,18 +787,17 @@ int kgsl_pwrscale_init(struct kgsl_device *device, struct platform_device *pdev, * the bus bandwidth vote. */ if (pwr->bus_control) { - data->bus.num = pwr->bus_ibs_count; - data->bus.ib_mbps = pwr->bus_ibs; - data->bus.width = pwr->bus_width; + adreno_tz_data.bus.num = pwr->bus_ibs_count; + adreno_tz_data.bus.ib_mbps = pwr->bus_ibs; + adreno_tz_data.bus.width = pwr->bus_width; if (!kgsl_of_property_read_ddrtype(device->pdev->dev.of_node, - "qcom,bus-accesses", &data->bus.max)) - data->bus.floating = false; - } else - data->bus.num = 0; + "qcom,bus-accesses", &adreno_tz_data.bus.max)) + adreno_tz_data.bus.floating = false; + } - devfreq = devfreq_add_device(&pdev->dev, &pwrscale->gpu_profile.profile, - governor, pwrscale->gpu_profile.private_data); + devfreq = devfreq_add_device(&pdev->dev, &gpu_profile->profile, + governor, &adreno_tz_data); if (IS_ERR(devfreq)) { device->pwrscale.enabled = false; return PTR_ERR(devfreq); @@ -796,7 +811,7 @@ int kgsl_pwrscale_init(struct kgsl_device *device, struct platform_device *pdev, pwrscale->gpu_profile.bus_devfreq = NULL; - if (data->bus.num) + if (adreno_tz_data.bus.num) pwrscale_busmon_create(device, pdev, pwrscale->freq_table); ret = sysfs_create_link(&device->dev->kobj, diff --git a/drivers/gpu/msm/kgsl_pwrscale.h b/drivers/gpu/msm/kgsl_pwrscale.h index 325ee6fda6a9..51b13f0c394d 100644 --- a/drivers/gpu/msm/kgsl_pwrscale.h +++ b/drivers/gpu/msm/kgsl_pwrscale.h @@ -101,20 +101,4 @@ int kgsl_busmon_get_dev_status(struct device *dev, struct devfreq_dev_status *stat); int kgsl_busmon_get_cur_freq(struct device *dev, unsigned long *freq); -#define KGSL_PWRSCALE_INIT(_priv_data) { \ - .enabled = true, \ - .gpu_profile = { \ - .private_data = _priv_data, \ - .profile = { \ - .target = kgsl_devfreq_target, \ - .get_dev_status = kgsl_devfreq_get_dev_status, \ - .get_cur_freq = kgsl_devfreq_get_cur_freq, \ - } }, \ - .bus_profile = { \ - .private_data = _priv_data, \ - .profile = { \ - .target = kgsl_busmon_target, \ - .get_dev_status = kgsl_busmon_get_dev_status, \ - .get_cur_freq = kgsl_busmon_get_cur_freq, \ - } } } #endif