mirror of https://github.com/xemu-project/xemu.git
s390x/pci: change the device array to a list
In order to support a greater number of devices we use a QTAILQ list of devices instead of a limited array. This leads us to change: - every lookup function s390_pci_find_xxx() for QTAILQ - the FH_MASK_INDEX to index up to 65536 devices Signed-off-by: Pierre Morel <pmorel@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
This commit is contained in:
parent
03805be081
commit
e70377dfa4
|
@ -93,33 +93,24 @@ int chsc_sei_nt2_have_event(void)
|
||||||
|
|
||||||
S390PCIBusDevice *s390_pci_find_next_avail_dev(S390PCIBusDevice *pbdev)
|
S390PCIBusDevice *s390_pci_find_next_avail_dev(S390PCIBusDevice *pbdev)
|
||||||
{
|
{
|
||||||
int idx = 0;
|
|
||||||
S390PCIBusDevice *dev = NULL;
|
|
||||||
S390pciState *s = s390_get_phb();
|
S390pciState *s = s390_get_phb();
|
||||||
|
S390PCIBusDevice *ret = pbdev ? QTAILQ_NEXT(pbdev, link) :
|
||||||
|
QTAILQ_FIRST(&s->zpci_devs);
|
||||||
|
|
||||||
if (pbdev) {
|
while (ret && ret->state == ZPCI_FS_RESERVED) {
|
||||||
idx = (pbdev->fh & FH_MASK_INDEX) + 1;
|
ret = QTAILQ_NEXT(ret, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; idx < PCI_SLOT_MAX; idx++) {
|
return ret;
|
||||||
dev = s->pbdev[idx];
|
|
||||||
if (dev && dev->state != ZPCI_FS_RESERVED) {
|
|
||||||
return dev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid)
|
S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid)
|
||||||
{
|
{
|
||||||
S390PCIBusDevice *pbdev;
|
S390PCIBusDevice *pbdev;
|
||||||
int i;
|
|
||||||
S390pciState *s = s390_get_phb();
|
S390pciState *s = s390_get_phb();
|
||||||
|
|
||||||
for (i = 0; i < PCI_SLOT_MAX; i++) {
|
QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
|
||||||
pbdev = s->pbdev[i];
|
if (pbdev->fid == fid) {
|
||||||
if (pbdev && pbdev->fid == fid) {
|
|
||||||
return pbdev;
|
return pbdev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,16 +194,10 @@ out:
|
||||||
|
|
||||||
static S390PCIBusDevice *s390_pci_find_dev_by_uid(uint16_t uid)
|
static S390PCIBusDevice *s390_pci_find_dev_by_uid(uint16_t uid)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
S390PCIBusDevice *pbdev;
|
S390PCIBusDevice *pbdev;
|
||||||
S390pciState *s = s390_get_phb();
|
S390pciState *s = s390_get_phb();
|
||||||
|
|
||||||
for (i = 0; i < PCI_SLOT_MAX; i++) {
|
QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
|
||||||
pbdev = s->pbdev[i];
|
|
||||||
if (!pbdev) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pbdev->uid == uid) {
|
if (pbdev->uid == uid) {
|
||||||
return pbdev;
|
return pbdev;
|
||||||
}
|
}
|
||||||
|
@ -223,7 +208,6 @@ static S390PCIBusDevice *s390_pci_find_dev_by_uid(uint16_t uid)
|
||||||
|
|
||||||
static S390PCIBusDevice *s390_pci_find_dev_by_target(const char *target)
|
static S390PCIBusDevice *s390_pci_find_dev_by_target(const char *target)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
S390PCIBusDevice *pbdev;
|
S390PCIBusDevice *pbdev;
|
||||||
S390pciState *s = s390_get_phb();
|
S390pciState *s = s390_get_phb();
|
||||||
|
|
||||||
|
@ -231,12 +215,7 @@ static S390PCIBusDevice *s390_pci_find_dev_by_target(const char *target)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < PCI_SLOT_MAX; i++) {
|
QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
|
||||||
pbdev = s->pbdev[i];
|
|
||||||
if (!pbdev) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(pbdev->target, target)) {
|
if (!strcmp(pbdev->target, target)) {
|
||||||
return pbdev;
|
return pbdev;
|
||||||
}
|
}
|
||||||
|
@ -247,9 +226,16 @@ static S390PCIBusDevice *s390_pci_find_dev_by_target(const char *target)
|
||||||
|
|
||||||
S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx)
|
S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx)
|
||||||
{
|
{
|
||||||
|
S390PCIBusDevice *pbdev;
|
||||||
S390pciState *s = s390_get_phb();
|
S390pciState *s = s390_get_phb();
|
||||||
|
|
||||||
return s->pbdev[idx & FH_MASK_INDEX];
|
QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
|
||||||
|
if (pbdev->idx == idx) {
|
||||||
|
return pbdev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh)
|
S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh)
|
||||||
|
@ -257,10 +243,11 @@ S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh)
|
||||||
S390pciState *s = s390_get_phb();
|
S390pciState *s = s390_get_phb();
|
||||||
S390PCIBusDevice *pbdev;
|
S390PCIBusDevice *pbdev;
|
||||||
|
|
||||||
pbdev = s->pbdev[fh & FH_MASK_INDEX];
|
QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
|
||||||
if (pbdev && pbdev->fh == fh) {
|
if (pbdev->fh == fh) {
|
||||||
return pbdev;
|
return pbdev;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -599,6 +586,7 @@ static int s390_pcihost_init(SysBusDevice *dev)
|
||||||
s->iommu_table = g_hash_table_new_full(g_int64_hash, g_int64_equal,
|
s->iommu_table = g_hash_table_new_full(g_int64_hash, g_int64_equal,
|
||||||
NULL, g_free);
|
NULL, g_free);
|
||||||
QTAILQ_INIT(&s->pending_sei);
|
QTAILQ_INIT(&s->pending_sei);
|
||||||
|
QTAILQ_INIT(&s->zpci_devs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,6 +654,25 @@ static S390PCIBusDevice *s390_pci_device_new(const char *target)
|
||||||
return S390_PCI_DEVICE(dev);
|
return S390_PCI_DEVICE(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool s390_pci_alloc_idx(S390PCIBusDevice *pbdev)
|
||||||
|
{
|
||||||
|
uint32_t idx;
|
||||||
|
S390pciState *s = s390_get_phb();
|
||||||
|
|
||||||
|
idx = s->next_idx;
|
||||||
|
while (s390_pci_find_dev_by_idx(idx)) {
|
||||||
|
idx = (idx + 1) & FH_MASK_INDEX;
|
||||||
|
if (idx == s->next_idx) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pbdev->idx = idx;
|
||||||
|
s->next_idx = (idx + 1) & FH_MASK_INDEX;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
|
static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
|
||||||
DeviceState *dev, Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
|
@ -713,18 +720,14 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
|
||||||
pbdev->fh, pbdev->fid);
|
pbdev->fh, pbdev->fid);
|
||||||
}
|
}
|
||||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) {
|
} else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) {
|
||||||
int idx;
|
|
||||||
|
|
||||||
pbdev = S390_PCI_DEVICE(dev);
|
pbdev = S390_PCI_DEVICE(dev);
|
||||||
for (idx = 0; idx < PCI_SLOT_MAX; idx++) {
|
|
||||||
if (!s->pbdev[idx]) {
|
if (!s390_pci_alloc_idx(pbdev)) {
|
||||||
s->pbdev[idx] = pbdev;
|
error_setg(errp, "no slot for plugging zpci device");
|
||||||
pbdev->fh = idx;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
pbdev->fh = pbdev->idx;
|
||||||
|
QTAILQ_INSERT_TAIL(&s->zpci_devs, pbdev, link);
|
||||||
error_setg(errp, "no slot for plugging zpci device");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,16 +753,15 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev,
|
||||||
{
|
{
|
||||||
PCIDevice *pci_dev = NULL;
|
PCIDevice *pci_dev = NULL;
|
||||||
PCIBus *bus;
|
PCIBus *bus;
|
||||||
int32_t devfn, i;
|
int32_t devfn;
|
||||||
S390PCIBusDevice *pbdev = NULL;
|
S390PCIBusDevice *pbdev = NULL;
|
||||||
S390pciState *s = s390_get_phb();
|
S390pciState *s = s390_get_phb();
|
||||||
|
|
||||||
if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
|
if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
|
||||||
pci_dev = PCI_DEVICE(dev);
|
pci_dev = PCI_DEVICE(dev);
|
||||||
|
|
||||||
for (i = 0 ; i < PCI_SLOT_MAX; i++) {
|
QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) {
|
||||||
if (s->pbdev[i] && s->pbdev[i]->pdev == pci_dev) {
|
if (pbdev->pdev == pci_dev) {
|
||||||
pbdev = s->pbdev[i];
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -802,7 +804,7 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev,
|
||||||
pbdev->state = ZPCI_FS_RESERVED;
|
pbdev->state = ZPCI_FS_RESERVED;
|
||||||
out:
|
out:
|
||||||
pbdev->fid = 0;
|
pbdev->fid = 0;
|
||||||
s->pbdev[pbdev->fh & FH_MASK_INDEX] = NULL;
|
QTAILQ_REMOVE(&s->zpci_devs, pbdev, link);
|
||||||
object_unparent(OBJECT(pbdev));
|
object_unparent(OBJECT(pbdev));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#define FH_MASK_ENABLE 0x80000000
|
#define FH_MASK_ENABLE 0x80000000
|
||||||
#define FH_MASK_INSTANCE 0x7f000000
|
#define FH_MASK_INSTANCE 0x7f000000
|
||||||
#define FH_MASK_SHM 0x00ff0000
|
#define FH_MASK_SHM 0x00ff0000
|
||||||
#define FH_MASK_INDEX 0x0000001f
|
#define FH_MASK_INDEX 0x0000ffff
|
||||||
#define FH_SHM_VFIO 0x00010000
|
#define FH_SHM_VFIO 0x00010000
|
||||||
#define FH_SHM_EMUL 0x00020000
|
#define FH_SHM_EMUL 0x00020000
|
||||||
#define S390_PCIPT_ADAPTER 2
|
#define S390_PCIPT_ADAPTER 2
|
||||||
|
@ -285,6 +285,7 @@ typedef struct S390PCIBusDevice {
|
||||||
ZpciState state;
|
ZpciState state;
|
||||||
char *target;
|
char *target;
|
||||||
uint16_t uid;
|
uint16_t uid;
|
||||||
|
uint32_t idx;
|
||||||
uint32_t fh;
|
uint32_t fh;
|
||||||
uint32_t fid;
|
uint32_t fid;
|
||||||
bool fid_defined;
|
bool fid_defined;
|
||||||
|
@ -299,6 +300,7 @@ typedef struct S390PCIBusDevice {
|
||||||
IndAddr *summary_ind;
|
IndAddr *summary_ind;
|
||||||
IndAddr *indicator;
|
IndAddr *indicator;
|
||||||
QEMUTimer *release_timer;
|
QEMUTimer *release_timer;
|
||||||
|
QTAILQ_ENTRY(S390PCIBusDevice) link;
|
||||||
} S390PCIBusDevice;
|
} S390PCIBusDevice;
|
||||||
|
|
||||||
typedef struct S390PCIBus {
|
typedef struct S390PCIBus {
|
||||||
|
@ -307,10 +309,11 @@ typedef struct S390PCIBus {
|
||||||
|
|
||||||
typedef struct S390pciState {
|
typedef struct S390pciState {
|
||||||
PCIHostState parent_obj;
|
PCIHostState parent_obj;
|
||||||
|
uint32_t next_idx;
|
||||||
S390PCIBus *bus;
|
S390PCIBus *bus;
|
||||||
S390PCIBusDevice *pbdev[PCI_SLOT_MAX];
|
|
||||||
GHashTable *iommu_table;
|
GHashTable *iommu_table;
|
||||||
QTAILQ_HEAD(, SeiContainer) pending_sei;
|
QTAILQ_HEAD(, SeiContainer) pending_sei;
|
||||||
|
QTAILQ_HEAD(, S390PCIBusDevice) zpci_devs;
|
||||||
} S390pciState;
|
} S390pciState;
|
||||||
|
|
||||||
int chsc_sei_nt2_get_event(void *res);
|
int chsc_sei_nt2_get_event(void *res);
|
||||||
|
|
Loading…
Reference in New Issue