direct-io.hg

changeset 10969:9e061d0dc394

[PCI] back: New virtual pci backend: slot

This backend use a slot per pci device. Contrary to vpci two functions from
one slot appear as two slots. This is useful on ia64 because it doesn't scan
functions > 0 if function 0 does not exist.

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
author kaf24@firebug.cl.cam.ac.uk
date Tue Aug 08 10:17:42 2006 +0100 (2006-08-08)
parents 51c227428166
children ae14b5b77938
files buildconfigs/linux-defconfig_xen0_ia64 buildconfigs/linux-defconfig_xen0_x86_32 buildconfigs/linux-defconfig_xen0_x86_64 buildconfigs/linux-defconfig_xen_ia64 buildconfigs/linux-defconfig_xen_x86_32 buildconfigs/linux-defconfig_xen_x86_64 linux-2.6-xen-sparse/drivers/xen/Kconfig linux-2.6-xen-sparse/drivers/xen/pciback/Makefile linux-2.6-xen-sparse/drivers/xen/pciback/slot.c
line diff
     1.1 --- a/buildconfigs/linux-defconfig_xen0_ia64	Tue Aug 08 10:03:30 2006 +0100
     1.2 +++ b/buildconfigs/linux-defconfig_xen0_ia64	Tue Aug 08 10:17:42 2006 +0100
     1.3 @@ -1533,8 +1533,9 @@ CONFIG_XEN_BLKDEV_BACKEND=y
     1.4  # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
     1.5  CONFIG_XEN_NETDEV_LOOPBACK=y
     1.6  CONFIG_XEN_PCIDEV_BACKEND=y
     1.7 -CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
     1.8 +# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
     1.9  # CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
    1.10 +CONFIG_XEN_PCIDEV_BACKEND_SLOT=y
    1.11  # CONFIG_XEN_PCIDEV_BE_DEBUG is not set
    1.12  # CONFIG_XEN_TPMDEV_BACKEND is not set
    1.13  CONFIG_XEN_BLKDEV_FRONTEND=y
     2.1 --- a/buildconfigs/linux-defconfig_xen0_x86_32	Tue Aug 08 10:03:30 2006 +0100
     2.2 +++ b/buildconfigs/linux-defconfig_xen0_x86_32	Tue Aug 08 10:17:42 2006 +0100
     2.3 @@ -1320,6 +1320,7 @@ CONFIG_XEN_BACKEND=y
     2.4  CONFIG_XEN_PCIDEV_BACKEND=y
     2.5  # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
     2.6  CONFIG_XEN_PCIDEV_BACKEND_PASS=y
     2.7 +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set
     2.8  # CONFIG_XEN_PCIDEV_BE_DEBUG is not set
     2.9  CONFIG_XEN_BLKDEV_BACKEND=y
    2.10  CONFIG_XEN_BLKDEV_TAP=y
     3.1 --- a/buildconfigs/linux-defconfig_xen0_x86_64	Tue Aug 08 10:03:30 2006 +0100
     3.2 +++ b/buildconfigs/linux-defconfig_xen0_x86_64	Tue Aug 08 10:17:42 2006 +0100
     3.3 @@ -1261,6 +1261,7 @@ CONFIG_XEN_BACKEND=y
     3.4  CONFIG_XEN_PCIDEV_BACKEND=y
     3.5  # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
     3.6  CONFIG_XEN_PCIDEV_BACKEND_PASS=y
     3.7 +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set
     3.8  # CONFIG_XEN_PCIDEV_BE_DEBUG is not set
     3.9  CONFIG_XEN_BLKDEV_BACKEND=y
    3.10  CONFIG_XEN_BLKDEV_TAP=y
     4.1 --- a/buildconfigs/linux-defconfig_xen_ia64	Tue Aug 08 10:03:30 2006 +0100
     4.2 +++ b/buildconfigs/linux-defconfig_xen_ia64	Tue Aug 08 10:17:42 2006 +0100
     4.3 @@ -1539,8 +1539,9 @@ CONFIG_XEN_BLKDEV_BACKEND=y
     4.4  # CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set
     4.5  CONFIG_XEN_NETDEV_LOOPBACK=y
     4.6  CONFIG_XEN_PCIDEV_BACKEND=y
     4.7 -CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
     4.8 +# CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
     4.9  # CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
    4.10 +CONFIG_XEN_PCIDEV_BACKEND_SLOT=y
    4.11  # CONFIG_XEN_PCIDEV_BE_DEBUG is not set
    4.12  # CONFIG_XEN_TPMDEV_BACKEND is not set
    4.13  CONFIG_XEN_BLKDEV_FRONTEND=y
     5.1 --- a/buildconfigs/linux-defconfig_xen_x86_32	Tue Aug 08 10:03:30 2006 +0100
     5.2 +++ b/buildconfigs/linux-defconfig_xen_x86_32	Tue Aug 08 10:17:42 2006 +0100
     5.3 @@ -3021,6 +3021,7 @@ CONFIG_XEN_BACKEND=y
     5.4  CONFIG_XEN_PCIDEV_BACKEND=m
     5.5  CONFIG_XEN_PCIDEV_BACKEND_VPCI=y
     5.6  # CONFIG_XEN_PCIDEV_BACKEND_PASS is not set
     5.7 +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set
     5.8  # CONFIG_XEN_PCIDEV_BE_DEBUG is not set
     5.9  CONFIG_XEN_BLKDEV_BACKEND=y
    5.10  CONFIG_XEN_BLKDEV_TAP=y
     6.1 --- a/buildconfigs/linux-defconfig_xen_x86_64	Tue Aug 08 10:03:30 2006 +0100
     6.2 +++ b/buildconfigs/linux-defconfig_xen_x86_64	Tue Aug 08 10:17:42 2006 +0100
     6.3 @@ -2853,6 +2853,7 @@ CONFIG_XEN_BACKEND=y
     6.4  CONFIG_XEN_PCIDEV_BACKEND=m
     6.5  # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set
     6.6  CONFIG_XEN_PCIDEV_BACKEND_PASS=y
     6.7 +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set
     6.8  # CONFIG_XEN_PCIDEV_BE_DEBUG is not set
     6.9  CONFIG_XEN_BLKDEV_BACKEND=y
    6.10  CONFIG_XEN_BLKDEV_TAP=y
     7.1 --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig	Tue Aug 08 10:03:30 2006 +0100
     7.2 +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig	Tue Aug 08 10:17:42 2006 +0100
     7.3 @@ -117,7 +117,7 @@ config XEN_PCIDEV_BACKEND_VPCI
     7.4  	  This PCI Backend hides the true PCI topology and makes the frontend
     7.5  	  think there is a single PCI bus with only the exported devices on it.
     7.6  	  For example, a device at 03:05.0 will be re-assigned to 00:00.0. A
     7.7 -	  second device at 02:1a.0 will be re-assigned to 00:01.0.
     7.8 +	  second device at 02:1a.1 will be re-assigned to 00:01.1.
     7.9  
    7.10  config XEN_PCIDEV_BACKEND_PASS
    7.11  	bool "Passthrough"
    7.12 @@ -129,6 +129,15 @@ config XEN_PCIDEV_BACKEND_PASS
    7.13  	  which depend on finding their hardward in certain bus/slot
    7.14  	  locations.
    7.15  
    7.16 +config XEN_PCIDEV_BACKEND_SLOT
    7.17 +	bool "Slot"
    7.18 +	---help---
    7.19 +	  This PCI Backend hides the true PCI topology and makes the frontend
    7.20 +	  think there is a single PCI bus with only the exported devices on it.
    7.21 +	  Contrary to the virtual PCI backend, a function becomes a new slot.
    7.22 +	  For example, a device at 03:05.2 will be re-assigned to 00:00.0. A
    7.23 +	  second device at 02:1a.1 will be re-assigned to 00:01.0.
    7.24 +
    7.25  endchoice
    7.26  
    7.27  config XEN_PCIDEV_BE_DEBUG
     8.1 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile	Tue Aug 08 10:03:30 2006 +0100
     8.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/Makefile	Tue Aug 08 10:17:42 2006 +0100
     8.3 @@ -7,6 +7,7 @@ pciback-y += conf_space.o conf_space_hea
     8.4  	     conf_space_capability_pm.o \
     8.5               conf_space_quirks.o
     8.6  pciback-$(CONFIG_XEN_PCIDEV_BACKEND_VPCI) += vpci.o
     8.7 +pciback-$(CONFIG_XEN_PCIDEV_BACKEND_SLOT) += slot.o
     8.8  pciback-$(CONFIG_XEN_PCIDEV_BACKEND_PASS) += passthrough.o
     8.9  
    8.10  ifeq ($(CONFIG_XEN_PCIDEV_BE_DEBUG),y)
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/slot.c	Tue Aug 08 10:17:42 2006 +0100
     9.3 @@ -0,0 +1,151 @@
     9.4 +/*
     9.5 + * PCI Backend - Provides a Virtual PCI bus (with real devices)
     9.6 + *               to the frontend
     9.7 + *
     9.8 + *   Author: Ryan Wilson <hap9@epoch.ncsc.mil> (vpci.c)
     9.9 + *   Author: Tristan Gingold <tristan.gingold@bull.net>, from vpci.c
    9.10 + */
    9.11 +
    9.12 +#include <linux/list.h>
    9.13 +#include <linux/slab.h>
    9.14 +#include <linux/pci.h>
    9.15 +#include <linux/spinlock.h>
    9.16 +#include "pciback.h"
    9.17 +
    9.18 +/* There are at most 32 slots in a pci bus.  */
    9.19 +#define PCI_SLOT_MAX 32
    9.20 +
    9.21 +#define PCI_BUS_NBR 2
    9.22 +
    9.23 +struct slot_dev_data {
    9.24 +	/* Access to dev_list must be protected by lock */
    9.25 +	struct pci_dev *slots[PCI_BUS_NBR][PCI_SLOT_MAX];
    9.26 +	spinlock_t lock;
    9.27 +};
    9.28 +
    9.29 +struct pci_dev *pciback_get_pci_dev(struct pciback_device *pdev,
    9.30 +				    unsigned int domain, unsigned int bus,
    9.31 +				    unsigned int devfn)
    9.32 +{
    9.33 +	struct pci_dev *dev = NULL;
    9.34 +	struct slot_dev_data *slot_dev = pdev->pci_dev_data;
    9.35 +	unsigned long flags;
    9.36 +
    9.37 +	if (domain != 0 || PCI_FUNC(devfn) != 0)
    9.38 +		return NULL;
    9.39 +
    9.40 +	if (PCI_SLOT(devfn) >= PCI_SLOT_MAX || bus >= PCI_BUS_NBR)
    9.41 +		return NULL;
    9.42 +
    9.43 +	spin_lock_irqsave(&slot_dev->lock, flags);
    9.44 +	dev = slot_dev->slots[bus][PCI_SLOT(devfn)];
    9.45 +	spin_unlock_irqrestore(&slot_dev->lock, flags);
    9.46 +
    9.47 +	return dev;
    9.48 +}
    9.49 +
    9.50 +int pciback_add_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
    9.51 +{
    9.52 +	int err = 0, slot, bus;
    9.53 +	struct slot_dev_data *slot_dev = pdev->pci_dev_data;
    9.54 +	unsigned long flags;
    9.55 +
    9.56 +	if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
    9.57 +		err = -EFAULT;
    9.58 +		xenbus_dev_fatal(pdev->xdev, err,
    9.59 +				 "Can't export bridges on the virtual PCI bus");
    9.60 +		goto out;
    9.61 +	}
    9.62 +
    9.63 +	spin_lock_irqsave(&slot_dev->lock, flags);
    9.64 +
    9.65 +	/* Assign to a new slot on the virtual PCI bus */
    9.66 +	for (bus = 0; bus < PCI_BUS_NBR; bus++)
    9.67 +		for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
    9.68 +			if (slot_dev->slots[bus][slot] == NULL) {
    9.69 +				printk(KERN_INFO
    9.70 +				       "pciback: slot: %s: assign to virtual slot %d, bus %d\n",
    9.71 +				       pci_name(dev), slot, bus);
    9.72 +				slot_dev->slots[bus][slot] = dev;
    9.73 +				goto unlock;
    9.74 +			}
    9.75 +		}
    9.76 +
    9.77 +	err = -ENOMEM;
    9.78 +	xenbus_dev_fatal(pdev->xdev, err,
    9.79 +			 "No more space on root virtual PCI bus");
    9.80 +
    9.81 +      unlock:
    9.82 +	spin_unlock_irqrestore(&slot_dev->lock, flags);
    9.83 +      out:
    9.84 +	return err;
    9.85 +}
    9.86 +
    9.87 +void pciback_release_pci_dev(struct pciback_device *pdev, struct pci_dev *dev)
    9.88 +{
    9.89 +	int slot, bus;
    9.90 +	struct slot_dev_data *slot_dev = pdev->pci_dev_data;
    9.91 +	struct pci_dev *found_dev = NULL;
    9.92 +	unsigned long flags;
    9.93 +
    9.94 +	spin_lock_irqsave(&slot_dev->lock, flags);
    9.95 +
    9.96 +	for (bus = 0; bus < PCI_BUS_NBR; bus++)
    9.97 +		for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
    9.98 +			if (slot_dev->slots[bus][slot] == dev) {
    9.99 +				slot_dev->slots[bus][slot] = NULL;
   9.100 +				found_dev = dev;
   9.101 +				goto out;
   9.102 +			}
   9.103 +		}
   9.104 +
   9.105 +      out:
   9.106 +	spin_unlock_irqrestore(&slot_dev->lock, flags);
   9.107 +
   9.108 +	if (found_dev)
   9.109 +		pcistub_put_pci_dev(found_dev);
   9.110 +}
   9.111 +
   9.112 +int pciback_init_devices(struct pciback_device *pdev)
   9.113 +{
   9.114 +	int slot, bus;
   9.115 +	struct slot_dev_data *slot_dev;
   9.116 +
   9.117 +	slot_dev = kmalloc(sizeof(*slot_dev), GFP_KERNEL);
   9.118 +	if (!slot_dev)
   9.119 +		return -ENOMEM;
   9.120 +
   9.121 +	spin_lock_init(&slot_dev->lock);
   9.122 +
   9.123 +	for (bus = 0; bus < PCI_BUS_NBR; bus++)
   9.124 +		for (slot = 0; slot < PCI_SLOT_MAX; slot++)
   9.125 +			slot_dev->slots[bus][slot] = NULL;
   9.126 +
   9.127 +	pdev->pci_dev_data = slot_dev;
   9.128 +
   9.129 +	return 0;
   9.130 +}
   9.131 +
   9.132 +int pciback_publish_pci_roots(struct pciback_device *pdev,
   9.133 +			      publish_pci_root_cb publish_cb)
   9.134 +{
   9.135 +	/* The Virtual PCI bus has only one root */
   9.136 +	return publish_cb(pdev, 0, 0);
   9.137 +}
   9.138 +
   9.139 +void pciback_release_devices(struct pciback_device *pdev)
   9.140 +{
   9.141 +	int slot, bus;
   9.142 +	struct slot_dev_data *slot_dev = pdev->pci_dev_data;
   9.143 +	struct pci_dev *dev;
   9.144 +
   9.145 +	for (bus = 0; bus < PCI_BUS_NBR; bus++)
   9.146 +		for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
   9.147 +			dev = slot_dev->slots[bus][slot];
   9.148 +			if (dev != NULL)
   9.149 +				pcistub_put_pci_dev(dev);
   9.150 +		}
   9.151 +
   9.152 +	kfree(slot_dev);
   9.153 +	pdev->pci_dev_data = NULL;
   9.154 +}