On Mon, Jul 29, 2024 at 12:57:18AM -0700, Saurabh Sengar wrote: > Currently on a very large system with 1780 CPUs, hv_acpi_init() takes > around 3 seconds to complete. This is because of sequential synic > initialization for each CPU performed by hv_synic_init(). > > Schedule these tasks parallelly so that each CPU executes hv_synic_init() > in parallel to take full advantage of multiple CPUs. > > This solution saves around 2 seconds of boot time on a 1780 CPU system, > which is around 66% improvement in the existing logic. > > Signed-off-by: Saurabh Sengar <ssengar@xxxxxxxxxxxxxxxxxxx> > --- Reviewed-by: Srivatsa S. Bhat (Microsoft) <srivatsa@xxxxxxxxxxxxx> Regards, Srivatsa Microsoft Linux Systems Group > [V2] > - used cpuhp_setup_state_nocalls_cpuslocked instead of internal function > - improve commit message and subject > - Added a comment for cpu hotplug callback > > > drivers/hv/vmbus_drv.c | 34 +++++++++++++++++++++++++++++++--- > 1 file changed, 31 insertions(+), 3 deletions(-) > > diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c > index c857dc3975be..f769b34445b8 100644 > --- a/drivers/hv/vmbus_drv.c > +++ b/drivers/hv/vmbus_drv.c > @@ -1306,6 +1306,13 @@ static irqreturn_t vmbus_percpu_isr(int irq, void *dev_id) > return IRQ_HANDLED; > } > > +static void vmbus_percpu_work(struct work_struct *work) > +{ > + unsigned int cpu = smp_processor_id(); > + > + hv_synic_init(cpu); > +} > + > /* > * vmbus_bus_init -Main vmbus driver initialization routine. > * > @@ -1316,7 +1323,8 @@ static irqreturn_t vmbus_percpu_isr(int irq, void *dev_id) > */ > static int vmbus_bus_init(void) > { > - int ret; > + int ret, cpu; > + struct work_struct __percpu *works; > > ret = hv_init(); > if (ret != 0) { > @@ -1355,12 +1363,32 @@ static int vmbus_bus_init(void) > if (ret) > goto err_alloc; > > + works = alloc_percpu(struct work_struct); > + if (!works) { > + ret = -ENOMEM; > + goto err_alloc; > + } > + > /* > * Initialize the per-cpu interrupt state and stimer state. > * Then connect to the host. > */ > - ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hyperv/vmbus:online", > - hv_synic_init, hv_synic_cleanup); > + cpus_read_lock(); > + for_each_online_cpu(cpu) { > + struct work_struct *work = per_cpu_ptr(works, cpu); > + > + INIT_WORK(work, vmbus_percpu_work); > + schedule_work_on(cpu, work); > + } > + > + for_each_online_cpu(cpu) > + flush_work(per_cpu_ptr(works, cpu)); > + > + /* register the callback for hotplug CPUs */ > + ret = cpuhp_setup_state_nocalls_cpuslocked(CPUHP_AP_ONLINE_DYN, "hyperv/vmbus:online", > + hv_synic_init, hv_synic_cleanup); > + cpus_read_unlock(); > + free_percpu(works); > if (ret < 0) > goto err_alloc; > hyperv_cpuhp_online = ret; > -- > 2.43.0 >