mirror of https://github.com/xemu-project/xemu.git
spapr_pci: fix MSI limit
At the moment XICS does not support interrupts reuse so sPAPR PHB implements this. sPAPRPHBState holds array of 32 spapr_pci_msi to describe PCI config address, first MSI and number of MSIs. Once allocated for a device, QEMU tries reusing this config until the number of MSIs changes. Existing SPAPR guests call ibm,change-msi in a loop until the handler returns the requested number of vectors. Recently introduced check for the maximum number of MSI/MSIX vectors supported by a device only works for a device which is new for PHB's MSI cache. If it is already there, the check is not performed which leads to new IRQ block allocation. This happens during PCI hotplug even when the user hot plug the same device which he just hot unplugged. This moves the check earlier. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
804e654a56
commit
28668b5f31
|
@ -280,7 +280,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||
unsigned int req_num = rtas_ld(args, 4); /* 0 == remove all */
|
||||
unsigned int seq_num = rtas_ld(args, 5);
|
||||
unsigned int ret_intr_type;
|
||||
int ndev, irq;
|
||||
int ndev, irq, max_irqs = 0;
|
||||
sPAPRPHBState *phb = NULL;
|
||||
PCIDevice *pdev = NULL;
|
||||
|
||||
|
@ -333,17 +333,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||
}
|
||||
trace_spapr_pci_msi("Configuring MSI", ndev, config_addr);
|
||||
|
||||
/* Check if there is an old config and MSI number has not changed */
|
||||
if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) {
|
||||
/* Unexpected behaviour */
|
||||
error_report("Cannot reuse MSI config for device#%d", ndev);
|
||||
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
/* There is no cached config, allocate MSIs */
|
||||
if (!phb->msi_table[ndev].nvec) {
|
||||
int max_irqs = 0;
|
||||
/* Check if the device supports as many IRQs as requested */
|
||||
if (ret_intr_type == RTAS_TYPE_MSI) {
|
||||
max_irqs = msi_nr_vectors_allocated(pdev);
|
||||
} else if (ret_intr_type == RTAS_TYPE_MSIX) {
|
||||
|
@ -355,9 +345,21 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
|||
rtas_st(rets, 0, -1); /* Hardware error */
|
||||
return;
|
||||
}
|
||||
/* Correct the number if the guest asked for too many */
|
||||
if (req_num > max_irqs) {
|
||||
req_num = max_irqs;
|
||||
}
|
||||
|
||||
/* Check if there is an old config and MSI number has not changed */
|
||||
if (phb->msi_table[ndev].nvec && (req_num != phb->msi_table[ndev].nvec)) {
|
||||
/* Unexpected behaviour */
|
||||
error_report("Cannot reuse MSI config for device#%d", ndev);
|
||||
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
/* There is no cached config, allocate MSIs */
|
||||
if (!phb->msi_table[ndev].nvec) {
|
||||
irq = spapr_allocate_irq_block(req_num, false,
|
||||
ret_intr_type == RTAS_TYPE_MSI);
|
||||
if (irq < 0) {
|
||||
|
|
Loading…
Reference in New Issue