This interface driver is a helper driver allows other drivers to have a common interface with the Hyper-V PCI frontend driver.
Unified · Split
| @@ -7469,6 +7469,7 @@ F: drivers/hid/hid-hyperv.c · 7468 unmodified lines | |||
| 7469 | F: drivers/hv/ | 7469 | F: drivers/hv/ |
| 7470 | F: drivers/input/serio/hyperv-keyboard.c | 7470 | F: drivers/input/serio/hyperv-keyboard.c |
| 7471 | F: drivers/pci/controller/pci-hyperv.c | 7471 | F: drivers/pci/controller/pci-hyperv.c |
| 7472 | F: drivers/pci/controller/pci-hyperv-intf.c | ||
| 7472 | F: drivers/net/hyperv/ | 7473 | F: drivers/net/hyperv/ |
| 7473 | F: drivers/scsi/storvsc_drv.c | 7474 | F: drivers/scsi/storvsc_drv.c |
| 7474 | F: drivers/uio/uio_hv_generic.c | 7475 | F: drivers/uio/uio_hv_generic.c |
| @@ -182,6 +182,7 @@ config PCI_LABEL · 181 unmodified lines | |||
| 182 | config PCI_HYPERV | 182 | config PCI_HYPERV |
| 183 | tristate "Hyper-V PCI Frontend" | 183 | tristate "Hyper-V PCI Frontend" |
| 184 | depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64 | 184 | depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64 |
| 185 | select PCI_HYPERV_INTERFACE | ||
| 185 | help | 186 | help |
| 186 | The PCI device frontend driver allows the kernel to import arbitrary | 187 | The PCI device frontend driver allows the kernel to import arbitrary |
| 187 | PCI devices from a PCI backend to support PCI driver domains. | 188 | PCI devices from a PCI backend to support PCI driver domains. |
| @@ -281,5 +281,12 @@ config VMD · 280 unmodified lines | |||
| 281 | To compile this driver as a module, choose M here: the | 281 | To compile this driver as a module, choose M here: the |
| 282 | module will be called vmd. | 282 | module will be called vmd. |
| 283 | 283 | ||
| 284 | config PCI_HYPERV_INTERFACE | ||
| 285 | tristate "Hyper-V PCI Interface" | ||
| 286 | depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64 | ||
| 287 | help | ||
| 288 | The Hyper-V PCI Interface is a helper driver allows other drivers to | ||
| 289 | have a common interface with the Hyper-V PCI frontend driver. | ||
| 290 | |||
| 284 | source "drivers/pci/controller/dwc/Kconfig" | 291 | source "drivers/pci/controller/dwc/Kconfig" |
| 285 | endmenu | 292 | endmenu |
| @@ -4,6 +4,7 @@ obj-$(CONFIG_PCIE_CADENCE_HOST) += pcie-cadence-host.o · 3 unmodified lines | |||
| 4 | obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o | 4 | obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o |
| 5 | obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o | 5 | obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o |
| 6 | obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o | 6 | obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o |
| 7 | obj-$(CONFIG_PCI_HYPERV_INTERFACE) += pci-hyperv-intf.o | ||
| 7 | obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o | 8 | obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o |
| 8 | obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o | 9 | obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o |
| 9 | obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o | 10 | obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o |
| @@ -0,0 +1,67 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Copyright (c) Microsoft Corporation. | ||
| 4 | * | ||
| 5 | * Author: | ||
| 6 | * Haiyang Zhang <haiyangz@microsoft.com> | ||
| 7 | * | ||
| 8 | * This small module is a helper driver allows other drivers to | ||
| 9 | * have a common interface with the Hyper-V PCI frontend driver. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/hyperv.h> | ||
| 17 | |||
| 18 | struct hyperv_pci_block_ops hvpci_block_ops; | ||
| 19 | EXPORT_SYMBOL_GPL(hvpci_block_ops); | ||
| 20 | |||
| 21 | int hyperv_read_cfg_blk(struct pci_dev *dev, void *buf, unsigned int buf_len, | ||
| 22 | unsigned int block_id, unsigned int *bytes_returned) | ||
| 23 | { | ||
| 24 | if (!hvpci_block_ops.read_block) | ||
| 25 | return -EOPNOTSUPP; | ||
| 26 | |||
| 27 | return hvpci_block_ops.read_block(dev, buf, buf_len, block_id, | ||
| 28 | bytes_returned); | ||
| 29 | } | ||
| 30 | EXPORT_SYMBOL_GPL(hyperv_read_cfg_blk); | ||
| 31 | |||
| 32 | int hyperv_write_cfg_blk(struct pci_dev *dev, void *buf, unsigned int len, | ||
| 33 | unsigned int block_id) | ||
| 34 | { | ||
| 35 | if (!hvpci_block_ops.write_block) | ||
| 36 | return -EOPNOTSUPP; | ||
| 37 | |||
| 38 | return hvpci_block_ops.write_block(dev, buf, len, block_id); | ||
| 39 | } | ||
| 40 | EXPORT_SYMBOL_GPL(hyperv_write_cfg_blk); | ||
| 41 | |||
| 42 | int hyperv_reg_block_invalidate(struct pci_dev *dev, void *context, | ||
| 43 | void (*block_invalidate)(void *context, | ||
| 44 | u64 block_mask)) | ||
| 45 | { | ||
| 46 | if (!hvpci_block_ops.reg_blk_invalidate) | ||
| 47 | return -EOPNOTSUPP; | ||
| 48 | |||
| 49 | return hvpci_block_ops.reg_blk_invalidate(dev, context, | ||
| 50 | block_invalidate); | ||
| 51 | } | ||
| 52 | EXPORT_SYMBOL_GPL(hyperv_reg_block_invalidate); | ||
| 53 | |||
| 54 | static void __exit exit_hv_pci_intf(void) | ||
| 55 | { | ||
| 56 | } | ||
| 57 | |||
| 58 | static int __init init_hv_pci_intf(void) | ||
| 59 | { | ||
| 60 | return 0; | ||
| 61 | } | ||
| 62 | |||
| 63 | module_init(init_hv_pci_intf); | ||
| 64 | module_exit(exit_hv_pci_intf); | ||
| 65 | |||
| 66 | MODULE_DESCRIPTION("Hyper-V PCI Interface"); | ||
| 67 | MODULE_LICENSE("GPL v2"); | ||
| @@ -983,7 +983,6 @@ int hv_read_config_block(struct pci_dev *pdev, void *buf, unsigned int len, · 982 unmodified lines | |||
| 983 | *bytes_returned = comp_pkt.bytes_returned; | 983 | *bytes_returned = comp_pkt.bytes_returned; |
| 984 | return 0; | 984 | return 0; |
| 985 | } | 985 | } |
| 986 | EXPORT_SYMBOL(hv_read_config_block); | ||
| 987 | 986 | ||
| 988 | /** | 987 | /** |
| 989 | * hv_pci_write_config_compl() - Invoked when a response packet for a write | 988 | * hv_pci_write_config_compl() - Invoked when a response packet for a write |
| @@ -1070,7 +1069,6 @@ int hv_write_config_block(struct pci_dev *pdev, void *buf, unsigned int len, · 80 unmodified lines | |||
| 1070 | 1069 | ||
| 1071 | return 0; | 1070 | return 0; |
| 1072 | } | 1071 | } |
| 1073 | EXPORT_SYMBOL(hv_write_config_block); | ||
| 1074 | 1072 | ||
| 1075 | /** | 1073 | /** |
| 1076 | * hv_register_block_invalidate() - Invoked when a config block invalidation | 1074 | * hv_register_block_invalidate() - Invoked when a config block invalidation |
| @@ -1101,7 +1099,6 @@ int hv_register_block_invalidate(struct pci_dev *pdev, void *context, · 24 unmodified lines | |||
| 1101 | return 0; | 1099 | return 0; |
| 1102 | 1100 | ||
| 1103 | } | 1101 | } |
| 1104 | EXPORT_SYMBOL(hv_register_block_invalidate); | ||
| 1105 | 1102 | ||
| 1106 | /* Interrupt management hooks */ | 1103 | /* Interrupt management hooks */ |
| 1107 | static void hv_int_desc_free(struct hv_pci_dev *hpdev, | 1104 | static void hv_int_desc_free(struct hv_pci_dev *hpdev, |
| @@ -3045,10 +3042,19 @@ static struct hv_driver hv_pci_drv = { · 1937 unmodified lines | |||
| 3045 | static void __exit exit_hv_pci_drv(void) | 3042 | static void __exit exit_hv_pci_drv(void) |
| 3046 | { | 3043 | { |
| 3047 | vmbus_driver_unregister(&hv_pci_drv); | 3044 | vmbus_driver_unregister(&hv_pci_drv); |
| 3045 | |||
| 3046 | hvpci_block_ops.read_block = NULL; | ||
| 3047 | hvpci_block_ops.write_block = NULL; | ||
| 3048 | hvpci_block_ops.reg_blk_invalidate = NULL; | ||
| 3048 | } | 3049 | } |
| 3049 | 3050 | ||
| 3050 | static int __init init_hv_pci_drv(void) | 3051 | static int __init init_hv_pci_drv(void) |
| 3051 | { | 3052 | { |
| 3053 | /* Initialize PCI block r/w interface */ | ||
| 3054 | hvpci_block_ops.read_block = hv_read_config_block; | ||
| 3055 | hvpci_block_ops.write_block = hv_write_config_block; | ||
| 3056 | hvpci_block_ops.reg_blk_invalidate = hv_register_block_invalidate; | ||
| 3057 | |||
| 3052 | return vmbus_driver_register(&hv_pci_drv); | 3058 | return vmbus_driver_register(&hv_pci_drv); |
| 3053 | } | 3059 | } |
| 3054 | 3060 | ||
| @@ -1579,18 +1579,32 @@ hv_pkt_iter_next(struct vmbus_channel *channel, · 1578 unmodified lines | |||
| 1579 | pkt = hv_pkt_iter_next(channel, pkt)) | 1579 | pkt = hv_pkt_iter_next(channel, pkt)) |
| 1580 | 1580 | ||
| 1581 | /* | 1581 | /* |
| 1582 | * Functions for passing data between SR-IOV PF and VF drivers. The VF driver | 1582 | * Interface for passing data between SR-IOV PF and VF drivers. The VF driver |
| 1583 | * sends requests to read and write blocks. Each block must be 128 bytes or | 1583 | * sends requests to read and write blocks. Each block must be 128 bytes or |
| 1584 | * smaller. Optionally, the VF driver can register a callback function which | 1584 | * smaller. Optionally, the VF driver can register a callback function which |
| 1585 | * will be invoked when the host says that one or more of the first 64 block | 1585 | * will be invoked when the host says that one or more of the first 64 block |
| 1586 | * IDs is "invalid" which means that the VF driver should reread them. | 1586 | * IDs is "invalid" which means that the VF driver should reread them. |
| 1587 | */ | 1587 | */ |
| 1588 | #define HV_CONFIG_BLOCK_SIZE_MAX 128 | 1588 | #define HV_CONFIG_BLOCK_SIZE_MAX 128 |
| 1589 | int hv_read_config_block(struct pci_dev *dev, void *buf, unsigned int buf_len, | 1589 | |
| 1590 | unsigned int block_id, unsigned int *bytes_returned); | 1590 | int hyperv_read_cfg_blk(struct pci_dev *dev, void *buf, unsigned int buf_len, |
| 1591 | int hv_write_config_block(struct pci_dev *dev, void *buf, unsigned int len, | 1591 | unsigned int block_id, unsigned int *bytes_returned); |
| 1592 | unsigned int block_id); | 1592 | int hyperv_write_cfg_blk(struct pci_dev *dev, void *buf, unsigned int len, |
| 1593 | int hv_register_block_invalidate(struct pci_dev *dev, void *context, | 1593 | unsigned int block_id); |
| 1594 | void (*block_invalidate)(void *context, | 1594 | int hyperv_reg_block_invalidate(struct pci_dev *dev, void *context, |
| 1595 | u64 block_mask)); | 1595 | void (*block_invalidate)(void *context, |
| 1596 | u64 block_mask)); | ||
| 1597 | |||
| 1598 | struct hyperv_pci_block_ops { | ||
| 1599 | int (*read_block)(struct pci_dev *dev, void *buf, unsigned int buf_len, | ||
| 1600 | unsigned int block_id, unsigned int *bytes_returned); | ||
| 1601 | int (*write_block)(struct pci_dev *dev, void *buf, unsigned int len, | ||
| 1602 | unsigned int block_id); | ||
| 1603 | int (*reg_blk_invalidate)(struct pci_dev *dev, void *context, | ||
| 1604 | void (*block_invalidate)(void *context, | ||
| 1605 | u64 block_mask)); | ||
| 1606 | }; | ||
| 1607 | |||
| 1608 | extern struct hyperv_pci_block_ops hvpci_block_ops; | ||
| 1609 | |||
| 1596 | #endif /* _HYPERV_H */ | 1610 | #endif /* _HYPERV_H */ |