diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index e9b656140363..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; @@ -3750,35 +3760,6 @@ static struct platform_driver adreno_platform_driver = { } }; -static const struct of_device_id busmon_match_table[] = { - { .compatible = "qcom,kgsl-busmon", .data = &device_3d0 }, - {} -}; - -static int adreno_busmon_probe(struct platform_device *pdev) -{ - struct kgsl_device *device; - const struct of_device_id *pdid = - of_match_device(busmon_match_table, &pdev->dev); - - if (pdid == NULL) - return -ENXIO; - - device = (struct kgsl_device *)pdid->data; - device->busmondev = &pdev->dev; - dev_set_drvdata(device->busmondev, device); - - return 0; -} - -static struct platform_driver kgsl_bus_platform_driver = { - .probe = adreno_busmon_probe, - .driver = { - .name = "kgsl-busmon", - .of_match_table = busmon_match_table, - } -}; - static int __init kgsl_3d_init(void) { int ret; @@ -3787,17 +3768,9 @@ static int __init kgsl_3d_init(void) if (ret) return ret; - ret = platform_driver_register(&kgsl_bus_platform_driver); - if (ret) { - kgsl_core_exit(); - return ret; - } - ret = platform_driver_register(&adreno_platform_driver); - if (ret) { - platform_driver_unregister(&kgsl_bus_platform_driver); + if (ret) kgsl_core_exit(); - } return ret; } @@ -3805,8 +3778,6 @@ static int __init kgsl_3d_init(void) static void __exit kgsl_3d_exit(void) { platform_driver_unregister(&adreno_platform_driver); - platform_driver_unregister(&kgsl_bus_platform_driver); - kgsl_core_exit(); } 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 9d14751fb74f..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; @@ -297,8 +296,6 @@ struct kgsl_device { int reset_counter; /* Track how many GPU core resets have occurred */ struct workqueue_struct *events_wq; - struct device *busmondev; /* pseudo dev for GPU BW voting governor */ - /* Number of active contexts seen globally for this device */ int active_context_count; struct kobject *gpu_sysfs_kobj; @@ -322,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 ab6b747e3719..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 @@ -654,22 +661,74 @@ static int opp_notify(struct notifier_block *nb, return 0; } +static void pwrscale_busmon_create(struct kgsl_device *device, + struct platform_device *pdev, unsigned long *table) +{ + 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; + + 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; + + dev_set_name(dev, "kgsl-busmon"); + if (device_register(dev)) + return; + + /* Build out the OPP table for the busmon device */ + for (i = 0; i < pwr->num_pwrlevels; i++) { + if (!pwr->pwrlevels[i].gpu_freq) + continue; + + dev_pm_opp_add(dev, pwr->pwrlevels[i].gpu_freq, 0); + } + + bus_devfreq = devfreq_add_device(dev, &pwrscale->bus_profile.profile, + "gpubw_mon", NULL); + + if (IS_ERR_OR_NULL(bus_devfreq)) { + dev_err(&pdev->dev, "Bus scaling not enabled\n"); + put_device(dev); + return; + } + + pwrscale->gpu_profile.bus_devfreq = bus_devfreq; +} + 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 devfreq *bus_devfreq = NULL; 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; @@ -677,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; } @@ -734,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); @@ -758,34 +810,9 @@ int kgsl_pwrscale_init(struct kgsl_device *device, struct platform_device *pdev, pwrscale->cooling_dev = NULL; pwrscale->gpu_profile.bus_devfreq = NULL; - if (data->bus.num) { - pwrscale->bus_profile.profile.max_state - = pwr->num_pwrlevels - 1; - pwrscale->bus_profile.profile.freq_table - = pwrscale->freq_table; - /* - * This is needed because devfreq expects the device - * to have an opp table handle to calculate the min/max - * frequency. - */ - ret = dev_pm_opp_of_add_table(device->busmondev); - /* - * Disable OPP which are not supported as per GPU freq plan. - * This is need to ensure freq_table specified in bus_profile - * above matches OPP table. - */ - kgsl_pwrctrl_disable_unused_opp(device, device->busmondev); - if (!ret) - bus_devfreq = devfreq_add_device(device->busmondev, - &pwrscale->bus_profile.profile, "gpubw_mon", - NULL); - - if (IS_ERR_OR_NULL(bus_devfreq)) - dev_err(device->dev, "Bus scaling not enabled\n"); - else - pwrscale->gpu_profile.bus_devfreq = bus_devfreq; - } + if (adreno_tz_data.bus.num) + pwrscale_busmon_create(device, pdev, pwrscale->freq_table); ret = sysfs_create_link(&device->dev->kobj, &devfreq->dev.kobj, "devfreq"); @@ -825,6 +852,12 @@ void kgsl_pwrscale_close(struct kgsl_device *device) pwr = &device->pwrctrl; pwrscale = &device->pwrscale; + + if (pwrscale->gpu_profile.bus_devfreq) { + devfreq_remove_device(pwrscale->gpu_profile.bus_devfreq); + put_device(&pwrscale->busmondev); + } + if (!pwrscale->devfreqptr) return; if (pwrscale->cooling_dev) diff --git a/drivers/gpu/msm/kgsl_pwrscale.h b/drivers/gpu/msm/kgsl_pwrscale.h index 212e7a6fb46f..51b13f0c394d 100644 --- a/drivers/gpu/msm/kgsl_pwrscale.h +++ b/drivers/gpu/msm/kgsl_pwrscale.h @@ -63,6 +63,8 @@ struct kgsl_pwrscale { bool ctxt_aware_enable; unsigned int ctxt_aware_target_pwrlevel; unsigned int ctxt_aware_busy_penalty; + /** @busmondev: A child device for the busmon governor */ + struct device busmondev; }; /** @@ -99,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