Commit e4c0f182 authored by wanghaibin's avatar wanghaibin Committed by Dongxu Sun
Browse files

virt_plat_dev: Register the virt platform device driver

virt inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8K8HP


CVE: NA

--------------------------------

This driver porbed the virt platform device by name, and
it just take up a few MSIs through the vp_irqdomain.

Signed-off-by: default avatarwanghaibin <wanghaibin.wang@huawei.com>
Signed-off-by: default avatarZenghui Yu <yuzenghui@huawei.com>
Signed-off-by: default avatarKunkun Jiang <jiangkunkun@huawei.com>
Signed-off-by: default avatarDongxu Sun <sundongxu3@huawei.com>
parent db0a347c
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -474,6 +474,15 @@ config HISI_HIKEY_USB
	  switching between the dual-role USB-C port and the USB-A host ports
	  using only one USB controller.

config VIRT_PLAT_DEV
	depends on KVM && ARM64 && ARCH_HISI
	default y
	tristate "virt platform device driver"
	help
	  Enable this configuration option to probe the virtual platform device,
	  which created for the Qemu emulated device to implement virtual MSI
	  direct injection.

source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
+1 −0
Original line number Diff line number Diff line
@@ -58,3 +58,4 @@ obj-$(CONFIG_HABANA_AI) += habanalabs/
obj-$(CONFIG_UACCE)		+= uacce/
obj-$(CONFIG_XILINX_SDFEC)	+= xilinx_sdfec.o
obj-$(CONFIG_HISI_HIKEY_USB)	+= hisi_hikey_usb.o
obj-$(CONFIG_VIRT_PLAT_DEV)	+= virt_plat_dev.o
+119 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2019-2020 HUAWEI TECHNOLOGIES CO., LTD., All Rights Reserved.
 * Author: Wanghaibin <wanghaibin.wang@huawei.com>
 */
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/msi.h>
#include <linux/platform_device.h>
#include <linux/uaccess.h>
#include <linux/device.h>

#define VIRT_DEV_DEBUG 1

#ifdef VIRT_DEV_DEBUG
#define virtdev_info(fmt, ...)	pr_info("virdev: " fmt, ## __VA_ARGS__)
#else
#define virtdev_info(fmt, ...)
#endif

static irqreturn_t virt_irq_handle(int irq, void *data)
{
	return IRQ_HANDLED;
}

static void virt_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
{
}

static int virt_device_probe(struct platform_device *pdev)
{
	struct msi_desc *desc;
	unsigned int *drvdata = dev_get_drvdata(&pdev->dev);
	unsigned int nvec = *drvdata;
	struct irq_domain *vp_irqdomain = vp_get_irq_domain();
	int ret;

	if (!vp_irqdomain)
		return -ENXIO;

	virtdev_info("Allocate platform msi irqs nvecs: %d\n", nvec);
	dev_set_msi_domain(&pdev->dev, vp_irqdomain);

	ret = platform_msi_domain_alloc_irqs(&pdev->dev, nvec,
					     virt_write_msi_msg);
	if (ret) {
		pr_err("Allocate platform msi irqs failed %d\n", ret);
		goto error;
	}

	virtdev_info("Allocate platform msi irqs succeed\n");
	for_each_msi_entry(desc, &pdev->dev) {
		virtdev_info("Request irq %d\n", desc->irq);
		ret = request_irq(desc->irq, virt_irq_handle, 0,
				  "virt_dev_host", pdev);
		if (ret) {
			pr_err("Request irq %d failed %d\n", desc->irq, ret);
			goto error_free_irqs;
		}
	}

	virtdev_info("Init virtual platform device driver successfully.\n");
	return 0;

error_free_irqs:
	for_each_msi_entry(desc, &pdev->dev)
		free_irq(desc->irq, pdev);

	platform_msi_domain_free_irqs(&pdev->dev);
error:
	return ret;
}

static int virt_device_remove(struct platform_device *pdev)
{
	struct msi_desc *desc;

	virtdev_info("%s\n", __func__);
	for_each_msi_entry(desc, &pdev->dev)
		free_irq(desc->irq, pdev);

	platform_msi_domain_free_irqs(&pdev->dev);

	return 0;
}

static struct platform_driver virtdev_driver = {
	.driver = {
		/* Using the device & driver name to match each other */
		.name = "virt_plat_dev",
	},
	.probe = virt_device_probe,
	.remove = virt_device_remove,
};

static int __init virtdev_init(void)
{
	int ret;

	ret = platform_driver_register(&virtdev_driver);
	if (ret) {
		pr_err("Register virtdev platform driver failed (%d)\n", ret);
		return ret;
	}

	virtdev_info("Register virtdev platform driver succeed.\n");
	return 0;
}
module_init(virtdev_init);

static void  __exit virtdev_exit(void)
{
	platform_driver_unregister(&virtdev_driver);
}
module_exit(virtdev_exit);

MODULE_LICENSE("GPL v2");