Re: [PATCH v10 04/27] clocksource: Add a new timer-ingenic driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Thierry,

Le ven. 8 mars 2019 à 7:22, Thierry Reding <thierry.reding@xxxxxxxxx> a écrit :
On Mon, Mar 04, 2019 at 07:13:05PM +0100, Paul Cercueil wrote:
 Hi Thierry,

On Mon, Mar 4, 2019 at 1:22 PM, Thierry Reding <thierry.reding@xxxxxxxxx>
 wrote:
 > On Sat, Mar 02, 2019 at 08:33:50PM -0300, Paul Cercueil wrote:
 > [...]
 > >  diff --git a/drivers/clocksource/ingenic-timer.c
 > > b/drivers/clocksource/ingenic-timer.c
[...]
 > >  +static u64 notrace ingenic_tcu_timer_read(void)
 > >  +{
 > >  +	unsigned int channel = ingenic_tcu->cs_channel;
 > >  +	u16 count;
 > >  +
 > >  +	count = readw(ingenic_tcu_base + TCU_REG_TCNTc(channel));
 >
 > Can't yo do this via the regmap?

I could, but for the sched_clock to be precise the function must return as fast as possible. That's the rationale behind the use of readw() here.

That's also the reason why ingenic_tcu_base is global and exported, so
 that the OS Timer driver can use it as well.

Is the path through the regmap really significantly slower than the
direct register access? Anyway, if you need the global anyway, might as
well use it.

About 10% slower.

[...]
> > + // Register the sched_clock at the very end as there's no way to
 > > undo it
 > >  +	rate = clk_get_rate(tcu->cs_clk);
 > >  +	sched_clock_register(ingenic_tcu_timer_read, 16, rate);
 >
> Oh wow... so you managed to nicely encapsulate everything and now this > seems to be the only reason why you need to rely on global variables.
 >
> That's unfortunate. I suppose we could go and add a void *data parameter > to sched_clock_register() and pass that to the read() function. That way > you could make this completely independent of global variables, but > there are 73 callers of sched_clock_register() and they are spread all
 > over the place, so sounds a bit daunting to me.

 Yes, that's the main reason behind the use of a global variables.
Is there a way we could introduce another callback, e.g. .read_value(),
 that would receive a void *param? Then the current .read() callback
 can be deprecated and the 73 callers can be migrated later.

Yeah, I suppose that would be possible. I'll defer to Daniel and Thomas
on this. They may not consider this important enough.

 > >  +
 > >  +	return 0;
 > >  +
 > >  +err_tcu_clocksource_cleanup:
 > >  +	ingenic_tcu_clocksource_cleanup(tcu);
 > >  +err_tcu_clk_cleanup:
 > >  +	ingenic_tcu_clk_cleanup(tcu, np);
 > >  +err_tcu_intc_cleanup:
 > >  +	ingenic_tcu_intc_cleanup(tcu);
 > >  +err_clk_disable:
 > >  +	clk_disable_unprepare(tcu->clk);
 > >  +err_clk_put:
 > >  +	clk_put(tcu->clk);
 > >  +err_free_regmap:
 > >  +	regmap_exit(tcu->map);
 > >  +err_iounmap:
 > >  +	iounmap(base);
 > >  +	release_mem_region(res.start, resource_size(&res));
 > >  +err_free_ingenic_tcu:
 > >  +	kfree(tcu);
 > >  +	return ret;
 > >  +}
 > >  +
 > >  +TIMER_OF_DECLARE(jz4740_tcu_intc,  "ingenic,jz4740-tcu",
 > > ingenic_tcu_init);
 > >  +TIMER_OF_DECLARE(jz4725b_tcu_intc, "ingenic,jz4725b-tcu",
 > > ingenic_tcu_init);
 > >  +TIMER_OF_DECLARE(jz4770_tcu_intc,  "ingenic,jz4770-tcu",
 > > ingenic_tcu_init);
 > >  +
 > >  +
> > +static int __init ingenic_tcu_probe(struct platform_device *pdev)
 > >  +{
 > >  +	platform_set_drvdata(pdev, ingenic_tcu);
 >
 > Then there's also this. Oh well... nevermind then.

 The content of ingenic_tcu_platform_init() could be moved inside
ingenic_tcu_init(). But can we get a hold of the struct device before the probe function is called? That would allow to set the drvdata and regmap
 without relying on global state.

I'm not sure if the driver core is ready at this point. It's likely it
isn't, otherwise there'd be no need for TIMER_OF_DECLARE(), really. I
also vaguely recall looking into this a few years ago because of some
similar work I was but I eventually gave up because I couldn't find a
way that would allow both the code to execute early enough and still
use the regular driver model.

Platform device become available at arch_initcall_sync (3s), while the
TIMER_OF_DECLARE code runs way earlier than any of the initcalls, so I
don't think there's a way to do it. Unless perhaps if the timers can
be initialized later. I'm not sure if that's possible, and might not be
worth it just for the sake of being pedantic.

Thierry

I think for the time being I can't really go around using the global variables.
Hopefully that's something that can be fixed in the future.

-Paul





[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux