xref: /openbmc/linux/drivers/xen/xen-pciback/vpci.c (revision 4ba50e7c)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
230edc14bSKonrad Rzeszutek Wilk /*
330edc14bSKonrad Rzeszutek Wilk  * PCI Backend - Provides a Virtual PCI bus (with real devices)
430edc14bSKonrad Rzeszutek Wilk  *               to the frontend
530edc14bSKonrad Rzeszutek Wilk  *
630edc14bSKonrad Rzeszutek Wilk  *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
730edc14bSKonrad Rzeszutek Wilk  */
830edc14bSKonrad Rzeszutek Wilk 
9283c0972SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1069049454SBjorn Helgaas #define dev_fmt pr_fmt
11283c0972SJoe Perches 
1230edc14bSKonrad Rzeszutek Wilk #include <linux/list.h>
1330edc14bSKonrad Rzeszutek Wilk #include <linux/slab.h>
1430edc14bSKonrad Rzeszutek Wilk #include <linux/pci.h>
1574d33dedSKonrad Rzeszutek Wilk #include <linux/mutex.h>
1630edc14bSKonrad Rzeszutek Wilk #include "pciback.h"
1730edc14bSKonrad Rzeszutek Wilk 
1830edc14bSKonrad Rzeszutek Wilk #define PCI_SLOT_MAX 32
1930edc14bSKonrad Rzeszutek Wilk 
2030edc14bSKonrad Rzeszutek Wilk struct vpci_dev_data {
2130edc14bSKonrad Rzeszutek Wilk 	/* Access to dev_list must be protected by lock */
2230edc14bSKonrad Rzeszutek Wilk 	struct list_head dev_list[PCI_SLOT_MAX];
2374d33dedSKonrad Rzeszutek Wilk 	struct mutex lock;
2430edc14bSKonrad Rzeszutek Wilk };
2530edc14bSKonrad Rzeszutek Wilk 
list_first(struct list_head * head)2630edc14bSKonrad Rzeszutek Wilk static inline struct list_head *list_first(struct list_head *head)
2730edc14bSKonrad Rzeszutek Wilk {
2830edc14bSKonrad Rzeszutek Wilk 	return head->next;
2930edc14bSKonrad Rzeszutek Wilk }
3030edc14bSKonrad Rzeszutek Wilk 
__xen_pcibk_get_pci_dev(struct xen_pcibk_device * pdev,unsigned int domain,unsigned int bus,unsigned int devfn)312ebdc426SKonrad Rzeszutek Wilk static struct pci_dev *__xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev,
322ebdc426SKonrad Rzeszutek Wilk 					       unsigned int domain,
332ebdc426SKonrad Rzeszutek Wilk 					       unsigned int bus,
3430edc14bSKonrad Rzeszutek Wilk 					       unsigned int devfn)
3530edc14bSKonrad Rzeszutek Wilk {
3630edc14bSKonrad Rzeszutek Wilk 	struct pci_dev_entry *entry;
3730edc14bSKonrad Rzeszutek Wilk 	struct pci_dev *dev = NULL;
3830edc14bSKonrad Rzeszutek Wilk 	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
3930edc14bSKonrad Rzeszutek Wilk 
4030edc14bSKonrad Rzeszutek Wilk 	if (domain != 0 || bus != 0)
4130edc14bSKonrad Rzeszutek Wilk 		return NULL;
4230edc14bSKonrad Rzeszutek Wilk 
4330edc14bSKonrad Rzeszutek Wilk 	if (PCI_SLOT(devfn) < PCI_SLOT_MAX) {
4474d33dedSKonrad Rzeszutek Wilk 		mutex_lock(&vpci_dev->lock);
4530edc14bSKonrad Rzeszutek Wilk 
4630edc14bSKonrad Rzeszutek Wilk 		list_for_each_entry(entry,
4730edc14bSKonrad Rzeszutek Wilk 				    &vpci_dev->dev_list[PCI_SLOT(devfn)],
4830edc14bSKonrad Rzeszutek Wilk 				    list) {
4930edc14bSKonrad Rzeszutek Wilk 			if (PCI_FUNC(entry->dev->devfn) == PCI_FUNC(devfn)) {
5030edc14bSKonrad Rzeszutek Wilk 				dev = entry->dev;
5130edc14bSKonrad Rzeszutek Wilk 				break;
5230edc14bSKonrad Rzeszutek Wilk 			}
5330edc14bSKonrad Rzeszutek Wilk 		}
5430edc14bSKonrad Rzeszutek Wilk 
5574d33dedSKonrad Rzeszutek Wilk 		mutex_unlock(&vpci_dev->lock);
5630edc14bSKonrad Rzeszutek Wilk 	}
5730edc14bSKonrad Rzeszutek Wilk 	return dev;
5830edc14bSKonrad Rzeszutek Wilk }
5930edc14bSKonrad Rzeszutek Wilk 
match_slot(struct pci_dev * l,struct pci_dev * r)6030edc14bSKonrad Rzeszutek Wilk static inline int match_slot(struct pci_dev *l, struct pci_dev *r)
6130edc14bSKonrad Rzeszutek Wilk {
6230edc14bSKonrad Rzeszutek Wilk 	if (pci_domain_nr(l->bus) == pci_domain_nr(r->bus)
6330edc14bSKonrad Rzeszutek Wilk 	    && l->bus == r->bus && PCI_SLOT(l->devfn) == PCI_SLOT(r->devfn))
6430edc14bSKonrad Rzeszutek Wilk 		return 1;
6530edc14bSKonrad Rzeszutek Wilk 
6630edc14bSKonrad Rzeszutek Wilk 	return 0;
6730edc14bSKonrad Rzeszutek Wilk }
6830edc14bSKonrad Rzeszutek Wilk 
__xen_pcibk_add_pci_dev(struct xen_pcibk_device * pdev,struct pci_dev * dev,int devid,publish_pci_dev_cb publish_cb)692ebdc426SKonrad Rzeszutek Wilk static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
702ebdc426SKonrad Rzeszutek Wilk 				   struct pci_dev *dev, int devid,
712ebdc426SKonrad Rzeszutek Wilk 				   publish_pci_dev_cb publish_cb)
7230edc14bSKonrad Rzeszutek Wilk {
73*4ba50e7cSJan Beulich 	int err = 0, slot, func = PCI_FUNC(dev->devfn);
7430edc14bSKonrad Rzeszutek Wilk 	struct pci_dev_entry *t, *dev_entry;
7530edc14bSKonrad Rzeszutek Wilk 	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
7630edc14bSKonrad Rzeszutek Wilk 
7730edc14bSKonrad Rzeszutek Wilk 	if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
7830edc14bSKonrad Rzeszutek Wilk 		err = -EFAULT;
7930edc14bSKonrad Rzeszutek Wilk 		xenbus_dev_fatal(pdev->xdev, err,
8030edc14bSKonrad Rzeszutek Wilk 				 "Can't export bridges on the virtual PCI bus");
8130edc14bSKonrad Rzeszutek Wilk 		goto out;
8230edc14bSKonrad Rzeszutek Wilk 	}
8330edc14bSKonrad Rzeszutek Wilk 
8430edc14bSKonrad Rzeszutek Wilk 	dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
8530edc14bSKonrad Rzeszutek Wilk 	if (!dev_entry) {
8630edc14bSKonrad Rzeszutek Wilk 		err = -ENOMEM;
8730edc14bSKonrad Rzeszutek Wilk 		xenbus_dev_fatal(pdev->xdev, err,
8830edc14bSKonrad Rzeszutek Wilk 				 "Error adding entry to virtual PCI bus");
8930edc14bSKonrad Rzeszutek Wilk 		goto out;
9030edc14bSKonrad Rzeszutek Wilk 	}
9130edc14bSKonrad Rzeszutek Wilk 
9230edc14bSKonrad Rzeszutek Wilk 	dev_entry->dev = dev;
9330edc14bSKonrad Rzeszutek Wilk 
9474d33dedSKonrad Rzeszutek Wilk 	mutex_lock(&vpci_dev->lock);
9530edc14bSKonrad Rzeszutek Wilk 
968a5248feSLaszlo Ersek 	/*
978a5248feSLaszlo Ersek 	 * Keep multi-function devices together on the virtual PCI bus, except
98*4ba50e7cSJan Beulich 	 * that we want to keep virtual functions at func 0 on their own. They
99*4ba50e7cSJan Beulich 	 * aren't multi-function devices and hence their presence at func 0
100*4ba50e7cSJan Beulich 	 * may cause guests to not scan the other functions.
1018a5248feSLaszlo Ersek 	 */
102*4ba50e7cSJan Beulich 	if (!dev->is_virtfn || func) {
10330edc14bSKonrad Rzeszutek Wilk 		for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
1048a5248feSLaszlo Ersek 			if (list_empty(&vpci_dev->dev_list[slot]))
1058a5248feSLaszlo Ersek 				continue;
1068a5248feSLaszlo Ersek 
10730edc14bSKonrad Rzeszutek Wilk 			t = list_entry(list_first(&vpci_dev->dev_list[slot]),
10830edc14bSKonrad Rzeszutek Wilk 				       struct pci_dev_entry, list);
109*4ba50e7cSJan Beulich 			if (t->dev->is_virtfn && !PCI_FUNC(t->dev->devfn))
110*4ba50e7cSJan Beulich 				continue;
11130edc14bSKonrad Rzeszutek Wilk 
11230edc14bSKonrad Rzeszutek Wilk 			if (match_slot(dev, t->dev)) {
11369049454SBjorn Helgaas 				dev_info(&dev->dev, "vpci: assign to virtual slot %d func %d\n",
114*4ba50e7cSJan Beulich 					 slot, func);
11530edc14bSKonrad Rzeszutek Wilk 				list_add_tail(&dev_entry->list,
11630edc14bSKonrad Rzeszutek Wilk 					      &vpci_dev->dev_list[slot]);
11730edc14bSKonrad Rzeszutek Wilk 				goto unlock;
11830edc14bSKonrad Rzeszutek Wilk 			}
11930edc14bSKonrad Rzeszutek Wilk 		}
12030edc14bSKonrad Rzeszutek Wilk 	}
12130edc14bSKonrad Rzeszutek Wilk 
12230edc14bSKonrad Rzeszutek Wilk 	/* Assign to a new slot on the virtual PCI bus */
12330edc14bSKonrad Rzeszutek Wilk 	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
12430edc14bSKonrad Rzeszutek Wilk 		if (list_empty(&vpci_dev->dev_list[slot])) {
12569049454SBjorn Helgaas 			dev_info(&dev->dev, "vpci: assign to virtual slot %d\n",
12669049454SBjorn Helgaas 				 slot);
12730edc14bSKonrad Rzeszutek Wilk 			list_add_tail(&dev_entry->list,
12830edc14bSKonrad Rzeszutek Wilk 				      &vpci_dev->dev_list[slot]);
12930edc14bSKonrad Rzeszutek Wilk 			goto unlock;
13030edc14bSKonrad Rzeszutek Wilk 		}
13130edc14bSKonrad Rzeszutek Wilk 	}
13230edc14bSKonrad Rzeszutek Wilk 
13330edc14bSKonrad Rzeszutek Wilk 	err = -ENOMEM;
13430edc14bSKonrad Rzeszutek Wilk 	xenbus_dev_fatal(pdev->xdev, err,
13530edc14bSKonrad Rzeszutek Wilk 			 "No more space on root virtual PCI bus");
13630edc14bSKonrad Rzeszutek Wilk 
13730edc14bSKonrad Rzeszutek Wilk unlock:
13874d33dedSKonrad Rzeszutek Wilk 	mutex_unlock(&vpci_dev->lock);
13930edc14bSKonrad Rzeszutek Wilk 
14030edc14bSKonrad Rzeszutek Wilk 	/* Publish this device. */
14130edc14bSKonrad Rzeszutek Wilk 	if (!err)
14230edc14bSKonrad Rzeszutek Wilk 		err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid);
143cea37f87SDaeseok Youn 	else
144cea37f87SDaeseok Youn 		kfree(dev_entry);
14530edc14bSKonrad Rzeszutek Wilk 
14630edc14bSKonrad Rzeszutek Wilk out:
14730edc14bSKonrad Rzeszutek Wilk 	return err;
14830edc14bSKonrad Rzeszutek Wilk }
14930edc14bSKonrad Rzeszutek Wilk 
__xen_pcibk_release_pci_dev(struct xen_pcibk_device * pdev,struct pci_dev * dev,bool lock)1502ebdc426SKonrad Rzeszutek Wilk static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
151e8801a74SKonrad Rzeszutek Wilk 					struct pci_dev *dev, bool lock)
15230edc14bSKonrad Rzeszutek Wilk {
15330edc14bSKonrad Rzeszutek Wilk 	int slot;
15430edc14bSKonrad Rzeszutek Wilk 	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
15530edc14bSKonrad Rzeszutek Wilk 	struct pci_dev *found_dev = NULL;
15630edc14bSKonrad Rzeszutek Wilk 
15774d33dedSKonrad Rzeszutek Wilk 	mutex_lock(&vpci_dev->lock);
15830edc14bSKonrad Rzeszutek Wilk 
15930edc14bSKonrad Rzeszutek Wilk 	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
160402c5e15SJan Beulich 		struct pci_dev_entry *e;
161402c5e15SJan Beulich 
162402c5e15SJan Beulich 		list_for_each_entry(e, &vpci_dev->dev_list[slot], list) {
16330edc14bSKonrad Rzeszutek Wilk 			if (e->dev == dev) {
16430edc14bSKonrad Rzeszutek Wilk 				list_del(&e->list);
16530edc14bSKonrad Rzeszutek Wilk 				found_dev = e->dev;
16630edc14bSKonrad Rzeszutek Wilk 				kfree(e);
16730edc14bSKonrad Rzeszutek Wilk 				goto out;
16830edc14bSKonrad Rzeszutek Wilk 			}
16930edc14bSKonrad Rzeszutek Wilk 		}
17030edc14bSKonrad Rzeszutek Wilk 	}
17130edc14bSKonrad Rzeszutek Wilk 
17230edc14bSKonrad Rzeszutek Wilk out:
17374d33dedSKonrad Rzeszutek Wilk 	mutex_unlock(&vpci_dev->lock);
17430edc14bSKonrad Rzeszutek Wilk 
175e8801a74SKonrad Rzeszutek Wilk 	if (found_dev) {
176e8801a74SKonrad Rzeszutek Wilk 		if (lock)
177e8801a74SKonrad Rzeszutek Wilk 			device_lock(&found_dev->dev);
17830edc14bSKonrad Rzeszutek Wilk 		pcistub_put_pci_dev(found_dev);
179e8801a74SKonrad Rzeszutek Wilk 		if (lock)
180e8801a74SKonrad Rzeszutek Wilk 			device_unlock(&found_dev->dev);
181e8801a74SKonrad Rzeszutek Wilk 	}
18230edc14bSKonrad Rzeszutek Wilk }
18330edc14bSKonrad Rzeszutek Wilk 
__xen_pcibk_init_devices(struct xen_pcibk_device * pdev)1842ebdc426SKonrad Rzeszutek Wilk static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
18530edc14bSKonrad Rzeszutek Wilk {
18630edc14bSKonrad Rzeszutek Wilk 	int slot;
18730edc14bSKonrad Rzeszutek Wilk 	struct vpci_dev_data *vpci_dev;
18830edc14bSKonrad Rzeszutek Wilk 
18930edc14bSKonrad Rzeszutek Wilk 	vpci_dev = kmalloc(sizeof(*vpci_dev), GFP_KERNEL);
19030edc14bSKonrad Rzeszutek Wilk 	if (!vpci_dev)
19130edc14bSKonrad Rzeszutek Wilk 		return -ENOMEM;
19230edc14bSKonrad Rzeszutek Wilk 
19374d33dedSKonrad Rzeszutek Wilk 	mutex_init(&vpci_dev->lock);
19430edc14bSKonrad Rzeszutek Wilk 
19530edc14bSKonrad Rzeszutek Wilk 	for (slot = 0; slot < PCI_SLOT_MAX; slot++)
19630edc14bSKonrad Rzeszutek Wilk 		INIT_LIST_HEAD(&vpci_dev->dev_list[slot]);
19730edc14bSKonrad Rzeszutek Wilk 
19830edc14bSKonrad Rzeszutek Wilk 	pdev->pci_dev_data = vpci_dev;
19930edc14bSKonrad Rzeszutek Wilk 
20030edc14bSKonrad Rzeszutek Wilk 	return 0;
20130edc14bSKonrad Rzeszutek Wilk }
20230edc14bSKonrad Rzeszutek Wilk 
__xen_pcibk_publish_pci_roots(struct xen_pcibk_device * pdev,publish_pci_root_cb publish_cb)2032ebdc426SKonrad Rzeszutek Wilk static int __xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev,
20430edc14bSKonrad Rzeszutek Wilk 					 publish_pci_root_cb publish_cb)
20530edc14bSKonrad Rzeszutek Wilk {
20630edc14bSKonrad Rzeszutek Wilk 	/* The Virtual PCI bus has only one root */
20730edc14bSKonrad Rzeszutek Wilk 	return publish_cb(pdev, 0, 0);
20830edc14bSKonrad Rzeszutek Wilk }
20930edc14bSKonrad Rzeszutek Wilk 
__xen_pcibk_release_devices(struct xen_pcibk_device * pdev)2102ebdc426SKonrad Rzeszutek Wilk static void __xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
21130edc14bSKonrad Rzeszutek Wilk {
21230edc14bSKonrad Rzeszutek Wilk 	int slot;
21330edc14bSKonrad Rzeszutek Wilk 	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
21430edc14bSKonrad Rzeszutek Wilk 
21530edc14bSKonrad Rzeszutek Wilk 	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
21630edc14bSKonrad Rzeszutek Wilk 		struct pci_dev_entry *e, *tmp;
21730edc14bSKonrad Rzeszutek Wilk 		list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
21830edc14bSKonrad Rzeszutek Wilk 					 list) {
219e8801a74SKonrad Rzeszutek Wilk 			struct pci_dev *dev = e->dev;
22030edc14bSKonrad Rzeszutek Wilk 			list_del(&e->list);
221e8801a74SKonrad Rzeszutek Wilk 			device_lock(&dev->dev);
222e8801a74SKonrad Rzeszutek Wilk 			pcistub_put_pci_dev(dev);
223e8801a74SKonrad Rzeszutek Wilk 			device_unlock(&dev->dev);
22430edc14bSKonrad Rzeszutek Wilk 			kfree(e);
22530edc14bSKonrad Rzeszutek Wilk 		}
22630edc14bSKonrad Rzeszutek Wilk 	}
22730edc14bSKonrad Rzeszutek Wilk 
22830edc14bSKonrad Rzeszutek Wilk 	kfree(vpci_dev);
22930edc14bSKonrad Rzeszutek Wilk 	pdev->pci_dev_data = NULL;
23030edc14bSKonrad Rzeszutek Wilk }
23130edc14bSKonrad Rzeszutek Wilk 
__xen_pcibk_get_pcifront_dev(struct pci_dev * pcidev,struct xen_pcibk_device * pdev,unsigned int * domain,unsigned int * bus,unsigned int * devfn)2322ebdc426SKonrad Rzeszutek Wilk static int __xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev,
233a92336a1SKonrad Rzeszutek Wilk 					struct xen_pcibk_device *pdev,
23430edc14bSKonrad Rzeszutek Wilk 					unsigned int *domain, unsigned int *bus,
23530edc14bSKonrad Rzeszutek Wilk 					unsigned int *devfn)
23630edc14bSKonrad Rzeszutek Wilk {
23730edc14bSKonrad Rzeszutek Wilk 	struct pci_dev_entry *entry;
23830edc14bSKonrad Rzeszutek Wilk 	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
23930edc14bSKonrad Rzeszutek Wilk 	int found = 0, slot;
24030edc14bSKonrad Rzeszutek Wilk 
24174d33dedSKonrad Rzeszutek Wilk 	mutex_lock(&vpci_dev->lock);
24230edc14bSKonrad Rzeszutek Wilk 	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
24330edc14bSKonrad Rzeszutek Wilk 		list_for_each_entry(entry,
24430edc14bSKonrad Rzeszutek Wilk 			    &vpci_dev->dev_list[slot],
24530edc14bSKonrad Rzeszutek Wilk 			    list) {
246a929e124SJan Beulich 			if (entry->dev == pcidev) {
24730edc14bSKonrad Rzeszutek Wilk 				found = 1;
24830edc14bSKonrad Rzeszutek Wilk 				*domain = 0;
24930edc14bSKonrad Rzeszutek Wilk 				*bus = 0;
25030edc14bSKonrad Rzeszutek Wilk 				*devfn = PCI_DEVFN(slot,
25130edc14bSKonrad Rzeszutek Wilk 					 PCI_FUNC(pcidev->devfn));
25230edc14bSKonrad Rzeszutek Wilk 			}
25330edc14bSKonrad Rzeszutek Wilk 		}
25430edc14bSKonrad Rzeszutek Wilk 	}
255e1db4cefSDan Carpenter 	mutex_unlock(&vpci_dev->lock);
25630edc14bSKonrad Rzeszutek Wilk 	return found;
25730edc14bSKonrad Rzeszutek Wilk }
2582ebdc426SKonrad Rzeszutek Wilk 
259402c5e15SJan Beulich const struct xen_pcibk_backend xen_pcibk_vpci_backend = {
2602ebdc426SKonrad Rzeszutek Wilk 	.name		= "vpci",
2612ebdc426SKonrad Rzeszutek Wilk 	.init		= __xen_pcibk_init_devices,
2622ebdc426SKonrad Rzeszutek Wilk 	.free		= __xen_pcibk_release_devices,
2632ebdc426SKonrad Rzeszutek Wilk 	.find		= __xen_pcibk_get_pcifront_dev,
2642ebdc426SKonrad Rzeszutek Wilk 	.publish	= __xen_pcibk_publish_pci_roots,
2652ebdc426SKonrad Rzeszutek Wilk 	.release	= __xen_pcibk_release_pci_dev,
2662ebdc426SKonrad Rzeszutek Wilk 	.add		= __xen_pcibk_add_pci_dev,
2672ebdc426SKonrad Rzeszutek Wilk 	.get		= __xen_pcibk_get_pci_dev,
2682ebdc426SKonrad Rzeszutek Wilk };
269