diff mbox

spapr_pci: fix MSI limit

Message ID 1399212588-23304-1-git-send-email-aik@ozlabs.ru
State New
Headers show

Commit Message

Alexey Kardashevskiy May 4, 2014, 2:09 p.m. UTC
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>
---

I believe the proper fix would be implementing interrupt reuse which
I posted a while ago in [PATCH 0/8] spapr: fix IOMMU and XICS/IRQs migration,
patches 2..7 (ignore first anmd last patches of that set):

xics: add flags for interrupts
xics: add find_server
xics: add pre_load() hook to ICSStateClass
xics: disable flags reset on xics reset
spapr: move interrupt allocator to xics
spapr: remove @next_irq

This would allow us to get rid of sPAPRPHBState::msi_state.

Please comment. Thanks!
---
 hw/ppc/spapr_pci.c | 34 ++++++++++++++++++----------------
 1 file changed, 18 insertions(+), 16 deletions(-)

Comments

Alexander Graf May 8, 2014, 10 a.m. UTC | #1
On 05/04/2014 04:09 PM, Alexey Kardashevskiy wrote:
> 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>

Thanks, applied to ppc-next.


Alex
diff mbox

Patch

diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index c052917..1db73f2 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -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,6 +333,23 @@  static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
     }
     trace_spapr_pci_msi("Configuring MSI", ndev, config_addr);
 
+    /* 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) {
+        max_irqs = pdev->msix_entries_nr;
+    }
+    if (!max_irqs) {
+        error_report("Requested interrupt type %d is not enabled for device#%d",
+                     ret_intr_type, ndev);
+        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 */
@@ -343,21 +360,6 @@  static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
 
     /* There is no cached config, allocate MSIs */
     if (!phb->msi_table[ndev].nvec) {
-        int max_irqs = 0;
-        if (ret_intr_type == RTAS_TYPE_MSI) {
-            max_irqs = msi_nr_vectors_allocated(pdev);
-        } else if (ret_intr_type == RTAS_TYPE_MSIX) {
-            max_irqs = pdev->msix_entries_nr;
-        }
-        if (!max_irqs) {
-            error_report("Requested interrupt type %d is not enabled for device#%d",
-                         ret_intr_type, ndev);
-            rtas_st(rets, 0, -1); /* Hardware error */
-            return;
-        }
-        if (req_num > max_irqs) {
-            req_num = max_irqs;
-        }
         irq = spapr_allocate_irq_block(req_num, false,
                                        ret_intr_type == RTAS_TYPE_MSI);
         if (irq < 0) {