xref: /openbmc/linux/drivers/xen/xen-pciback/vpci.c (revision 171f1bc7)
1 /*
2  * PCI Backend - Provides a Virtual PCI bus (with real devices)
3  *               to the frontend
4  *
5  *   Author: Ryan Wilson <hap9@epoch.ncsc.mil>
6  */
7 
8 #include <linux/list.h>
9 #include <linux/slab.h>
10 #include <linux/pci.h>
11 #include <linux/mutex.h>
12 #include "pciback.h"
13 
14 #define PCI_SLOT_MAX 32
15 
16 struct vpci_dev_data {
17 	/* Access to dev_list must be protected by lock */
18 	struct list_head dev_list[PCI_SLOT_MAX];
19 	struct mutex lock;
20 };
21 
22 static inline struct list_head *list_first(struct list_head *head)
23 {
24 	return head->next;
25 }
26 
27 static struct pci_dev *__xen_pcibk_get_pci_dev(struct xen_pcibk_device *pdev,
28 					       unsigned int domain,
29 					       unsigned int bus,
30 					       unsigned int devfn)
31 {
32 	struct pci_dev_entry *entry;
33 	struct pci_dev *dev = NULL;
34 	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
35 
36 	if (domain != 0 || bus != 0)
37 		return NULL;
38 
39 	if (PCI_SLOT(devfn) < PCI_SLOT_MAX) {
40 		mutex_lock(&vpci_dev->lock);
41 
42 		list_for_each_entry(entry,
43 				    &vpci_dev->dev_list[PCI_SLOT(devfn)],
44 				    list) {
45 			if (PCI_FUNC(entry->dev->devfn) == PCI_FUNC(devfn)) {
46 				dev = entry->dev;
47 				break;
48 			}
49 		}
50 
51 		mutex_unlock(&vpci_dev->lock);
52 	}
53 	return dev;
54 }
55 
56 static inline int match_slot(struct pci_dev *l, struct pci_dev *r)
57 {
58 	if (pci_domain_nr(l->bus) == pci_domain_nr(r->bus)
59 	    && l->bus == r->bus && PCI_SLOT(l->devfn) == PCI_SLOT(r->devfn))
60 		return 1;
61 
62 	return 0;
63 }
64 
65 static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
66 				   struct pci_dev *dev, int devid,
67 				   publish_pci_dev_cb publish_cb)
68 {
69 	int err = 0, slot, func = -1;
70 	struct pci_dev_entry *t, *dev_entry;
71 	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
72 
73 	if ((dev->class >> 24) == PCI_BASE_CLASS_BRIDGE) {
74 		err = -EFAULT;
75 		xenbus_dev_fatal(pdev->xdev, err,
76 				 "Can't export bridges on the virtual PCI bus");
77 		goto out;
78 	}
79 
80 	dev_entry = kmalloc(sizeof(*dev_entry), GFP_KERNEL);
81 	if (!dev_entry) {
82 		err = -ENOMEM;
83 		xenbus_dev_fatal(pdev->xdev, err,
84 				 "Error adding entry to virtual PCI bus");
85 		goto out;
86 	}
87 
88 	dev_entry->dev = dev;
89 
90 	mutex_lock(&vpci_dev->lock);
91 
92 	/* Keep multi-function devices together on the virtual PCI bus */
93 	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
94 		if (!list_empty(&vpci_dev->dev_list[slot])) {
95 			t = list_entry(list_first(&vpci_dev->dev_list[slot]),
96 				       struct pci_dev_entry, list);
97 
98 			if (match_slot(dev, t->dev)) {
99 				pr_info(DRV_NAME ": vpci: %s: "
100 					"assign to virtual slot %d func %d\n",
101 					pci_name(dev), slot,
102 					PCI_FUNC(dev->devfn));
103 				list_add_tail(&dev_entry->list,
104 					      &vpci_dev->dev_list[slot]);
105 				func = PCI_FUNC(dev->devfn);
106 				goto unlock;
107 			}
108 		}
109 	}
110 
111 	/* Assign to a new slot on the virtual PCI bus */
112 	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
113 		if (list_empty(&vpci_dev->dev_list[slot])) {
114 			printk(KERN_INFO DRV_NAME
115 			       ": vpci: %s: assign to virtual slot %d\n",
116 			       pci_name(dev), slot);
117 			list_add_tail(&dev_entry->list,
118 				      &vpci_dev->dev_list[slot]);
119 			func = PCI_FUNC(dev->devfn);
120 			goto unlock;
121 		}
122 	}
123 
124 	err = -ENOMEM;
125 	xenbus_dev_fatal(pdev->xdev, err,
126 			 "No more space on root virtual PCI bus");
127 
128 unlock:
129 	mutex_unlock(&vpci_dev->lock);
130 
131 	/* Publish this device. */
132 	if (!err)
133 		err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid);
134 
135 out:
136 	return err;
137 }
138 
139 static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
140 					struct pci_dev *dev)
141 {
142 	int slot;
143 	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
144 	struct pci_dev *found_dev = NULL;
145 
146 	mutex_lock(&vpci_dev->lock);
147 
148 	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
149 		struct pci_dev_entry *e;
150 
151 		list_for_each_entry(e, &vpci_dev->dev_list[slot], list) {
152 			if (e->dev == dev) {
153 				list_del(&e->list);
154 				found_dev = e->dev;
155 				kfree(e);
156 				goto out;
157 			}
158 		}
159 	}
160 
161 out:
162 	mutex_unlock(&vpci_dev->lock);
163 
164 	if (found_dev)
165 		pcistub_put_pci_dev(found_dev);
166 }
167 
168 static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
169 {
170 	int slot;
171 	struct vpci_dev_data *vpci_dev;
172 
173 	vpci_dev = kmalloc(sizeof(*vpci_dev), GFP_KERNEL);
174 	if (!vpci_dev)
175 		return -ENOMEM;
176 
177 	mutex_init(&vpci_dev->lock);
178 
179 	for (slot = 0; slot < PCI_SLOT_MAX; slot++)
180 		INIT_LIST_HEAD(&vpci_dev->dev_list[slot]);
181 
182 	pdev->pci_dev_data = vpci_dev;
183 
184 	return 0;
185 }
186 
187 static int __xen_pcibk_publish_pci_roots(struct xen_pcibk_device *pdev,
188 					 publish_pci_root_cb publish_cb)
189 {
190 	/* The Virtual PCI bus has only one root */
191 	return publish_cb(pdev, 0, 0);
192 }
193 
194 static void __xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
195 {
196 	int slot;
197 	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
198 
199 	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
200 		struct pci_dev_entry *e, *tmp;
201 		list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
202 					 list) {
203 			list_del(&e->list);
204 			pcistub_put_pci_dev(e->dev);
205 			kfree(e);
206 		}
207 	}
208 
209 	kfree(vpci_dev);
210 	pdev->pci_dev_data = NULL;
211 }
212 
213 static int __xen_pcibk_get_pcifront_dev(struct pci_dev *pcidev,
214 					struct xen_pcibk_device *pdev,
215 					unsigned int *domain, unsigned int *bus,
216 					unsigned int *devfn)
217 {
218 	struct pci_dev_entry *entry;
219 	struct pci_dev *dev = NULL;
220 	struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
221 	int found = 0, slot;
222 
223 	mutex_lock(&vpci_dev->lock);
224 	for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
225 		list_for_each_entry(entry,
226 			    &vpci_dev->dev_list[slot],
227 			    list) {
228 			dev = entry->dev;
229 			if (dev && dev->bus->number == pcidev->bus->number
230 				&& pci_domain_nr(dev->bus) ==
231 					pci_domain_nr(pcidev->bus)
232 				&& dev->devfn == pcidev->devfn) {
233 				found = 1;
234 				*domain = 0;
235 				*bus = 0;
236 				*devfn = PCI_DEVFN(slot,
237 					 PCI_FUNC(pcidev->devfn));
238 			}
239 		}
240 	}
241 	mutex_unlock(&vpci_dev->lock);
242 	return found;
243 }
244 
245 const struct xen_pcibk_backend xen_pcibk_vpci_backend = {
246 	.name		= "vpci",
247 	.init		= __xen_pcibk_init_devices,
248 	.free		= __xen_pcibk_release_devices,
249 	.find		= __xen_pcibk_get_pcifront_dev,
250 	.publish	= __xen_pcibk_publish_pci_roots,
251 	.release	= __xen_pcibk_release_pci_dev,
252 	.add		= __xen_pcibk_add_pci_dev,
253 	.get		= __xen_pcibk_get_pci_dev,
254 };
255