Hi,

On 19. 4. 17. 오전 12:23, Dmitry Osipenko wrote:
> 16.04.2019 8:56, Chanwoo Choi пишет:
>> Hi,
>>
>> It looks good to me to drop the primary interrupt handler
>> but I have some comments. Please check it.
>>
>> On 19. 4. 15. 오후 11:54, Dmitry Osipenko wrote:
>>> There is no real need in the primary interrupt handler, hence move
>>> everything to the secondary (threaded) handler. In a result locking
>>> is consistent now and there are no potential races with the interrupt
>>> handler because it is protected with the devfreq's mutex.
>>>
>>> Signed-off-by: Dmitry Osipenko <dig...@gmail.com>
>>> ---
>>>  drivers/devfreq/tegra-devfreq.c | 61 ++++++++++++---------------------
>>>  1 file changed, 22 insertions(+), 39 deletions(-)
>>>
>>> diff --git a/drivers/devfreq/tegra-devfreq.c 
>>> b/drivers/devfreq/tegra-devfreq.c
>>> index 2a1464098200..69b557df5084 100644
>>> --- a/drivers/devfreq/tegra-devfreq.c
>>> +++ b/drivers/devfreq/tegra-devfreq.c
>>> @@ -144,7 +144,6 @@ static struct tegra_devfreq_device_config 
>>> actmon_device_configs[] = {
>>>  struct tegra_devfreq_device {
>>>     const struct tegra_devfreq_device_config *config;
>>>     void __iomem *regs;
>>> -   spinlock_t lock;
>>>  
>>>     /* Average event count sampled in the last interrupt */
>>>     u32 avg_count;
>>> @@ -249,11 +248,8 @@ static void actmon_write_barrier(struct tegra_devfreq 
>>> *tegra)
>>>  static void actmon_isr_device(struct tegra_devfreq *tegra,
>>>                           struct tegra_devfreq_device *dev)
>>>  {
>>> -   unsigned long flags;
>>>     u32 intr_status, dev_ctrl;
>>>  
>>> -   spin_lock_irqsave(&dev->lock, flags);
>>> -
>>>     dev->avg_count = device_readl(dev, ACTMON_DEV_AVG_COUNT);
>>>     tegra_devfreq_update_avg_wmark(tegra, dev);
>>>  
>>> @@ -302,26 +298,6 @@ static void actmon_isr_device(struct tegra_devfreq 
>>> *tegra,
>>>     device_writel(dev, ACTMON_INTR_STATUS_CLEAR, ACTMON_DEV_INTR_STATUS);
>>>  
>>>     actmon_write_barrier(tegra);
>>> -
>>> -   spin_unlock_irqrestore(&dev->lock, flags);
>>> -}
>>> -
>>> -static irqreturn_t actmon_isr(int irq, void *data)
>>> -{
>>> -   struct tegra_devfreq *tegra = data;
>>> -   bool handled = false;
>>> -   unsigned int i;
>>> -   u32 val;
>>> -
>>> -   val = actmon_readl(tegra, ACTMON_GLB_STATUS);
>>> -   for (i = 0; i < ARRAY_SIZE(tegra->devices); i++) {
>>> -           if (val & tegra->devices[i].config->irq_mask) {
>>> -                   actmon_isr_device(tegra, tegra->devices + i);
>>> -                   handled = true;
>>> -           }
>>> -   }
>>> -
>>> -   return handled ? IRQ_WAKE_THREAD : IRQ_NONE;
>>>  }
>>>  
>>>  static unsigned long actmon_cpu_to_emc_rate(struct tegra_devfreq *tegra,
>>> @@ -348,35 +324,46 @@ static void actmon_update_target(struct tegra_devfreq 
>>> *tegra,
>>>     unsigned long cpu_freq = 0;
>>>     unsigned long static_cpu_emc_freq = 0;
>>>     unsigned int avg_sustain_coef;
>>> -   unsigned long flags;
>>> +   u32 avg_count;
>>>  
>>>     if (dev->config->avg_dependency_threshold) {
>>>             cpu_freq = cpufreq_get(0);
>>>             static_cpu_emc_freq = actmon_cpu_to_emc_rate(tegra, cpu_freq);
>>>     }
>>>  
>>> -   spin_lock_irqsave(&dev->lock, flags);
>>> -
>>> -   dev->target_freq = dev->avg_count / ACTMON_SAMPLING_PERIOD;
>>> +   avg_count = dev->avg_count;
>>> +   dev->target_freq = avg_count / ACTMON_SAMPLING_PERIOD;
>>
>> Actually, this change is not related to this patch.
>> Please keep the original code.
>>
>>>     avg_sustain_coef = 100 * 100 / dev->config->boost_up_threshold;
>>>     dev->target_freq = do_percent(dev->target_freq, avg_sustain_coef);
>>>     dev->target_freq += dev->boost_freq;
>>>  
>>> -   if (dev->avg_count >= dev->config->avg_dependency_threshold)
>>> +   if (avg_count >= dev->config->avg_dependency_threshold)
>>
>> ditto.
> 
> Good catch, it's a leftover from v1 that I forgot to revert. Thank you.
> 
> [snip]
> 
>>
>> When I review this patch, I have a question
>> about why tegra_actmon_rate_notify_cb is needed.
>>
>> tegra_actmon_rate_notify_cb() do something
>> when the clock rate of emc_clock is changed.
>> I think that 'emc_clock' is changed by this driver.
>> It means that the this driver can catch the change timing
>> of emc_clock rate without notifier. 
> 
> The devfreq driver isn't the only driver of the EMC clock rate. The devfreq 
> driver changes EMC freq dynamically based of on average memory usage 
> activity, but for some hardware units (like display controller for example) 
> there is a requirement for a minimum memory bandwidth (isochronous 
> transactions) and hence when display is waking up from suspend it immediately 
> requires an amount of memory bandwidth that could be higher than ACTMON 
> hardware unit suggests and besides the ACTMON's reaction is delayed by the 
> sampling period (12ms).

Thanks for explaining it. If EMC clock is used on multiple point,
I understand why the clock notifier is necessary.

> 
>> IMO, it is possible to call tegra_devfreq_update_wmark()
>> directly without clock notifier before calling
>> 'clk_set_min_rate()/clk_set_rate()' in the tegra_devfreq_target().
>>
>> With clock notifier, it cannot restore something for
>> tegra_devfreq_update_wmark(tegra, dev) when failed to
>> set the rate of emc_clk by 'clk_set_min_rate()/clk_set_rate()'.
> 
> The watermarks should be changed in accordance to the actual EMC clock rate. 
> Given that EMC rate could be changed by something else than the devfreq 
> driver, we need to re-adjust the watermarks to the actual values after the 
> EMC rate-change completion. Please note that the clock notifier uses the 
> POST_RATE_CHANGE event that happens only after successful completion of EMC 
> clock rate change.

I understand the needs of clock notifier. Thanks.

> 
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

Reply via email to