mirror of https://github.com/xemu-project/xemu.git
Revert "pcie_sriov: Reuse SR-IOV VF device instances"
This reverts commit 139610ae67
.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
9bab08da4e
commit
b1282f1e35
|
@ -2895,7 +2895,7 @@ void pci_set_enabled(PCIDevice *d, bool state)
|
|||
memory_region_set_enabled(&d->bus_master_enable_region,
|
||||
(pci_get_word(d->config + PCI_COMMAND)
|
||||
& PCI_COMMAND_MASTER) && d->enabled);
|
||||
if (d->qdev.realized) {
|
||||
if (!d->enabled) {
|
||||
pci_device_reset(d);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,16 +20,9 @@
|
|||
#include "qapi/error.h"
|
||||
#include "trace.h"
|
||||
|
||||
static void unparent_vfs(PCIDevice *dev, uint16_t total_vfs)
|
||||
{
|
||||
for (uint16_t i = 0; i < total_vfs; i++) {
|
||||
PCIDevice *vf = dev->exp.sriov_pf.vf[i];
|
||||
object_unparent(OBJECT(vf));
|
||||
object_unref(OBJECT(vf));
|
||||
}
|
||||
g_free(dev->exp.sriov_pf.vf);
|
||||
dev->exp.sriov_pf.vf = NULL;
|
||||
}
|
||||
static PCIDevice *register_vf(PCIDevice *pf, int devfn,
|
||||
const char *name, uint16_t vf_num);
|
||||
static void unregister_vfs(PCIDevice *dev);
|
||||
|
||||
bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset,
|
||||
const char *vfname, uint16_t vf_dev_id,
|
||||
|
@ -37,8 +30,6 @@ bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset,
|
|||
uint16_t vf_offset, uint16_t vf_stride,
|
||||
Error **errp)
|
||||
{
|
||||
BusState *bus = qdev_get_parent_bus(&dev->qdev);
|
||||
int32_t devfn = dev->devfn + vf_offset;
|
||||
uint8_t *cfg = dev->config + offset;
|
||||
uint8_t *wmask;
|
||||
|
||||
|
@ -58,6 +49,7 @@ bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset,
|
|||
offset, PCI_EXT_CAP_SRIOV_SIZEOF);
|
||||
dev->exp.sriov_cap = offset;
|
||||
dev->exp.sriov_pf.num_vfs = 0;
|
||||
dev->exp.sriov_pf.vfname = g_strdup(vfname);
|
||||
dev->exp.sriov_pf.vf = NULL;
|
||||
|
||||
pci_set_word(cfg + PCI_SRIOV_VF_OFFSET, vf_offset);
|
||||
|
@ -91,34 +83,14 @@ bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset,
|
|||
|
||||
qdev_prop_set_bit(&dev->qdev, "multifunction", true);
|
||||
|
||||
dev->exp.sriov_pf.vf = g_new(PCIDevice *, total_vfs);
|
||||
|
||||
for (uint16_t i = 0; i < total_vfs; i++) {
|
||||
PCIDevice *vf = pci_new(devfn, vfname);
|
||||
vf->exp.sriov_vf.pf = dev;
|
||||
vf->exp.sriov_vf.vf_number = i;
|
||||
|
||||
if (!qdev_realize(&vf->qdev, bus, errp)) {
|
||||
unparent_vfs(dev, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* set vid/did according to sr/iov spec - they are not used */
|
||||
pci_config_set_vendor_id(vf->config, 0xffff);
|
||||
pci_config_set_device_id(vf->config, 0xffff);
|
||||
|
||||
dev->exp.sriov_pf.vf[i] = vf;
|
||||
devfn += vf_stride;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void pcie_sriov_pf_exit(PCIDevice *dev)
|
||||
{
|
||||
uint8_t *cfg = dev->config + dev->exp.sriov_cap;
|
||||
|
||||
unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF));
|
||||
unregister_vfs(dev);
|
||||
g_free((char *)dev->exp.sriov_pf.vfname);
|
||||
dev->exp.sriov_pf.vfname = NULL;
|
||||
}
|
||||
|
||||
void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int region_num,
|
||||
|
@ -184,11 +156,38 @@ void pcie_sriov_vf_register_bar(PCIDevice *dev, int region_num,
|
|||
}
|
||||
}
|
||||
|
||||
static PCIDevice *register_vf(PCIDevice *pf, int devfn, const char *name,
|
||||
uint16_t vf_num)
|
||||
{
|
||||
PCIDevice *dev = pci_new(devfn, name);
|
||||
dev->exp.sriov_vf.pf = pf;
|
||||
dev->exp.sriov_vf.vf_number = vf_num;
|
||||
PCIBus *bus = pci_get_bus(pf);
|
||||
Error *local_err = NULL;
|
||||
|
||||
qdev_realize(&dev->qdev, &bus->qbus, &local_err);
|
||||
if (local_err) {
|
||||
error_report_err(local_err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set vid/did according to sr/iov spec - they are not used */
|
||||
pci_config_set_vendor_id(dev->config, 0xffff);
|
||||
pci_config_set_device_id(dev->config, 0xffff);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
static void register_vfs(PCIDevice *dev)
|
||||
{
|
||||
uint16_t num_vfs;
|
||||
uint16_t i;
|
||||
uint16_t sriov_cap = dev->exp.sriov_cap;
|
||||
uint16_t vf_offset =
|
||||
pci_get_word(dev->config + sriov_cap + PCI_SRIOV_VF_OFFSET);
|
||||
uint16_t vf_stride =
|
||||
pci_get_word(dev->config + sriov_cap + PCI_SRIOV_VF_STRIDE);
|
||||
int32_t devfn = dev->devfn + vf_offset;
|
||||
|
||||
assert(sriov_cap > 0);
|
||||
num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF);
|
||||
|
@ -196,10 +195,18 @@ static void register_vfs(PCIDevice *dev)
|
|||
return;
|
||||
}
|
||||
|
||||
dev->exp.sriov_pf.vf = g_new(PCIDevice *, num_vfs);
|
||||
|
||||
trace_sriov_register_vfs(dev->name, PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn), num_vfs);
|
||||
for (i = 0; i < num_vfs; i++) {
|
||||
pci_set_enabled(dev->exp.sriov_pf.vf[i], true);
|
||||
dev->exp.sriov_pf.vf[i] = register_vf(dev, devfn,
|
||||
dev->exp.sriov_pf.vfname, i);
|
||||
if (!dev->exp.sriov_pf.vf[i]) {
|
||||
num_vfs = i;
|
||||
break;
|
||||
}
|
||||
devfn += vf_stride;
|
||||
}
|
||||
dev->exp.sriov_pf.num_vfs = num_vfs;
|
||||
}
|
||||
|
@ -212,8 +219,12 @@ static void unregister_vfs(PCIDevice *dev)
|
|||
trace_sriov_unregister_vfs(dev->name, PCI_SLOT(dev->devfn),
|
||||
PCI_FUNC(dev->devfn), num_vfs);
|
||||
for (i = 0; i < num_vfs; i++) {
|
||||
pci_set_enabled(dev->exp.sriov_pf.vf[i], false);
|
||||
PCIDevice *vf = dev->exp.sriov_pf.vf[i];
|
||||
object_unparent(OBJECT(vf));
|
||||
object_unref(OBJECT(vf));
|
||||
}
|
||||
g_free(dev->exp.sriov_pf.vf);
|
||||
dev->exp.sriov_pf.vf = NULL;
|
||||
dev->exp.sriov_pf.num_vfs = 0;
|
||||
}
|
||||
|
||||
|
@ -235,10 +246,14 @@ void pcie_sriov_config_write(PCIDevice *dev, uint32_t address,
|
|||
PCI_FUNC(dev->devfn), off, val, len);
|
||||
|
||||
if (range_covers_byte(off, len, PCI_SRIOV_CTRL)) {
|
||||
if (val & PCI_SRIOV_CTRL_VFE) {
|
||||
register_vfs(dev);
|
||||
if (dev->exp.sriov_pf.num_vfs) {
|
||||
if (!(val & PCI_SRIOV_CTRL_VFE)) {
|
||||
unregister_vfs(dev);
|
||||
}
|
||||
} else {
|
||||
unregister_vfs(dev);
|
||||
if (val & PCI_SRIOV_CTRL_VFE) {
|
||||
register_vfs(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -680,4 +680,9 @@ static inline void pci_irq_pulse(PCIDevice *pci_dev)
|
|||
MSIMessage pci_get_msi_message(PCIDevice *dev, int vector);
|
||||
void pci_set_enabled(PCIDevice *pci_dev, bool state);
|
||||
|
||||
static inline void pci_set_power(PCIDevice *pci_dev, bool state)
|
||||
{
|
||||
pci_set_enabled(pci_dev, state);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -212,21 +212,6 @@ static inline uint16_t pci_get_bdf(PCIDevice *dev)
|
|||
return PCI_BUILD_BDF(pci_bus_num(pci_get_bus(dev)), dev->devfn);
|
||||
}
|
||||
|
||||
static inline void pci_set_power(PCIDevice *pci_dev, bool state)
|
||||
{
|
||||
/*
|
||||
* Don't change the enabled state of VFs when powering on/off the device.
|
||||
*
|
||||
* When powering on, VFs must not be enabled immediately but they must
|
||||
* wait until the guest configures SR-IOV.
|
||||
* When powering off, their corresponding PFs will be reset and disable
|
||||
* VFs.
|
||||
*/
|
||||
if (!pci_is_vf(pci_dev)) {
|
||||
pci_set_enabled(pci_dev, state);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t pci_requester_id(PCIDevice *dev);
|
||||
|
||||
/* DMA access functions */
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
typedef struct PCIESriovPF {
|
||||
uint16_t num_vfs; /* Number of virtual functions created */
|
||||
uint8_t vf_bar_type[PCI_NUM_REGIONS]; /* Store type for each VF bar */
|
||||
const char *vfname; /* Reference to the device type used for the VFs */
|
||||
PCIDevice **vf; /* Pointer to an array of num_vfs VF devices */
|
||||
} PCIESriovPF;
|
||||
|
||||
|
|
Loading…
Reference in New Issue