Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: hv: Add a Hyper-V PCI interface driver for software backchannel interface

This interface driver is a helper driver allows other drivers to
have a common interface with the Hyper-V PCI frontend driver.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Haiyang Zhang and committed by
David S. Miller
348dd93e e5d2f910

+108 -11
+1
MAINTAINERS
··· 7469 7469 F: drivers/hv/ 7470 7470 F: drivers/input/serio/hyperv-keyboard.c 7471 7471 F: drivers/pci/controller/pci-hyperv.c 7472 + F: drivers/pci/controller/pci-hyperv-intf.c 7472 7473 F: drivers/net/hyperv/ 7473 7474 F: drivers/scsi/storvsc_drv.c 7474 7475 F: drivers/uio/uio_hv_generic.c
+1
drivers/pci/Kconfig
··· 182 182 config PCI_HYPERV 183 183 tristate "Hyper-V PCI Frontend" 184 184 depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64 185 + select PCI_HYPERV_INTERFACE 185 186 help 186 187 The PCI device frontend driver allows the kernel to import arbitrary 187 188 PCI devices from a PCI backend to support PCI driver domains.
+7
drivers/pci/controller/Kconfig
··· 281 281 To compile this driver as a module, choose M here: the 282 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 291 source "drivers/pci/controller/dwc/Kconfig" 285 292 endmenu
+1
drivers/pci/controller/Makefile
··· 4 4 obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o 5 5 obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o 6 6 obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o 7 + obj-$(CONFIG_PCI_HYPERV_INTERFACE) += pci-hyperv-intf.o 7 8 obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o 8 9 obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o 9 10 obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
+67
drivers/pci/controller/pci-hyperv-intf.c
··· 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");
+9 -3
drivers/pci/controller/pci-hyperv.c
··· 983 983 *bytes_returned = comp_pkt.bytes_returned; 984 984 return 0; 985 985 } 986 - EXPORT_SYMBOL(hv_read_config_block); 987 986 988 987 /** 989 988 * hv_pci_write_config_compl() - Invoked when a response packet for a write ··· 1069 1070 1070 1071 return 0; 1071 1072 } 1072 - EXPORT_SYMBOL(hv_write_config_block); 1073 1073 1074 1074 /** 1075 1075 * hv_register_block_invalidate() - Invoked when a config block invalidation ··· 1099 1101 return 0; 1100 1102 1101 1103 } 1102 - EXPORT_SYMBOL(hv_register_block_invalidate); 1103 1104 1104 1105 /* Interrupt management hooks */ 1105 1106 static void hv_int_desc_free(struct hv_pci_dev *hpdev, ··· 3042 3045 static void __exit exit_hv_pci_drv(void) 3043 3046 { 3044 3047 vmbus_driver_unregister(&hv_pci_drv); 3048 + 3049 + hvpci_block_ops.read_block = NULL; 3050 + hvpci_block_ops.write_block = NULL; 3051 + hvpci_block_ops.reg_blk_invalidate = NULL; 3045 3052 } 3046 3053 3047 3054 static int __init init_hv_pci_drv(void) 3048 3055 { 3056 + /* Initialize PCI block r/w interface */ 3057 + hvpci_block_ops.read_block = hv_read_config_block; 3058 + hvpci_block_ops.write_block = hv_write_config_block; 3059 + hvpci_block_ops.reg_blk_invalidate = hv_register_block_invalidate; 3060 + 3049 3061 return vmbus_driver_register(&hv_pci_drv); 3050 3062 } 3051 3063
+22 -8
include/linux/hyperv.h
··· 1579 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 1583 * sends requests to read and write blocks. Each block must be 128 bytes or 1584 1584 * smaller. Optionally, the VF driver can register a callback function which 1585 1585 * will be invoked when the host says that one or more of the first 64 block 1586 1586 * IDs is "invalid" which means that the VF driver should reread them. 1587 1587 */ 1588 1588 #define HV_CONFIG_BLOCK_SIZE_MAX 128 1589 - int hv_read_config_block(struct pci_dev *dev, void *buf, unsigned int buf_len, 1590 - unsigned int block_id, unsigned int *bytes_returned); 1591 - int hv_write_config_block(struct pci_dev *dev, void *buf, unsigned int len, 1592 - unsigned int block_id); 1593 - int hv_register_block_invalidate(struct pci_dev *dev, void *context, 1594 - void (*block_invalidate)(void *context, 1595 - u64 block_mask)); 1589 + 1590 + int hyperv_read_cfg_blk(struct pci_dev *dev, void *buf, unsigned int buf_len, 1591 + unsigned int block_id, unsigned int *bytes_returned); 1592 + int hyperv_write_cfg_blk(struct pci_dev *dev, void *buf, unsigned int len, 1593 + unsigned int block_id); 1594 + int hyperv_reg_block_invalidate(struct pci_dev *dev, void *context, 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 1610 #endif /* _HYPERV_H */