[PATCH v8 01/13] ARM: Add per-platform SMP/CPU-hotplug operations

Arnd Bergmann arnd at arndb.de
Wed Jun 13 17:33:28 EDT 2012


On Tuesday 12 June 2012, Marc Zyngier wrote:
> @@ -35,6 +36,9 @@ struct machine_desc {
>  	unsigned char		reserve_lp1 :1;	/* never has lp1	*/
>  	unsigned char		reserve_lp2 :1;	/* never has lp2	*/
>  	char			restart_mode;	/* default restart mode	*/
> +#ifdef CONFIG_SMP
> +	struct smp_ops		*smp_ops;	/* SMP operations	*/
> +#endif
>  	void			(*fixup)(struct tag *, char **,
>  					 struct meminfo *);
>  	void			(*reserve)(void);/* reserve mem blocks	*/
> @@ -50,6 +54,12 @@ struct machine_desc {
>  	void			(*restart)(char, const char *);
>  };
>  
> +#ifdef CONFIG_SMP
> +#define smp_ops(s)		.smp_ops = (&s),
> +#else
> +#define smp_ops(s)		/* empty */
> +#endif
> +

I think we should just leave these in unconditionally as before. The price
is one pointer per machine_desc, but the advantage is that we don't have
to use an ugly macro.

If people think the savings are worth doing the macro for, can we
at least kill the "," and the "&" in it, to make it more regular syntax?

> +struct smp_ops {
> +	struct smp_init_ops		init_ops;
> +	struct smp_secondary_ops	secondary_ops;
> +	struct smp_hotplug_ops		hotplug_ops;
> +};

Ok, I don't really mind this split so much, although it still feels
like it's making the structure more complicated than it should.

> +#ifdef CONFIG_SMP
> +#define smp_init_ops(prefix)		.init_ops = {			\
> +		.smp_init_cpus		= prefix##_smp_init_cpus,	\
> +		.smp_prepare_cpus	= prefix##_smp_prepare_cpus,	\
> +	},
> +
> +#define smp_secondary_ops(prefix)	.secondary_ops = {		\
> +		.smp_secondary_init	= prefix##_secondary_init,	\
> +		.smp_boot_secondary	= prefix##_boot_secondary,	\
> +	},
> +
> +extern void smp_ops_register(struct smp_ops *);
> +
> +#else
> +#define smp_init_ops(prefix)		.init_ops = {},
> +#define smp_secondary_ops(prefix)	.secondary_ops = {},
> +#define smp_ops_register(a)		do {} while(0)
> +#endif
> +
> +#ifdef CONFIG_HOTPLUG_CPU
> +#define smp_hotplug_ops(prefix)		.hotplug_ops = {	\
> +		.cpu_kill	= prefix##_cpu_kill,		\
> +		.cpu_die	= prefix##_cpu_die,		\
> +		.cpu_disable	= prefix##_cpu_disable,		\
> +	},
> +#else
> +#define smp_hotplug_ops(prefix)		.hotplug_ops = {},
> +#endif

But these macros are just horrible. The string concatenation makes it impossible
to grep for where the function pointers are actually used. Just open-code
the initialization, it's really not too much to ask to write something like

struct smp_ops vexpress_smp_ops = {
	.init_ops = {
		.smp_init_cpus		= vexpress_smp_init_cpus,
		.smp_prepare_cpus	= vexpress_smp_prepare_cpus,
	},
	.secondary_ops = {
		.smp_secondary_init	= vexpress_secondary_init,
		.smp_boot_secondary	= vexpress_boot_secondary,
	},
#ifdef CONFIG_HOTPLUG_CPU
	.hotplug_ops = {
		.cpu_kill		= vexpress_cpu_kill,
		.cpu_die		= vexpress_cpu_die,
		.cpu_disable		= vexpress_cpu_disable,
	},
#endif
};

Anyone can read this, and it's not all that much to write either. Whereas the macro
version requires everybody who wants to modify that code to understand all the
macros you introduced.

	Arnd



More information about the linux-arm-kernel mailing list