static int vmbus_bus_init()

in vmbus_drv.c [1494:1601]


static int vmbus_bus_init(void)
{
	int ret;

	ret = hv_init();
	if (ret != 0) {
		pr_err("Unable to initialize the hypervisor - 0x%x\n", ret);
		return ret;
	}

	ret = bus_register(&hv_bus);
	if (ret)
		return ret;

	/*
	 * VMbus interrupts are best modeled as per-cpu interrupts. If
	 * on an architecture with support for per-cpu IRQs (e.g. ARM64),
	 * allocate a per-cpu IRQ using standard Linux kernel functionality.
	 * If not on such an architecture (e.g., x86/x64), then rely on
	 * code in the arch-specific portion of the code tree to connect
	 * the VMbus interrupt handler.
	 */

	if (vmbus_irq == -1) {
		hv_setup_vmbus_handler(vmbus_isr);
	} else {
		vmbus_evt = alloc_percpu(long);
		ret = request_percpu_irq(vmbus_irq, vmbus_percpu_isr,
				"Hyper-V VMbus", vmbus_evt);
		if (ret) {
			pr_err("Can't request Hyper-V VMbus IRQ %d, Err %d",
					vmbus_irq, ret);
			free_percpu(vmbus_evt);
			goto err_setup;
		}
	}

	ret = hv_synic_alloc();
	if (ret)
		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);
	if (ret < 0)
		goto err_cpuhp;
	hyperv_cpuhp_online = ret;

	ret = vmbus_connect();
	if (ret)
		goto err_connect;

	/*
	 * Only register if the crash MSRs are available
	 */
	if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
		u64 hyperv_crash_ctl;
		/*
		 * Sysctl registration is not fatal, since by default
		 * reporting is enabled.
		 */
		hv_ctl_table_hdr = register_sysctl_table(hv_root_table);
		if (!hv_ctl_table_hdr)
			pr_err("Hyper-V: sysctl table register error");

		/*
		 * Register for panic kmsg callback only if the right
		 * capability is supported by the hypervisor.
		 */
		hyperv_crash_ctl = hv_get_register(HV_REGISTER_CRASH_CTL);
		if (hyperv_crash_ctl & HV_CRASH_CTL_CRASH_NOTIFY_MSG)
			hv_kmsg_dump_register();

		register_die_notifier(&hyperv_die_block);
	}

	/*
	 * Always register the panic notifier because we need to unload
	 * the VMbus channel connection to prevent any VMbus
	 * activity after the VM panics.
	 */
	atomic_notifier_chain_register(&panic_notifier_list,
			       &hyperv_panic_block);

	vmbus_request_offers();

	return 0;

err_connect:
	cpuhp_remove_state(hyperv_cpuhp_online);
err_cpuhp:
	hv_synic_free();
err_alloc:
	if (vmbus_irq == -1) {
		hv_remove_vmbus_handler();
	} else {
		free_percpu_irq(vmbus_irq, vmbus_evt);
		free_percpu(vmbus_evt);
	}
err_setup:
	bus_unregister(&hv_bus);
	unregister_sysctl_table(hv_ctl_table_hdr);
	hv_ctl_table_hdr = NULL;
	return ret;
}