Loading drivers/devfreq/governor_bw_vbif.c +24 −8 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #include "governor.h" unsigned long (*extern_get_bw)(void) = NULL; unsigned long *dev_ab; static unsigned long dev_ib; DEFINE_MUTEX(df_lock); static struct devfreq *df; Loading @@ -29,12 +31,15 @@ static int devfreq_vbif_get_freq(struct devfreq *df, unsigned long *freq, u32 *flag) { if (extern_get_bw) { *freq = extern_get_bw(); return 0; } else { return -ENODEV; /* If the IB isn't set yet, check if it should be non-zero. */ if (!dev_ib && extern_get_bw) { dev_ib = extern_get_bw(); if (dev_ab) *dev_ab = dev_ib / 4; } *freq = dev_ib; return 0; } /* Loading @@ -47,14 +52,15 @@ void devfreq_vbif_register_callback(void *p) extern_get_bw = p; } int devfreq_vbif_update_bw(void) int devfreq_vbif_update_bw(unsigned long ib, unsigned long ab) { int ret = 0; mutex_lock(&df_lock); if (df) { mutex_lock(&df->lock); dev_ib = ib; *dev_ab = ab; ret = update_devfreq(df); mutex_unlock(&df->lock); } Loading @@ -66,14 +72,24 @@ static int devfreq_vbif_ev_handler(struct devfreq *devfreq, unsigned int event, void *data) { int ret; struct devfreq_dev_status stat; switch (event) { case DEVFREQ_GOV_START: mutex_lock(&df_lock); df = devfreq; if (df->profile->get_dev_status) ret = df->profile->get_dev_status(df->dev.parent, &stat); else ret = 0; if (ret || !stat.private_data) pr_warn("Device doesn't take AB votes!\n"); else dev_ab = stat.private_data; mutex_unlock(&df_lock); ret = devfreq_vbif_update_bw(); ret = devfreq_vbif_update_bw(0, 0); if (ret) { pr_err("Unable to update BW! Gov start failed!\n"); return ret; Loading drivers/devfreq/governor_gpubw_mon.c +3 −2 Original line number Diff line number Diff line Loading @@ -63,14 +63,14 @@ static int devfreq_gpubw_get_target(struct devfreq *df, priv->bus.total_time += stats.total_time; priv->bus.gpu_time += stats.busy_time; priv->bus.ram_time += b.ram_time; priv->bus.ram_time += b.ram_wait; priv->bus.ram_wait += b.ram_wait; level = devfreq_get_freq_level(df, stats.current_frequency); if (priv->bus.total_time < LONG_FLOOR) return result; norm_cycles = (unsigned int)priv->bus.ram_time / norm_cycles = (unsigned int)(priv->bus.ram_time + priv->bus.ram_wait) / (unsigned int) priv->bus.total_time; gpu_percent = (100 * (unsigned int)priv->bus.gpu_time) / (unsigned int) priv->bus.total_time; Loading Loading @@ -100,6 +100,7 @@ static int devfreq_gpubw_get_target(struct devfreq *df, priv->bus.total_time = 0; priv->bus.gpu_time = 0; priv->bus.ram_time = 0; priv->bus.ram_wait = 0; return result; } Loading drivers/gpu/msm/kgsl_pwrctrl.c +37 −2 Original line number Diff line number Diff line Loading @@ -50,6 +50,9 @@ #define KGSL_MAX_BUSLEVELS 20 #define DEFAULT_BUS_P 25 #define DEFAULT_BUS_DIV (100 / DEFAULT_BUS_P) struct clk_pair { const char *name; uint map; Loading Loading @@ -96,6 +99,7 @@ static struct clk_pair clks[KGSL_MAX_CLKS] = { static unsigned int ib_votes[KGSL_MAX_BUSLEVELS]; static int last_vote_buslevel; static int max_vote_buslevel; static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, int requested_state); Loading @@ -114,6 +118,29 @@ static unsigned int kgsl_get_bw(void) return ib_votes[last_vote_buslevel]; } /** * _ab_buslevel_update() - Return latest msm bus AB vote * @pwr: Pointer to the kgsl_pwrctrl struct * @ab: Pointer to be updated with the calculated AB vote */ static void _ab_buslevel_update(struct kgsl_pwrctrl *pwr, unsigned long *ab) { unsigned int ib = ib_votes[last_vote_buslevel]; unsigned int max_bw = ib_votes[max_vote_buslevel]; if (!ab) return; if (ib == 0) *ab = 0; else if (!pwr->bus_percent_ab) *ab = DEFAULT_BUS_P * ib / 100; else *ab = (pwr->bus_percent_ab * max_bw) / 100; if (*ab > ib) *ab = ib; } /** * _adjust_pwrlevel() - Given a requested power level do bounds checking on the * constraints and return the nearest possible level Loading Loading @@ -167,6 +194,7 @@ void kgsl_pwrctrl_buslevel_update(struct kgsl_device *device, struct kgsl_pwrctrl *pwr = &device->pwrctrl; int cur = pwr->pwrlevels[pwr->active_pwrlevel].bus_freq; int buslevel = 0; unsigned long ab; if (!pwr->pcl) return; /* the bus should be ON to update the active frequency */ Loading @@ -186,10 +214,12 @@ void kgsl_pwrctrl_buslevel_update(struct kgsl_device *device, } trace_kgsl_buslevel(device, pwr->active_pwrlevel, buslevel); last_vote_buslevel = buslevel; /* buslevel is the IB vote, update the AB */ _ab_buslevel_update(pwr, &ab); /* vote for ocmem */ msm_bus_scale_client_update_request(pwr->pcl, buslevel); /* ask a governor to vote on behalf of us */ devfreq_vbif_update_bw(); devfreq_vbif_update_bw(ib_votes[last_vote_buslevel], ab); } EXPORT_SYMBOL(kgsl_pwrctrl_buslevel_update); Loading Loading @@ -307,6 +337,7 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device, * frequency increases. */ pwr->bus_mod = 0; pwr->bus_percent_ab = 0; kgsl_pwrctrl_buslevel_update(device, true); pwrlevel = &pwr->pwrlevels[pwr->active_pwrlevel]; Loading Loading @@ -1427,11 +1458,15 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) struct msm_bus_vectors *vector = &usecase->vectors[0]; if (vector->dst == MSM_BUS_SLAVE_EBI_CH0 && vector->ib != 0) { if (i < KGSL_MAX_BUSLEVELS) if (i < KGSL_MAX_BUSLEVELS) { /* Convert bytes to Mbytes. */ ib_votes[i] = DIV_ROUND_UP_ULL(vector->ib, 1048576) - 1; if (ib_votes[i] > ib_votes[max_vote_buslevel]) max_vote_buslevel = i; } for (k = 0; k < n; k++) if (vector->ib == pwr->bus_ib[k]) { Loading drivers/gpu/msm/kgsl_pwrctrl.h +2 −0 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ struct kgsl_pwr_constraint { * @pm_qos_wakeup_latency - allowed CPU latency in microseconds during wakeup * @bus_control - true if the bus calculation is independent * @bus_mod - modifier from the current power level for the bus vote * @bus_percent_ab - current percent of total possible bus usage * @bus_index - default bus index into the bus_ib table * @bus_ib - the set of unique ib requests needed for the bus calculation * @constraint - currently active power constraint Loading Loading @@ -145,6 +146,7 @@ struct kgsl_pwrctrl { unsigned int pm_qos_wakeup_latency; bool bus_control; int bus_mod; unsigned int bus_percent_ab; struct device *devbw; unsigned int bus_index[KGSL_MAX_PWRLEVELS]; uint64_t bus_ib[KGSL_MAX_PWRLEVELS]; Loading drivers/gpu/msm/kgsl_pwrscale.c +11 −8 Original line number Diff line number Diff line Loading @@ -26,6 +26,13 @@ static void do_devfreq_suspend(struct work_struct *work); static void do_devfreq_resume(struct work_struct *work); static void do_devfreq_notify(struct work_struct *work); /* * These variables are used to keep the latest data * returned by kgsl_devfreq_get_dev_status */ static struct xstats last_xstats; static struct devfreq_dev_status last_status = { .private_data = &last_xstats }; /* * kgsl_pwrscale_sleep - notify governor that device is going off * @device: The device Loading Loading @@ -61,6 +68,7 @@ void kgsl_pwrscale_wake(struct kgsl_device *device) /* clear old stats before waking */ memset(&device->pwrscale.accum_stats, 0, sizeof(device->pwrscale.accum_stats)); memset(&last_xstats, 0, sizeof(last_xstats)); /* and any hw activity from waking up*/ device->ftbl->power_stats(device, &stats); Loading Loading @@ -264,13 +272,6 @@ int kgsl_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) } EXPORT_SYMBOL(kgsl_devfreq_target); /* * These variables are used to keep the latest data * returned by kgsl_devfreq_get_dev_status */ struct xstats last_xstats; struct devfreq_dev_status last_status = { .private_data = &last_xstats }; /* * kgsl_devfreq_get_dev_status - devfreq_dev_profile.get_dev_status callback * @dev: see devfreq.h Loading Loading @@ -488,8 +489,10 @@ int kgsl_busmon_target(struct device *dev, unsigned long *freq, u32 flags) ((pwr_level->bus_freq + pwr->bus_mod) > pwr_level->bus_min)) pwr->bus_mod--; if (pwr->bus_mod != b) if (pwr->bus_mod != b) { pwr->bus_percent_ab = device->pwrscale.bus_profile.percent_ab; kgsl_pwrctrl_buslevel_update(device, true); } mutex_unlock(&device->mutex); return 0; Loading Loading
drivers/devfreq/governor_bw_vbif.c +24 −8 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #include "governor.h" unsigned long (*extern_get_bw)(void) = NULL; unsigned long *dev_ab; static unsigned long dev_ib; DEFINE_MUTEX(df_lock); static struct devfreq *df; Loading @@ -29,12 +31,15 @@ static int devfreq_vbif_get_freq(struct devfreq *df, unsigned long *freq, u32 *flag) { if (extern_get_bw) { *freq = extern_get_bw(); return 0; } else { return -ENODEV; /* If the IB isn't set yet, check if it should be non-zero. */ if (!dev_ib && extern_get_bw) { dev_ib = extern_get_bw(); if (dev_ab) *dev_ab = dev_ib / 4; } *freq = dev_ib; return 0; } /* Loading @@ -47,14 +52,15 @@ void devfreq_vbif_register_callback(void *p) extern_get_bw = p; } int devfreq_vbif_update_bw(void) int devfreq_vbif_update_bw(unsigned long ib, unsigned long ab) { int ret = 0; mutex_lock(&df_lock); if (df) { mutex_lock(&df->lock); dev_ib = ib; *dev_ab = ab; ret = update_devfreq(df); mutex_unlock(&df->lock); } Loading @@ -66,14 +72,24 @@ static int devfreq_vbif_ev_handler(struct devfreq *devfreq, unsigned int event, void *data) { int ret; struct devfreq_dev_status stat; switch (event) { case DEVFREQ_GOV_START: mutex_lock(&df_lock); df = devfreq; if (df->profile->get_dev_status) ret = df->profile->get_dev_status(df->dev.parent, &stat); else ret = 0; if (ret || !stat.private_data) pr_warn("Device doesn't take AB votes!\n"); else dev_ab = stat.private_data; mutex_unlock(&df_lock); ret = devfreq_vbif_update_bw(); ret = devfreq_vbif_update_bw(0, 0); if (ret) { pr_err("Unable to update BW! Gov start failed!\n"); return ret; Loading
drivers/devfreq/governor_gpubw_mon.c +3 −2 Original line number Diff line number Diff line Loading @@ -63,14 +63,14 @@ static int devfreq_gpubw_get_target(struct devfreq *df, priv->bus.total_time += stats.total_time; priv->bus.gpu_time += stats.busy_time; priv->bus.ram_time += b.ram_time; priv->bus.ram_time += b.ram_wait; priv->bus.ram_wait += b.ram_wait; level = devfreq_get_freq_level(df, stats.current_frequency); if (priv->bus.total_time < LONG_FLOOR) return result; norm_cycles = (unsigned int)priv->bus.ram_time / norm_cycles = (unsigned int)(priv->bus.ram_time + priv->bus.ram_wait) / (unsigned int) priv->bus.total_time; gpu_percent = (100 * (unsigned int)priv->bus.gpu_time) / (unsigned int) priv->bus.total_time; Loading Loading @@ -100,6 +100,7 @@ static int devfreq_gpubw_get_target(struct devfreq *df, priv->bus.total_time = 0; priv->bus.gpu_time = 0; priv->bus.ram_time = 0; priv->bus.ram_wait = 0; return result; } Loading
drivers/gpu/msm/kgsl_pwrctrl.c +37 −2 Original line number Diff line number Diff line Loading @@ -50,6 +50,9 @@ #define KGSL_MAX_BUSLEVELS 20 #define DEFAULT_BUS_P 25 #define DEFAULT_BUS_DIV (100 / DEFAULT_BUS_P) struct clk_pair { const char *name; uint map; Loading Loading @@ -96,6 +99,7 @@ static struct clk_pair clks[KGSL_MAX_CLKS] = { static unsigned int ib_votes[KGSL_MAX_BUSLEVELS]; static int last_vote_buslevel; static int max_vote_buslevel; static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, int requested_state); Loading @@ -114,6 +118,29 @@ static unsigned int kgsl_get_bw(void) return ib_votes[last_vote_buslevel]; } /** * _ab_buslevel_update() - Return latest msm bus AB vote * @pwr: Pointer to the kgsl_pwrctrl struct * @ab: Pointer to be updated with the calculated AB vote */ static void _ab_buslevel_update(struct kgsl_pwrctrl *pwr, unsigned long *ab) { unsigned int ib = ib_votes[last_vote_buslevel]; unsigned int max_bw = ib_votes[max_vote_buslevel]; if (!ab) return; if (ib == 0) *ab = 0; else if (!pwr->bus_percent_ab) *ab = DEFAULT_BUS_P * ib / 100; else *ab = (pwr->bus_percent_ab * max_bw) / 100; if (*ab > ib) *ab = ib; } /** * _adjust_pwrlevel() - Given a requested power level do bounds checking on the * constraints and return the nearest possible level Loading Loading @@ -167,6 +194,7 @@ void kgsl_pwrctrl_buslevel_update(struct kgsl_device *device, struct kgsl_pwrctrl *pwr = &device->pwrctrl; int cur = pwr->pwrlevels[pwr->active_pwrlevel].bus_freq; int buslevel = 0; unsigned long ab; if (!pwr->pcl) return; /* the bus should be ON to update the active frequency */ Loading @@ -186,10 +214,12 @@ void kgsl_pwrctrl_buslevel_update(struct kgsl_device *device, } trace_kgsl_buslevel(device, pwr->active_pwrlevel, buslevel); last_vote_buslevel = buslevel; /* buslevel is the IB vote, update the AB */ _ab_buslevel_update(pwr, &ab); /* vote for ocmem */ msm_bus_scale_client_update_request(pwr->pcl, buslevel); /* ask a governor to vote on behalf of us */ devfreq_vbif_update_bw(); devfreq_vbif_update_bw(ib_votes[last_vote_buslevel], ab); } EXPORT_SYMBOL(kgsl_pwrctrl_buslevel_update); Loading Loading @@ -307,6 +337,7 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device, * frequency increases. */ pwr->bus_mod = 0; pwr->bus_percent_ab = 0; kgsl_pwrctrl_buslevel_update(device, true); pwrlevel = &pwr->pwrlevels[pwr->active_pwrlevel]; Loading Loading @@ -1427,11 +1458,15 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) struct msm_bus_vectors *vector = &usecase->vectors[0]; if (vector->dst == MSM_BUS_SLAVE_EBI_CH0 && vector->ib != 0) { if (i < KGSL_MAX_BUSLEVELS) if (i < KGSL_MAX_BUSLEVELS) { /* Convert bytes to Mbytes. */ ib_votes[i] = DIV_ROUND_UP_ULL(vector->ib, 1048576) - 1; if (ib_votes[i] > ib_votes[max_vote_buslevel]) max_vote_buslevel = i; } for (k = 0; k < n; k++) if (vector->ib == pwr->bus_ib[k]) { Loading
drivers/gpu/msm/kgsl_pwrctrl.h +2 −0 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ struct kgsl_pwr_constraint { * @pm_qos_wakeup_latency - allowed CPU latency in microseconds during wakeup * @bus_control - true if the bus calculation is independent * @bus_mod - modifier from the current power level for the bus vote * @bus_percent_ab - current percent of total possible bus usage * @bus_index - default bus index into the bus_ib table * @bus_ib - the set of unique ib requests needed for the bus calculation * @constraint - currently active power constraint Loading Loading @@ -145,6 +146,7 @@ struct kgsl_pwrctrl { unsigned int pm_qos_wakeup_latency; bool bus_control; int bus_mod; unsigned int bus_percent_ab; struct device *devbw; unsigned int bus_index[KGSL_MAX_PWRLEVELS]; uint64_t bus_ib[KGSL_MAX_PWRLEVELS]; Loading
drivers/gpu/msm/kgsl_pwrscale.c +11 −8 Original line number Diff line number Diff line Loading @@ -26,6 +26,13 @@ static void do_devfreq_suspend(struct work_struct *work); static void do_devfreq_resume(struct work_struct *work); static void do_devfreq_notify(struct work_struct *work); /* * These variables are used to keep the latest data * returned by kgsl_devfreq_get_dev_status */ static struct xstats last_xstats; static struct devfreq_dev_status last_status = { .private_data = &last_xstats }; /* * kgsl_pwrscale_sleep - notify governor that device is going off * @device: The device Loading Loading @@ -61,6 +68,7 @@ void kgsl_pwrscale_wake(struct kgsl_device *device) /* clear old stats before waking */ memset(&device->pwrscale.accum_stats, 0, sizeof(device->pwrscale.accum_stats)); memset(&last_xstats, 0, sizeof(last_xstats)); /* and any hw activity from waking up*/ device->ftbl->power_stats(device, &stats); Loading Loading @@ -264,13 +272,6 @@ int kgsl_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) } EXPORT_SYMBOL(kgsl_devfreq_target); /* * These variables are used to keep the latest data * returned by kgsl_devfreq_get_dev_status */ struct xstats last_xstats; struct devfreq_dev_status last_status = { .private_data = &last_xstats }; /* * kgsl_devfreq_get_dev_status - devfreq_dev_profile.get_dev_status callback * @dev: see devfreq.h Loading Loading @@ -488,8 +489,10 @@ int kgsl_busmon_target(struct device *dev, unsigned long *freq, u32 flags) ((pwr_level->bus_freq + pwr->bus_mod) > pwr_level->bus_min)) pwr->bus_mod--; if (pwr->bus_mod != b) if (pwr->bus_mod != b) { pwr->bus_percent_ab = device->pwrscale.bus_profile.percent_ab; kgsl_pwrctrl_buslevel_update(device, true); } mutex_unlock(&device->mutex); return 0; Loading