Lines Matching +full:0 +full:- +full:dev

6  * Copyright (c) 2015-2017 Knut Omang <knut.omang@oracle.com>
9 * See the COPYING file in the top-level directory.
17 #include "hw/qdev-properties.h"
24 static void unparent_vfs(PCIDevice *dev, uint16_t total_vfs) in unparent_vfs() argument
26 for (uint16_t i = 0; i < total_vfs; i++) { in unparent_vfs()
27 PCIDevice *vf = dev->exp.sriov_pf.vf[i]; in unparent_vfs()
31 g_free(dev->exp.sriov_pf.vf); in unparent_vfs()
32 dev->exp.sriov_pf.vf = NULL; in unparent_vfs()
35 static void register_vfs(PCIDevice *dev) in register_vfs() argument
39 uint16_t sriov_cap = dev->exp.sriov_cap; in register_vfs()
41 assert(sriov_cap > 0); in register_vfs()
42 num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF); in register_vfs()
44 trace_sriov_register_vfs(dev->name, PCI_SLOT(dev->devfn), in register_vfs()
45 PCI_FUNC(dev->devfn), num_vfs); in register_vfs()
46 for (i = 0; i < num_vfs; i++) { in register_vfs()
47 pci_set_enabled(dev->exp.sriov_pf.vf[i], true); in register_vfs()
50 pci_set_word(dev->wmask + sriov_cap + PCI_SRIOV_NUM_VF, 0); in register_vfs()
53 static void unregister_vfs(PCIDevice *dev) in unregister_vfs() argument
55 uint8_t *cfg = dev->config + dev->exp.sriov_cap; in unregister_vfs()
58 trace_sriov_unregister_vfs(dev->name, PCI_SLOT(dev->devfn), in unregister_vfs()
59 PCI_FUNC(dev->devfn)); in unregister_vfs()
60 for (i = 0; i < pci_get_word(cfg + PCI_SRIOV_TOTAL_VF); i++) { in unregister_vfs()
61 pci_set_enabled(dev->exp.sriov_pf.vf[i], false); in unregister_vfs()
64 pci_set_word(dev->wmask + dev->exp.sriov_cap + PCI_SRIOV_NUM_VF, 0xffff); in unregister_vfs()
67 static bool pcie_sriov_pf_init_common(PCIDevice *dev, uint16_t offset, in pcie_sriov_pf_init_common() argument
72 int32_t devfn = dev->devfn + vf_offset; in pcie_sriov_pf_init_common()
73 uint8_t *cfg = dev->config + offset; in pcie_sriov_pf_init_common()
76 if (!pci_is_express(dev)) { in pcie_sriov_pf_init_common()
77 error_setg(errp, "PCI Express is required for SR-IOV PF"); in pcie_sriov_pf_init_common()
81 if (pci_is_vf(dev)) { in pcie_sriov_pf_init_common()
82 error_setg(errp, "a device cannot be a SR-IOV PF and a VF at the same time"); in pcie_sriov_pf_init_common()
87 (uint32_t)devfn + (uint32_t)(total_vfs - 1) * vf_stride >= PCI_DEVFN_MAX) { in pcie_sriov_pf_init_common()
92 pcie_add_capability(dev, PCI_EXT_CAP_ID_SRIOV, 1, in pcie_sriov_pf_init_common()
94 dev->exp.sriov_cap = offset; in pcie_sriov_pf_init_common()
95 dev->exp.sriov_pf.vf = NULL; in pcie_sriov_pf_init_common()
111 pci_set_word(cfg + PCI_SRIOV_SYS_PGSIZE, 0x1); in pcie_sriov_pf_init_common()
117 pci_set_word(cfg + PCI_SRIOV_NUM_VF, 0); in pcie_sriov_pf_init_common()
120 wmask = dev->wmask + offset; in pcie_sriov_pf_init_common()
123 pci_set_word(wmask + PCI_SRIOV_NUM_VF, 0xffff); in pcie_sriov_pf_init_common()
124 pci_set_word(wmask + PCI_SRIOV_SYS_PGSIZE, 0x553); in pcie_sriov_pf_init_common()
126 qdev_prop_set_bit(&dev->qdev, "multifunction", true); in pcie_sriov_pf_init_common()
131 bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset, in pcie_sriov_pf_init() argument
137 BusState *bus = qdev_get_parent_bus(&dev->qdev); in pcie_sriov_pf_init()
138 int32_t devfn = dev->devfn + vf_offset; in pcie_sriov_pf_init()
140 if (pfs && g_hash_table_contains(pfs, dev->qdev.id)) { in pcie_sriov_pf_init()
141 error_setg(errp, "attaching user-created SR-IOV VF unsupported"); in pcie_sriov_pf_init()
145 if (!pcie_sriov_pf_init_common(dev, offset, vf_dev_id, init_vfs, in pcie_sriov_pf_init()
150 dev->exp.sriov_pf.vf = g_new(PCIDevice *, total_vfs); in pcie_sriov_pf_init()
152 for (uint16_t i = 0; i < total_vfs; i++) { in pcie_sriov_pf_init()
154 vf->exp.sriov_vf.pf = dev; in pcie_sriov_pf_init()
155 vf->exp.sriov_vf.vf_number = i; in pcie_sriov_pf_init()
157 if (!qdev_realize(&vf->qdev, bus, errp)) { in pcie_sriov_pf_init()
160 unparent_vfs(dev, i); in pcie_sriov_pf_init()
164 /* set vid/did according to sr/iov spec - they are not used */ in pcie_sriov_pf_init()
165 pci_config_set_vendor_id(vf->config, 0xffff); in pcie_sriov_pf_init()
166 pci_config_set_device_id(vf->config, 0xffff); in pcie_sriov_pf_init()
168 dev->exp.sriov_pf.vf[i] = vf; in pcie_sriov_pf_init()
175 void pcie_sriov_pf_exit(PCIDevice *dev) in pcie_sriov_pf_exit() argument
177 uint8_t *cfg = dev->config + dev->exp.sriov_cap; in pcie_sriov_pf_exit()
179 if (dev->exp.sriov_pf.vf_user_created) { in pcie_sriov_pf_exit()
180 uint16_t ven_id = pci_get_word(dev->config + PCI_VENDOR_ID); in pcie_sriov_pf_exit()
181 uint16_t total_vfs = pci_get_word(dev->config + PCI_SRIOV_TOTAL_VF); in pcie_sriov_pf_exit()
182 uint16_t vf_dev_id = pci_get_word(dev->config + PCI_SRIOV_VF_DID); in pcie_sriov_pf_exit()
184 unregister_vfs(dev); in pcie_sriov_pf_exit()
186 for (uint16_t i = 0; i < total_vfs; i++) { in pcie_sriov_pf_exit()
187 dev->exp.sriov_pf.vf[i]->exp.sriov_vf.pf = NULL; in pcie_sriov_pf_exit()
189 pci_config_set_vendor_id(dev->exp.sriov_pf.vf[i]->config, ven_id); in pcie_sriov_pf_exit()
190 pci_config_set_device_id(dev->exp.sriov_pf.vf[i]->config, vf_dev_id); in pcie_sriov_pf_exit()
193 unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF)); in pcie_sriov_pf_exit()
197 void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int region_num, in pcie_sriov_pf_init_vf_bar() argument
202 uint16_t sriov_cap = dev->exp.sriov_cap; in pcie_sriov_pf_init_vf_bar()
204 assert(sriov_cap > 0); in pcie_sriov_pf_init_vf_bar()
205 assert(region_num >= 0); in pcie_sriov_pf_init_vf_bar()
209 wmask = ~(size - 1); in pcie_sriov_pf_init_vf_bar()
212 pci_set_long(dev->config + addr, type); in pcie_sriov_pf_init_vf_bar()
215 pci_set_quad(dev->wmask + addr, wmask); in pcie_sriov_pf_init_vf_bar()
216 pci_set_quad(dev->cmask + addr, ~0ULL); in pcie_sriov_pf_init_vf_bar()
218 pci_set_long(dev->wmask + addr, wmask & 0xffffffff); in pcie_sriov_pf_init_vf_bar()
219 pci_set_long(dev->cmask + addr, 0xffffffff); in pcie_sriov_pf_init_vf_bar()
221 dev->exp.sriov_pf.vf_bar_type[region_num] = type; in pcie_sriov_pf_init_vf_bar()
224 void pcie_sriov_vf_register_bar(PCIDevice *dev, int region_num, in pcie_sriov_vf_register_bar() argument
229 assert(dev->exp.sriov_vf.pf); in pcie_sriov_vf_register_bar()
230 type = dev->exp.sriov_vf.pf->exp.sriov_pf.vf_bar_type[region_num]; in pcie_sriov_vf_register_bar()
232 return pci_register_bar(dev, region_num, type, memory); in pcie_sriov_vf_register_bar()
237 return (*(PCIDevice **)a)->devfn - (*(PCIDevice **)b)->devfn; in compare_vf_devfns()
240 int16_t pcie_sriov_pf_init_from_user_created_vfs(PCIDevice *dev, in pcie_sriov_pf_init_from_user_created_vfs() argument
246 BusState *bus = qdev_get_parent_bus(DEVICE(dev)); in pcie_sriov_pf_init_from_user_created_vfs()
247 uint16_t ven_id = pci_get_word(dev->config + PCI_VENDOR_ID); in pcie_sriov_pf_init_from_user_created_vfs()
254 if (!pfs || !dev->qdev.id) { in pcie_sriov_pf_init_from_user_created_vfs()
255 return 0; in pcie_sriov_pf_init_from_user_created_vfs()
258 pf = g_hash_table_lookup(pfs, dev->qdev.id); in pcie_sriov_pf_init_from_user_created_vfs()
260 return 0; in pcie_sriov_pf_init_from_user_created_vfs()
263 if (pf->len > UINT16_MAX) { in pcie_sriov_pf_init_from_user_created_vfs()
265 return -1; in pcie_sriov_pf_init_from_user_created_vfs()
269 vfs = (void *)pf->pdata; in pcie_sriov_pf_init_from_user_created_vfs()
271 if (vfs[0]->devfn <= dev->devfn) { in pcie_sriov_pf_init_from_user_created_vfs()
273 return -1; in pcie_sriov_pf_init_from_user_created_vfs()
276 vf_dev_id = pci_get_word(vfs[0]->config + PCI_DEVICE_ID); in pcie_sriov_pf_init_from_user_created_vfs()
277 vf_offset = vfs[0]->devfn - dev->devfn; in pcie_sriov_pf_init_from_user_created_vfs()
278 vf_stride = pf->len < 2 ? 0 : vfs[1]->devfn - vfs[0]->devfn; in pcie_sriov_pf_init_from_user_created_vfs()
280 for (i = 0; i < pf->len; i++) { in pcie_sriov_pf_init_from_user_created_vfs()
281 if (bus != qdev_get_parent_bus(&vfs[i]->qdev)) { in pcie_sriov_pf_init_from_user_created_vfs()
282 error_setg(errp, "SR-IOV VF parent bus mismatches with PF"); in pcie_sriov_pf_init_from_user_created_vfs()
283 return -1; in pcie_sriov_pf_init_from_user_created_vfs()
286 if (ven_id != pci_get_word(vfs[i]->config + PCI_VENDOR_ID)) { in pcie_sriov_pf_init_from_user_created_vfs()
287 error_setg(errp, "SR-IOV VF vendor ID mismatches with PF"); in pcie_sriov_pf_init_from_user_created_vfs()
288 return -1; in pcie_sriov_pf_init_from_user_created_vfs()
291 if (vf_dev_id != pci_get_word(vfs[i]->config + PCI_DEVICE_ID)) { in pcie_sriov_pf_init_from_user_created_vfs()
292 error_setg(errp, "inconsistent SR-IOV VF device IDs"); in pcie_sriov_pf_init_from_user_created_vfs()
293 return -1; in pcie_sriov_pf_init_from_user_created_vfs()
296 for (size_t j = 0; j < PCI_NUM_REGIONS; j++) { in pcie_sriov_pf_init_from_user_created_vfs()
297 if (vfs[i]->io_regions[j].size != vfs[0]->io_regions[j].size || in pcie_sriov_pf_init_from_user_created_vfs()
298 vfs[i]->io_regions[j].type != vfs[0]->io_regions[j].type) { in pcie_sriov_pf_init_from_user_created_vfs()
299 error_setg(errp, "inconsistent SR-IOV BARs"); in pcie_sriov_pf_init_from_user_created_vfs()
300 return -1; in pcie_sriov_pf_init_from_user_created_vfs()
304 if (vfs[i]->devfn - vfs[0]->devfn != vf_stride * i) { in pcie_sriov_pf_init_from_user_created_vfs()
305 error_setg(errp, "inconsistent SR-IOV stride"); in pcie_sriov_pf_init_from_user_created_vfs()
306 return -1; in pcie_sriov_pf_init_from_user_created_vfs()
310 if (!pcie_sriov_pf_init_common(dev, offset, vf_dev_id, pf->len, in pcie_sriov_pf_init_from_user_created_vfs()
311 pf->len, vf_offset, vf_stride, errp)) { in pcie_sriov_pf_init_from_user_created_vfs()
312 return -1; in pcie_sriov_pf_init_from_user_created_vfs()
315 if (!pcie_find_capability(dev, PCI_EXT_CAP_ID_ARI)) { in pcie_sriov_pf_init_from_user_created_vfs()
316 pcie_ari_init(dev, offset + size); in pcie_sriov_pf_init_from_user_created_vfs()
320 for (i = 0; i < pf->len; i++) { in pcie_sriov_pf_init_from_user_created_vfs()
321 vfs[i]->exp.sriov_vf.pf = dev; in pcie_sriov_pf_init_from_user_created_vfs()
322 vfs[i]->exp.sriov_vf.vf_number = i; in pcie_sriov_pf_init_from_user_created_vfs()
324 /* set vid/did according to sr/iov spec - they are not used */ in pcie_sriov_pf_init_from_user_created_vfs()
325 pci_config_set_vendor_id(vfs[i]->config, 0xffff); in pcie_sriov_pf_init_from_user_created_vfs()
326 pci_config_set_device_id(vfs[i]->config, 0xffff); in pcie_sriov_pf_init_from_user_created_vfs()
329 dev->exp.sriov_pf.vf = vfs; in pcie_sriov_pf_init_from_user_created_vfs()
330 dev->exp.sriov_pf.vf_user_created = true; in pcie_sriov_pf_init_from_user_created_vfs()
332 for (i = 0; i < PCI_NUM_REGIONS; i++) { in pcie_sriov_pf_init_from_user_created_vfs()
333 PCIIORegion *region = &vfs[0]->io_regions[i]; in pcie_sriov_pf_init_from_user_created_vfs()
335 if (region->size) { in pcie_sriov_pf_init_from_user_created_vfs()
336 pcie_sriov_pf_init_vf_bar(dev, i, region->type, region->size); in pcie_sriov_pf_init_from_user_created_vfs()
343 bool pcie_sriov_register_device(PCIDevice *dev, Error **errp) in pcie_sriov_register_device() argument
345 if (!dev->exp.sriov_pf.vf && dev->qdev.id && in pcie_sriov_register_device()
346 pfs && g_hash_table_contains(pfs, dev->qdev.id)) { in pcie_sriov_register_device()
347 error_setg(errp, "attaching user-created SR-IOV VF unsupported"); in pcie_sriov_register_device()
351 if (dev->sriov_pf) { in pcie_sriov_register_device()
355 if (!PCI_DEVICE_GET_CLASS(dev)->sriov_vf_user_creatable) { in pcie_sriov_register_device()
356 error_setg(errp, "user cannot create SR-IOV VF with this device type"); in pcie_sriov_register_device()
360 if (!pci_is_express(dev)) { in pcie_sriov_register_device()
361 error_setg(errp, "PCI Express is required for SR-IOV VF"); in pcie_sriov_register_device()
365 if (!pci_qdev_find_device(dev->sriov_pf, &pci_pf)) { in pcie_sriov_register_device()
366 error_setg(errp, "PCI device specified as SR-IOV PF already exists"); in pcie_sriov_register_device()
374 pf = g_hash_table_lookup(pfs, dev->sriov_pf); in pcie_sriov_register_device()
377 g_hash_table_insert(pfs, g_strdup(dev->sriov_pf), pf); in pcie_sriov_register_device()
380 g_ptr_array_add(pf, dev); in pcie_sriov_register_device()
386 void pcie_sriov_unregister_device(PCIDevice *dev) in pcie_sriov_unregister_device() argument
388 if (dev->sriov_pf && pfs) { in pcie_sriov_unregister_device()
389 GPtrArray *pf = g_hash_table_lookup(pfs, dev->sriov_pf); in pcie_sriov_unregister_device()
392 g_ptr_array_remove_fast(pf, dev); in pcie_sriov_unregister_device()
394 if (!pf->len) { in pcie_sriov_unregister_device()
395 g_hash_table_remove(pfs, dev->sriov_pf); in pcie_sriov_unregister_device()
402 void pcie_sriov_config_write(PCIDevice *dev, uint32_t address, in pcie_sriov_config_write() argument
406 uint16_t sriov_cap = dev->exp.sriov_cap; in pcie_sriov_config_write()
411 off = address - sriov_cap; in pcie_sriov_config_write()
416 trace_sriov_config_write(dev->name, PCI_SLOT(dev->devfn), in pcie_sriov_config_write()
417 PCI_FUNC(dev->devfn), off, val, len); in pcie_sriov_config_write()
421 register_vfs(dev); in pcie_sriov_config_write()
423 unregister_vfs(dev); in pcie_sriov_config_write()
426 uint8_t *cfg = dev->config + sriov_cap; in pcie_sriov_config_write()
427 uint8_t *wmask = dev->wmask + sriov_cap; in pcie_sriov_config_write()
439 void pcie_sriov_pf_post_load(PCIDevice *dev) in pcie_sriov_pf_post_load() argument
441 if (dev->exp.sriov_cap) { in pcie_sriov_pf_post_load()
442 register_vfs(dev); in pcie_sriov_pf_post_load()
448 void pcie_sriov_pf_reset(PCIDevice *dev) in pcie_sriov_pf_reset() argument
450 uint16_t sriov_cap = dev->exp.sriov_cap; in pcie_sriov_pf_reset()
455 pci_set_word(dev->config + sriov_cap + PCI_SRIOV_CTRL, 0); in pcie_sriov_pf_reset()
456 unregister_vfs(dev); in pcie_sriov_pf_reset()
458 pci_set_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF, 0); in pcie_sriov_pf_reset()
459 pci_set_word(dev->wmask + sriov_cap + PCI_SRIOV_CTRL, in pcie_sriov_pf_reset()
466 pci_set_word(dev->config + sriov_cap + PCI_SRIOV_SYS_PGSIZE, 0x1); in pcie_sriov_pf_reset()
468 for (uint16_t i = 0; i < PCI_NUM_REGIONS; i++) { in pcie_sriov_pf_reset()
469 pci_set_quad(dev->config + sriov_cap + PCI_SRIOV_BAR + i * 4, in pcie_sriov_pf_reset()
470 dev->exp.sriov_pf.vf_bar_type[i]); in pcie_sriov_pf_reset()
475 void pcie_sriov_pf_add_sup_pgsize(PCIDevice *dev, uint16_t opt_sup_pgsize) in pcie_sriov_pf_add_sup_pgsize() argument
477 uint8_t *cfg = dev->config + dev->exp.sriov_cap; in pcie_sriov_pf_add_sup_pgsize()
478 uint8_t *wmask = dev->wmask + dev->exp.sriov_cap; in pcie_sriov_pf_add_sup_pgsize()
493 uint16_t pcie_sriov_vf_number(PCIDevice *dev) in pcie_sriov_vf_number() argument
495 assert(dev->exp.sriov_vf.pf); in pcie_sriov_vf_number()
496 return dev->exp.sriov_vf.vf_number; in pcie_sriov_vf_number()
499 PCIDevice *pcie_sriov_get_pf(PCIDevice *dev) in pcie_sriov_get_pf() argument
501 return dev->exp.sriov_vf.pf; in pcie_sriov_get_pf()
504 PCIDevice *pcie_sriov_get_vf_at_index(PCIDevice *dev, int n) in pcie_sriov_get_vf_at_index() argument
506 assert(!pci_is_vf(dev)); in pcie_sriov_get_vf_at_index()
507 if (n < pcie_sriov_num_vfs(dev)) { in pcie_sriov_get_vf_at_index()
508 return dev->exp.sriov_pf.vf[n]; in pcie_sriov_get_vf_at_index()
513 uint16_t pcie_sriov_num_vfs(PCIDevice *dev) in pcie_sriov_num_vfs() argument
515 uint16_t sriov_cap = dev->exp.sriov_cap; in pcie_sriov_num_vfs()
516 uint8_t *cfg = dev->config + sriov_cap; in pcie_sriov_num_vfs()
520 pci_get_word(cfg + PCI_SRIOV_NUM_VF) : 0; in pcie_sriov_num_vfs()