/*
 * PCI Backend - Provides a Virtual PCI bus (with real devices)
 *               to the frontend
 *
 *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
 */

#include <linux/list.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
#include "pciback.h"

#define PCI_SLOT_MAX 32
#define DRV_NAME	"xen-pciback"

struct vpci_dev_data {
	/* Access to dev_list must be protected by lock */
	struct list_head dev_list[PCI_SLOT_MAX];
	spinlock_t lock;
};

static inline struct list_head *list_first(struct list_head *head)
{
	return head->next;
}

static struct pci_dev *__xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev,
					       unsigned int domain,
					       unsigned int bus,
					       unsigned int devfn)
{
	struct pci_dev_entry *entry;
	struct pci_dev *dev = NULL;
	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
	unsigned long flags;

	if (domain != 0 || bus != 0)
		return NULL;

	if (PCI_SLOT(devfn) < PCI_SLOT_MAX) {
		spin_lock_irqsave(&vpci_dev->lock, flags);

		list_for_each_entry(entry,
				    &vpci_dev->dev_list[PCI_SLOT(devfn)],
				    list) {
			if (PCI_FUNC(entry->dev->devfn) == PCI_FUNC(devfn)) {
				dev = entry->dev;
				break;
			}
		}

		spin_unlock_irqrestore(&vpci_dev->lock, flags);
	}
	return dev;
}

static inline int match_slot(struct pci_dev *l, struct pci_dev *r)
{
	if (pci_domain_nr(l->bus) == pci_domain_nr(r->bus)
	    && l->bus == r->bus && PCI_SLOT(l->devfn) == PCI_SLOT(r->devfn))
		return 1;

	return 0;
}

static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
				   struct pci_dev *dev, int devid,
				   publish_pci_dev_cb publish_cb)
{
	int err = 0, slot, func = -1;
	struct pci_dev_entry *t, *dev_entry;
	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
	unsigned long flags;

	if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
		err = -EFAULT;
		xenbus_dev_fatal(pdev->xdev, err,
				 "Can't export bridges on the virtual PCI bus");
		goto out;
	}

	dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
	if (!dev_entry) {
		err = -ENOMEM;
		xenbus_dev_fatal(pdev->xdev, err,
				 "Error adding entry to virtual PCI bus");
		goto out;
	}

	dev_entry->dev = dev;

	spin_lock_irqsave(&vpci_dev->lock, flags);

	/* Keep multi-function devices together on the virtual PCI bus */
	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
		if (!list_empty(&vpci_dev->dev_list[slot])) {
			t = list_entry(list_first(&vpci_dev->dev_list[slot]),
				       struct pci_dev_entry, list);

			if (match_slot(dev, t->dev)) {
				pr_info(DRV_NAME ": vpci: %s: "
					"assign to virtual slot %d func %d\n",
					pci_name(dev), slot,
					PCI_FUNC(dev->devfn));
				list_add_tail(&dev_entry->list,
					      &vpci_dev->dev_list[slot]);
				func = PCI_FUNC(dev->devfn);
				goto unlock;
			}
		}
	}

	/* Assign to a new slot on the virtual PCI bus */
	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
		if (list_empty(&vpci_dev->dev_list[slot])) {
			printk(KERN_INFO DRV_NAME
			       ": vpci: %s: assign to virtual slot %d\n",
			       pci_name(dev), slot);
			list_add_tail(&dev_entry->list,
				      &vpci_dev->dev_list[slot]);
			func = PCI_FUNC(dev->devfn);
			goto unlock;
		}
	}

	err = -ENOMEM;
	xenbus_dev_fatal(pdev->xdev, err,
			 "No more space on root virtual PCI bus");

unlock:
	spin_unlock_irqrestore(&vpci_dev->lock, flags);

	/* Publish this device. */
	if (!err)
		err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid);

out:
	return err;
}

static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
					struct pci_dev *dev)
{
	int slot;
	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
	struct pci_dev *found_dev = NULL;
	unsigned long flags;

	spin_lock_irqsave(&vpci_dev->lock, flags);

	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
		struct pci_dev_entry *e, *tmp;
		list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
					 list) {
			if (e->dev == dev) {
				list_del(&e->list);
				found_dev = e->dev;
				kfree(e);
				goto out;
			}
		}
	}

out:
	spin_unlock_irqrestore(&vpci_dev->lock, flags);

	if (found_dev)
		pcistub_put_pci_dev(found_dev);
}

static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
{
	int slot;
	struct vpci_dev_data *vpci_dev;

	vpci_dev = kmalloc(sizeof(*vpci_dev), GFP_KERNEL);
	if (!vpci_dev)
		return -ENOMEM;

	spin_lock_init(&vpci_dev->lock);

	for (slot = 0; slot < PCI_SLOT_MAX; slot++)
		INIT_LIST_HEAD(&vpci_dev->dev_list[slot]);

	pdev->pci_dev_data = vpci_dev;

	return 0;
}

static int __xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev,
					 publish_pci_root_cb publish_cb)
{
	/* The Virtual PCI bus has only one root */
	return publish_cb(pdev, 0, 0);
}

static void __xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
{
	int slot;
	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;

	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
		struct pci_dev_entry *e, *tmp;
		list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
					 list) {
			list_del(&e->list);
			pcistub_put_pci_dev(e->dev);
			kfree(e);
		}
	}

	kfree(vpci_dev);
	pdev->pci_dev_data = NULL;
}

static int __xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev,
					struct xen_pcibk_device *pdev,
					unsigned int *domain, unsigned int *bus,
					unsigned int *devfn)
{
	struct pci_dev_entry *entry;
	struct pci_dev *dev = NULL;
	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
	unsigned long flags;
	int found = 0, slot;

	spin_lock_irqsave(&vpci_dev->lock, flags);
	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
		list_for_each_entry(entry,
			    &vpci_dev->dev_list[slot],
			    list) {
			dev = entry->dev;
			if (dev && dev->bus->number == pcidev->bus->number
				&& pci_domain_nr(dev->bus) ==
					pci_domain_nr(pcidev->bus)
				&& dev->devfn == pcidev->devfn) {
				found = 1;
				*domain = 0;
				*bus = 0;
				*devfn = PCI_DEVFN(slot,
					 PCI_FUNC(pcidev->devfn));
			}
		}
	}
	spin_unlock_irqrestore(&vpci_dev->lock, flags);
	return found;
}

struct xen_pcibk_backend xen_pcibk_vpci_backend = {
	.name		= "vpci",
	.init		= __xen_pcibk_init_devices,
	.free		= __xen_pcibk_release_devices,
	.find		= __xen_pcibk_get_pcifront_dev,
	.publish	= __xen_pcibk_publish_pci_roots,
	.release	= __xen_pcibk_release_pci_dev,
	.add		= __xen_pcibk_add_pci_dev,
	.get		= __xen_pcibk_get_pci_dev,
};
