[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 3/5] Add MSI capability to the pciback driver.
This is a reverse commit of a previous patch that disabled the functionality. It is essentially a copy of the MSI functionality from the linux-2.6.18.hg tree. Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> --- drivers/xen/pciback/Makefile | 1 + drivers/xen/pciback/conf_space_capability_msi.c | 79 +++++++++++++++++++++++ drivers/xen/pciback/pci_stub.c | 15 ++++ drivers/xen/pciback/pciback.h | 14 ++++ drivers/xen/pciback/pciback_ops.c | 14 ++++ 5 files changed, 123 insertions(+), 0 deletions(-) create mode 100644 drivers/xen/pciback/conf_space_capability_msi.c diff --git a/drivers/xen/pciback/Makefile b/drivers/xen/pciback/Makefile index a99bdaa..106dae7 100644 --- a/drivers/xen/pciback/Makefile +++ b/drivers/xen/pciback/Makefile @@ -6,6 +6,7 @@ pciback-y += conf_space.o conf_space_header.o \ conf_space_capability_vpd.o \ conf_space_capability_pm.o \ conf_space_quirks.o +pciback-$(CONFIG_PCI_MSI) += conf_space_capability_msi.o pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o pciback-$(CONFIG_XEN_PCIDEV_BACKEND_SLOT) += slot.o pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o diff --git a/drivers/xen/pciback/conf_space_capability_msi.c b/drivers/xen/pciback/conf_space_capability_msi.c new file mode 100644 index 0000000..762e396 --- /dev/null +++ b/drivers/xen/pciback/conf_space_capability_msi.c @@ -0,0 +1,79 @@ +/* + * PCI Backend -- Configuration overlay for MSI capability + */ +#include <linux/pci.h> +#include <linux/slab.h> +#include "conf_space.h" +#include "conf_space_capability.h" +#include <xen/interface/io/pciif.h> +#include "pciback.h" + +int pciback_enable_msi(struct pciback_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op) +{ + int otherend = pdev->xdev->otherend_id; + int status; + + status = pci_enable_msi(dev); + + if (status) { + printk("error enable msi for guest %x status %x\n", otherend, status); + op->value = 0; + return XEN_PCI_ERR_op_failed; + } + + op->value = dev->irq; + return 0; +} + +int pciback_disable_msi(struct pciback_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op) +{ + pci_disable_msi(dev); + + op->value = dev->irq; + return 0; +} + +int pciback_enable_msix(struct pciback_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op) +{ + int i, result; + struct msix_entry *entries; + + if (op->value > SH_INFO_MAX_VEC) + return -EINVAL; + + entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL); + if (entries == NULL) + return -ENOMEM; + + for (i = 0; i < op->value; i++) { + entries[i].entry = op->msix_entries[i].entry; + entries[i].vector = op->msix_entries[i].vector; + } + + result = pci_enable_msix(dev, entries, op->value); + + for (i = 0; i < op->value; i++) { + op->msix_entries[i].entry = entries[i].entry; + op->msix_entries[i].vector = entries[i].vector; + } + + kfree(entries); + + op->value = result; + + return result; +} + +int pciback_disable_msix(struct pciback_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op) +{ + + pci_disable_msix(dev); + + op->value = dev->irq; + return 0; +} + diff --git a/drivers/xen/pciback/pci_stub.c b/drivers/xen/pciback/pci_stub.c index 5ea594b..88c742b 100644 --- a/drivers/xen/pciback/pci_stub.c +++ b/drivers/xen/pciback/pci_stub.c @@ -1173,6 +1173,21 @@ static ssize_t permissive_show(struct device_driver *drv, char *buf) DRIVER_ATTR(permissive, S_IRUSR | S_IWUSR, permissive_show, permissive_add); +#ifdef CONFIG_PCI_MSI + +int pciback_get_owner(struct pci_dev *dev) +{ + struct pcistub_device *psdev; + + psdev = pcistub_device_find(pci_domain_nr(dev->bus), dev->bus->number, + PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + + if (!psdev || !psdev->pdev) + return -1; + + return psdev->pdev->xdev->otherend_id; +} +#endif static void pcistub_exit(void) { diff --git a/drivers/xen/pciback/pciback.h b/drivers/xen/pciback/pciback.h index 421b81e..5e8e14e 100644 --- a/drivers/xen/pciback/pciback.h +++ b/drivers/xen/pciback/pciback.h @@ -104,6 +104,20 @@ void pciback_do_op(struct work_struct *data); int pciback_xenbus_register(void); void pciback_xenbus_unregister(void); +#ifdef CONFIG_PCI_MSI +int pciback_enable_msi(struct pciback_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op); + +int pciback_disable_msi(struct pciback_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op); + + +int pciback_enable_msix(struct pciback_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op); + +int pciback_disable_msix(struct pciback_device *pdev, + struct pci_dev *dev, struct xen_pci_op *op); +#endif extern int verbose_request; void test_and_schedule_op(struct pciback_device *pdev); diff --git a/drivers/xen/pciback/pciback_ops.c b/drivers/xen/pciback/pciback_ops.c index 834663d..6624faf 100644 --- a/drivers/xen/pciback/pciback_ops.c +++ b/drivers/xen/pciback/pciback_ops.c @@ -89,6 +89,20 @@ void pciback_do_op(struct work_struct *data) op->err = pciback_config_write(dev, op->offset, op->size, op->value); break; +#ifdef CONFIG_PCI_MSI + case XEN_PCI_OP_enable_msi: + op->err = pciback_enable_msi(pdev, dev, op); + break; + case XEN_PCI_OP_disable_msi: + op->err = pciback_disable_msi(pdev, dev, op); + break; + case XEN_PCI_OP_enable_msix: + op->err = pciback_enable_msix(pdev, dev, op); + break; + case XEN_PCI_OP_disable_msix: + op->err = pciback_disable_msix(pdev, dev, op); + break; +#endif default: op->err = XEN_PCI_ERR_not_implemented; break; -- 1.6.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |