All of lore.kernel.org
 help / color / mirror / Atom feed
From: Roger Pau Monne <roger.pau@citrix.com>
To: xen-devel@lists.xenproject.org, boris.ostrovsky@oracle.com,
	konrad.wilk@oracle.com
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
	Jan Beulich <jbeulich@suse.com>,
	Roger Pau Monne <roger.pau@citrix.com>
Subject: [PATCH v4 2/4] x86/physdev: factor out the code to allocate and map a pirq
Date: Thu, 1 Jun 2017 12:49:12 +0100	[thread overview]
Message-ID: <20170601114914.18601-3-roger.pau@citrix.com> (raw)
In-Reply-To: <20170601114914.18601-1-roger.pau@citrix.com>

Move the code to allocate and map a domain pirq (either GSI or MSI)
into the x86 irq code base, so that it can be used outside of the
physdev ops.

This change shouldn't affect the functionality of the already existing
physdev ops.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
---
Changes since v3:
 - Pass the index parameter to the allocate_pirq function, so that it
   can be printed in case of error.
 - Remove pointless elses in allocate_pirq.
 - Return directly in the last check of allocate_pirq (instead of
   storing the error code in the pirq variable.
 - allocate_and_map_{gsi/msi}_pirq don't need index to be a pointer.
 - Fix the last parameter of the allocate_pirq call in
   allocate_and_map_gsi_pirq to use NULL (instead of 0).
 - Add an ASSERT_UNREACHABLE if the interrupt type passed to
   allocate_and_map_msi_pirq is not of MSI the MSI kind.
 - Restore newlines in the physdev_map_pirq switch case.

Changes since v2:
 - Factor out the code to allocate the pirq.
 - Fix coding style issues.
 - Do not take the pci lock to bind a GSI.
 - Pass a type parameter to the MSI bind function.

Changes since v1:
 - New in this version.
---
 xen/arch/x86/irq.c        | 159 ++++++++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/physdev.c    | 122 ++---------------------------------
 xen/include/asm-x86/irq.h |   5 ++
 3 files changed, 169 insertions(+), 117 deletions(-)

diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index 676ba5216f..5184b6144e 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2537,3 +2537,162 @@ bool_t hvm_domain_use_pirq(const struct domain *d, const struct pirq *pirq)
     return is_hvm_domain(d) && pirq &&
            pirq->arch.hvm.emuirq != IRQ_UNBOUND; 
 }
+
+static int allocate_pirq(struct domain *d, int index, int pirq, int irq,
+                         int type, int *nr)
+{
+    int current_pirq;
+
+    ASSERT(spin_is_locked(&d->event_lock));
+    current_pirq = domain_irq_to_pirq(d, irq);
+    if ( pirq < 0 )
+    {
+        if ( current_pirq )
+        {
+            dprintk(XENLOG_G_ERR, "dom%d: %d:%d already mapped to %d\n",
+                    d->domain_id, index, pirq, current_pirq);
+            if ( current_pirq < 0 )
+                return -EBUSY;
+        }
+        else if ( type == MAP_PIRQ_TYPE_MULTI_MSI )
+        {
+            if ( *nr <= 0 || *nr > 32 )
+                return -EDOM;
+            if ( *nr != 1 && !iommu_intremap )
+                return -EOPNOTSUPP;
+
+            while ( *nr & (*nr - 1) )
+                *nr += *nr & -*nr;
+            pirq = get_free_pirqs(d, *nr);
+            if ( pirq < 0 )
+            {
+                while ( (*nr >>= 1) > 1 )
+                    if ( get_free_pirqs(d, *nr) > 0 )
+                        break;
+                dprintk(XENLOG_G_ERR, "dom%d: no block of %d free pirqs\n",
+                        d->domain_id, *nr << 1);
+            }
+        }
+        else
+        {
+            pirq = get_free_pirq(d, type);
+            if ( pirq < 0 )
+                dprintk(XENLOG_G_ERR, "dom%d: no free pirq\n", d->domain_id);
+        }
+    }
+    else if ( current_pirq && pirq != current_pirq )
+    {
+        dprintk(XENLOG_G_ERR, "dom%d: irq %d already mapped to pirq %d\n",
+                d->domain_id, irq, current_pirq);
+        return -EEXIST;
+    }
+
+    return pirq;
+}
+
+int allocate_and_map_gsi_pirq(struct domain *d, int index, int *pirq_p)
+{
+    int irq, pirq, ret;
+
+    if ( index < 0 || index >= nr_irqs_gsi )
+    {
+        dprintk(XENLOG_G_ERR, "dom%d: map invalid irq %d\n", d->domain_id,
+                index);
+        return -EINVAL;
+    }
+
+    irq = domain_pirq_to_irq(current->domain, index);
+    if ( irq <= 0 )
+    {
+        if ( is_hardware_domain(current->domain) )
+            irq = index;
+        else
+        {
+            dprintk(XENLOG_G_ERR, "dom%d: map pirq with incorrect irq!\n",
+                    d->domain_id);
+            return -EINVAL;
+        }
+    }
+
+    /* Verify or get pirq. */
+    spin_lock(&d->event_lock);
+    pirq = allocate_pirq(d, index, *pirq_p, irq, MAP_PIRQ_TYPE_GSI, NULL);
+    if ( pirq < 0 )
+    {
+        ret = pirq;
+        goto done;
+    }
+
+    ret = map_domain_pirq(d, pirq, irq, MAP_PIRQ_TYPE_GSI, NULL);
+    if ( ret == 0 )
+        *pirq_p = pirq;
+
+ done:
+    spin_unlock(&d->event_lock);
+
+    return ret;
+}
+
+int allocate_and_map_msi_pirq(struct domain *d, int index, int *pirq_p,
+                              int type, struct msi_info *msi)
+{
+    int irq, pirq, ret;
+
+    switch ( type )
+    {
+    case MAP_PIRQ_TYPE_MSI:
+        if ( !msi->table_base )
+            msi->entry_nr = 1;
+        irq = index;
+        if ( irq == -1 )
+    case MAP_PIRQ_TYPE_MULTI_MSI:
+            irq = create_irq(NUMA_NO_NODE);
+
+        if ( irq < nr_irqs_gsi || irq >= nr_irqs )
+        {
+            dprintk(XENLOG_G_ERR, "dom%d: can't create irq for msi!\n",
+                    d->domain_id);
+            return -EINVAL;
+        }
+
+        msi->irq = irq;
+        break;
+
+    default:
+        dprintk(XENLOG_G_ERR, "dom%d: wrong pirq type %x\n",
+                d->domain_id, type);
+        ASSERT_UNREACHABLE();
+        return -EINVAL;
+    }
+
+    msi->irq = irq;
+
+    pcidevs_lock();
+    /* Verify or get pirq. */
+    spin_lock(&d->event_lock);
+    pirq = allocate_pirq(d, index, *pirq_p, irq, type, &msi->entry_nr);
+    if ( pirq < 0 )
+    {
+        ret = pirq;
+        goto done;
+    }
+
+    ret = map_domain_pirq(d, pirq, irq, type, msi);
+    if ( ret == 0 )
+        *pirq_p = pirq;
+
+ done:
+    spin_unlock(&d->event_lock);
+    pcidevs_unlock();
+    if ( ret != 0 )
+        switch ( type )
+        {
+        case MAP_PIRQ_TYPE_MSI:
+            if ( index == -1 )
+        case MAP_PIRQ_TYPE_MULTI_MSI:
+                destroy_irq(irq);
+            break;
+        }
+
+    return ret;
+}
diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c
index eec4a41231..0eb409758f 100644
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -92,8 +92,7 @@ int physdev_map_pirq(domid_t domid, int type, int *index, int *pirq_p,
                      struct msi_info *msi)
 {
     struct domain *d = current->domain;
-    int pirq, irq, ret = 0;
-    void *map_data = NULL;
+    int ret;
 
     if ( domid == DOMID_SELF && is_hvm_domain(d) && has_pirq(d) )
     {
@@ -119,135 +118,24 @@ int physdev_map_pirq(domid_t domid, int type, int *index, int *pirq_p,
     switch ( type )
     {
     case MAP_PIRQ_TYPE_GSI:
-        if ( *index < 0 || *index >= nr_irqs_gsi )
-        {
-            dprintk(XENLOG_G_ERR, "dom%d: map invalid irq %d\n",
-                    d->domain_id, *index);
-            ret = -EINVAL;
-            goto free_domain;
-        }
-
-        irq = domain_pirq_to_irq(current->domain, *index);
-        if ( irq <= 0 )
-        {
-            if ( is_hardware_domain(current->domain) )
-                irq = *index;
-            else {
-                dprintk(XENLOG_G_ERR, "dom%d: map pirq with incorrect irq!\n",
-                        d->domain_id);
-                ret = -EINVAL;
-                goto free_domain;
-            }
-        }
+        ret = allocate_and_map_gsi_pirq(d, *index, pirq_p);
         break;
 
     case MAP_PIRQ_TYPE_MSI:
         if ( !msi->table_base )
             msi->entry_nr = 1;
-        irq = *index;
-        if ( irq == -1 )
+        /* fallthrough */
     case MAP_PIRQ_TYPE_MULTI_MSI:
-            irq = create_irq(NUMA_NO_NODE);
-
-        if ( irq < nr_irqs_gsi || irq >= nr_irqs )
-        {
-            dprintk(XENLOG_G_ERR, "dom%d: can't create irq for msi!\n",
-                    d->domain_id);
-            ret = -EINVAL;
-            goto free_domain;
-        }
-
-        msi->irq = irq;
-        map_data = msi;
+        ret = allocate_and_map_msi_pirq(d, *index, pirq_p, type, msi);
         break;
 
     default:
         dprintk(XENLOG_G_ERR, "dom%d: wrong map_pirq type %x\n",
                 d->domain_id, type);
         ret = -EINVAL;
-        goto free_domain;
-    }
-
-    pcidevs_lock();
-    /* Verify or get pirq. */
-    spin_lock(&d->event_lock);
-    pirq = domain_irq_to_pirq(d, irq);
-    if ( *pirq_p < 0 )
-    {
-        if ( pirq )
-        {
-            dprintk(XENLOG_G_ERR, "dom%d: %d:%d already mapped to %d\n",
-                    d->domain_id, *index, *pirq_p, pirq);
-            if ( pirq < 0 )
-            {
-                ret = -EBUSY;
-                goto done;
-            }
-        }
-        else if ( type == MAP_PIRQ_TYPE_MULTI_MSI )
-        {
-            if ( msi->entry_nr <= 0 || msi->entry_nr > 32 )
-                ret = -EDOM;
-            else if ( msi->entry_nr != 1 && !iommu_intremap )
-                ret = -EOPNOTSUPP;
-            else
-            {
-                while ( msi->entry_nr & (msi->entry_nr - 1) )
-                    msi->entry_nr += msi->entry_nr & -msi->entry_nr;
-                pirq = get_free_pirqs(d, msi->entry_nr);
-                if ( pirq < 0 )
-                {
-                    while ( (msi->entry_nr >>= 1) > 1 )
-                        if ( get_free_pirqs(d, msi->entry_nr) > 0 )
-                            break;
-                    dprintk(XENLOG_G_ERR, "dom%d: no block of %d free pirqs\n",
-                            d->domain_id, msi->entry_nr << 1);
-                    ret = pirq;
-                }
-            }
-            if ( ret < 0 )
-                goto done;
-        }
-        else
-        {
-            pirq = get_free_pirq(d, type);
-            if ( pirq < 0 )
-            {
-                dprintk(XENLOG_G_ERR, "dom%d: no free pirq\n", d->domain_id);
-                ret = pirq;
-                goto done;
-            }
-        }
-    }
-    else
-    {
-        if ( pirq && pirq != *pirq_p )
-        {
-            dprintk(XENLOG_G_ERR, "dom%d: pirq %d conflicts with irq %d\n",
-                    d->domain_id, *index, *pirq_p);
-            ret = -EEXIST;
-            goto done;
-        }
-        else
-            pirq = *pirq_p;
+        break;
     }
 
-    ret = map_domain_pirq(d, pirq, irq, type, map_data);
-    if ( ret == 0 )
-        *pirq_p = pirq;
-
- done:
-    spin_unlock(&d->event_lock);
-    pcidevs_unlock();
-    if ( ret != 0 )
-        switch ( type )
-        {
-        case MAP_PIRQ_TYPE_MSI:
-            if ( *index == -1 )
-        case MAP_PIRQ_TYPE_MULTI_MSI:
-                destroy_irq(irq);
-            break;
-        }
  free_domain:
     rcu_unlock_domain(d);
     return ret;
diff --git a/xen/include/asm-x86/irq.h b/xen/include/asm-x86/irq.h
index ef625ebb13..182caa44be 100644
--- a/xen/include/asm-x86/irq.h
+++ b/xen/include/asm-x86/irq.h
@@ -200,4 +200,9 @@ bool_t cpu_has_pending_apic_eoi(void);
 
 static inline void arch_move_irqs(struct vcpu *v) { }
 
+struct msi_info;
+int allocate_and_map_gsi_pirq(struct domain *d, int index, int *pirq_p);
+int allocate_and_map_msi_pirq(struct domain *d, int index, int *pirq_p,
+                              int type, struct msi_info *msi);
+
 #endif /* _ASM_HW_IRQ_H */
-- 
2.11.0 (Apple Git-81)


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  parent reply	other threads:[~2017-06-01 11:49 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-01 11:49 [PATCH v4 0/4] x86/dpci: bind legacy PCI interrupts to PVHv2 Dom0 Roger Pau Monne
2017-06-01 11:49 ` [PATCH v4 1/4] x86/pt: remove hvm_domid field from bind struct Roger Pau Monne
2017-06-01 11:57   ` Wei Liu
2017-06-01 13:17   ` Jan Beulich
2017-06-01 14:45     ` Roger Pau Monne
2017-06-01 11:49 ` Roger Pau Monne [this message]
2017-06-01 14:20   ` [PATCH v4 2/4] x86/physdev: factor out the code to allocate and map a pirq Jan Beulich
2017-06-01 14:40   ` Andrew Cooper
2017-06-01 15:20     ` Roger Pau Monne
2017-06-01 11:49 ` [PATCH v4 3/4] x86/pt: enable binding of GSIs to a PVH Dom0 Roger Pau Monne
2017-06-01 22:13   ` Boris Ostrovsky
2017-06-02  8:41     ` Roger Pau Monne
2017-06-02 12:46       ` Boris Ostrovsky
2017-06-02 13:58         ` [PATCH v4.1 " Roger Pau Monne
2017-06-07 13:17           ` Jan Beulich
2017-06-19 16:45             ` Roger Pau Monne
2017-06-20  7:19               ` Jan Beulich
2017-06-01 11:49 ` [PATCH v4 4/4] x86/vioapic: bind interrupts to " Roger Pau Monne
2017-06-07 13:20   ` Jan Beulich
2017-06-19 17:04     ` Roger Pau Monne

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170601114914.18601-3-roger.pau@citrix.com \
    --to=roger.pau@citrix.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=jbeulich@suse.com \
    --cc=konrad.wilk@oracle.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.