[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC PATCH 03/19] xen/arm: its: Port ITS driver to xen



From: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx>

This patch just makes ITS driver taken from linux
compiles in xen environment.

The following changes are done
 - memory allocation apis are changed
 - raw spin lock api's changed to normal spin lock api's
 - debug prints changed to xen debug prints
 - remove msi chip functions to setup_irq and teardown_irq
 - linux irqchip functions are removed
 - updated gic_v3_defs.h file

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx>
---
 xen/arch/arm/Makefile             |    1 +
 xen/arch/arm/gic-v3-its.c         |  548 +++++++++++++------------------------
 xen/arch/arm/gic-v3.c             |    1 +
 xen/include/asm-arm/gic_v3_defs.h |  127 +++++++++
 4 files changed, 322 insertions(+), 355 deletions(-)

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 41aba2e..f6eb834 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -13,6 +13,7 @@ obj-y += sysctl.o
 obj-y += domain_build.o
 obj-y += gic.o gic-v2.o
 obj-$(CONFIG_ARM_64) += gic-v3.o
+obj-$(CONFIG_ARM_64) += gic-v3-its.o
 obj-y += io.o
 obj-y += irq.o
 obj-y += kernel.o
diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index 28b72e4..cde0ec0 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -2,6 +2,10 @@
  * Copyright (C) 2013, 2014 ARM Limited, All Rights Reserved.
  * Author: Marc Zyngier <marc.zyngier@xxxxxxx>
  *
+ * Xen changes:
+ * Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx>
+ * Copyright (C) 2014, 2015 Cavium Inc.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -15,28 +19,40 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/bitmap.h>
-#include <linux/cpu.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/log2.h>
-#include <linux/mm.h>
-#include <linux/msi.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_pci.h>
-#include <linux/of_platform.h>
-#include <linux/percpu.h>
-#include <linux/slab.h>
-
-#include <linux/irqchip/arm-gic-v3.h>
-
-#include <asm/cacheflush.h>
-#include <asm/cputype.h>
-#include <asm/exception.h>
-
-#include "irqchip.h"
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/init.h>
+#include <xen/cpu.h>
+#include <xen/mm.h>
+#include <xen/irq.h>
+#include <xen/sched.h>
+#include <xen/errno.h>
+#include <xen/delay.h>
+#include <xen/device_tree.h>
+#include <xen/libfdt/libfdt.h>
+#include <xen/xmalloc.h>
+#include <xen/list.h>
+#include <xen/sizes.h>
+#include <asm/p2m.h>
+#include <asm/domain.h>
+#include <asm/io.h>
+#include <asm/device.h>
+#include <asm/gic.h>
+#include <asm/gic_v3_defs.h>
+
+#define its_print(lvl, fmt, ...)                                        \
+    printk(lvl "GIC-ITS:" fmt, ## __VA_ARGS__)
+
+#define its_err(fmt, ...) its_print(XENLOG_ERR, fmt, ## __VA_ARGS__)
+
+#define its_dbg(fmt, ...)                                             \
+    its_print(XENLOG_DEBUG, fmt, ## __VA_ARGS__)
+
+#define its_info(fmt, ...)                                            \
+    its_print(XENLOG_INFO, fmt, ## __VA_ARGS__)
+
+#define its_warn(fmt, ...)                                            \
+    its_print(XENLOG_WARNING, fmt, ## __VA_ARGS__)
 
 #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING        (1 << 0)
 
@@ -58,9 +74,8 @@ struct its_collection {
  * devices writing to it.
  */
 struct its_node {
-    raw_spinlock_t        lock;
+    spinlock_t        lock;
     struct                list_head entry;
-    struct msi_chip       msi_chip;
     void __iomem          *base;
     unsigned long         phys_base;
     struct its_cmd_block  *cmd_base;
@@ -92,12 +107,11 @@ struct its_device {
 
 static LIST_HEAD(its_nodes);
 static DEFINE_SPINLOCK(its_lock);
-static struct irq_domain  *lpi_domain;
-static struct device_node *gic_root_node;
-static struct rdists      *gic_rdists;
+static struct dt_device_node *gic_root_node;
+static struct rdist_prop  *gic_rdists;
 
-#define gic_data_rdist()        (raw_cpu_ptr(gic_rdists->rdist))
-#define gic_data_rdist_rd_base()    (gic_data_rdist()->rd_base)
+#define gic_data_rdist()              (per_cpu(rdist, smp_processor_id()))
+#define gic_data_rdist_rd_base()      (per_cpu(rdist, 
smp_processor_id()).rbase)
 
 /*
  * ITS command descriptors - parameters to be encoded in a command
@@ -228,10 +242,10 @@ static struct its_collection *its_build_mapd_cmd(struct 
its_cmd_block *cmd,
                                                  struct its_cmd_desc *desc)
 {
     unsigned long itt_addr;
-    u8 size = max(order_base_2(desc->its_mapd_cmd.dev->nr_ites), 1);
+    u8 size = max(fls(desc->its_mapd_cmd.dev->nr_ites) - 1, 1);
 
-    itt_addr = virt_to_phys(desc->its_mapd_cmd.dev->itt);
-    itt_addr = ALIGN(itt_addr, ITS_ITT_ALIGN);
+    itt_addr = __pa(desc->its_mapd_cmd.dev->itt);
+    itt_addr = ((itt_addr) + (ITS_ITT_ALIGN - 1)) & ~(ITS_ITT_ALIGN - 1);
 
     its_encode_cmd(cmd, GITS_CMD_MAPD);
     its_encode_devid(cmd, desc->its_mapd_cmd.dev->device_id);
@@ -343,17 +357,23 @@ static int its_queue_full(struct its_node *its)
 static struct its_cmd_block *its_allocate_entry(struct its_node *its)
 {
     struct its_cmd_block *cmd;
-    u32 count = 1000000;    /* 1s! */
+    bool_t timeout = 0;
+    s_time_t deadline = NOW() + MILLISECS(1000);
 
     while (its_queue_full(its)) {
-        count--;
-        if (!count) {
-            pr_err_ratelimited("ITS queue not draining\n");
-            return NULL;
+       if ( NOW() > deadline )
+        {
+            timeout = 1;
+            break;
         }
         cpu_relax();
         udelay(1);
     }
+    if ( timeout )
+    {
+        its_err("ITS queue not draining\n");
+        return NULL;
+    }
 
     cmd = its->cmd_write++;
 
@@ -380,7 +400,7 @@ static void its_flush_cmd(struct its_node *its, struct 
its_cmd_block *cmd)
      * the ITS.
      */
     if (its->flags & ITS_FLAGS_CMDQ_NEEDS_FLUSHING)
-        __flush_dcache_area(cmd, sizeof(*cmd));
+        clean_dcache_va_range(cmd, sizeof(*cmd));
     else
         dsb(ishst);
 }
@@ -390,7 +410,8 @@ static void its_wait_for_range_completion(struct its_node 
*its,
                                           struct its_cmd_block *to)
 {
     u64 rd_idx, from_idx, to_idx;
-    u32 count = 1000000;    /* 1s! */
+    bool_t timeout = 0;
+    s_time_t deadline = NOW() + MILLISECS(1000);
 
     from_idx = its_cmd_ptr_to_offset(its, from);
     to_idx = its_cmd_ptr_to_offset(its, to);
@@ -400,14 +421,16 @@ static void its_wait_for_range_completion(struct its_node 
*its,
         if (rd_idx >= to_idx || rd_idx < from_idx)
             break;
 
-        count--;
-        if (!count) {
-            pr_err_ratelimited("ITS queue timeout\n");
-            return;
+        if ( NOW() > deadline )
+        {
+            timeout = 1;
+            break;
         }
         cpu_relax();
         udelay(1);
     }
+    if ( timeout )
+        printk("ITS queue timeout\n");
 }
 
 static void its_send_single_command(struct its_node *its,
@@ -417,12 +440,12 @@ static void its_send_single_command(struct its_node *its,
     struct its_cmd_block *cmd, *sync_cmd, *next_cmd;
     struct its_collection *sync_col;
 
-    raw_spin_lock(&its->lock);
+    spin_lock(&its->lock);
 
     cmd = its_allocate_entry(its);
     if (!cmd) {        /* We're soooooo screewed... */
-        pr_err_ratelimited("ITS can't allocate, dropping command\n");
-        raw_spin_unlock(&its->lock);
+        its_err("ITS can't allocate, dropping command\n");
+        spin_unlock(&its->lock);
         return;
     }
     sync_col = builder(cmd, desc);
@@ -431,7 +454,7 @@ static void its_send_single_command(struct its_node *its,
     if (sync_col) {
         sync_cmd = its_allocate_entry(its);
         if (!sync_cmd) {
-            pr_err_ratelimited("ITS can't SYNC, skipping\n");
+            its_warn("ITS can't SYNC, skipping\n");
             goto post;
         }
         its_encode_cmd(sync_cmd, GITS_CMD_SYNC);
@@ -442,12 +465,12 @@ static void its_send_single_command(struct its_node *its,
 
 post:
     next_cmd = its_post_commands(its);
-    raw_spin_unlock(&its->lock);
+    spin_unlock(&its->lock);
 
     its_wait_for_range_completion(its, cmd, next_cmd);
 }
 
-static void its_send_inv(struct its_device *dev, u32 event_id)
+void its_send_inv(struct its_device *dev, u32 event_id)
 {
     struct its_cmd_desc desc;
 
@@ -489,7 +512,7 @@ static void its_send_mapvi(struct its_device *dev, u32 
irq_id, u32 id)
     its_send_single_command(dev->its, its_build_mapvi_cmd, &desc);
 }
 
-static void its_send_movi(struct its_device *dev,
+void its_send_movi(struct its_device *dev,
               struct its_collection *col, u32 id)
 {
     struct its_cmd_desc desc;
@@ -501,7 +524,7 @@ static void its_send_movi(struct its_device *dev,
     its_send_single_command(dev->its, its_build_movi_cmd, &desc);
 }
 
-static void its_send_discard(struct its_device *dev, u32 id)
+void its_send_discard(struct its_device *dev, u32 id)
 {
     struct its_cmd_desc desc;
 
@@ -521,104 +544,6 @@ static void its_send_invall(struct its_node *its, struct 
its_collection *col)
 }
 
 /*
- * irqchip functions - assumes MSI, mostly.
- */
-
-static void lpi_set_config(struct its_device *its_dev, u32 hwirq,
-               u32 id, int enable)
-{
-    u8 *cfg = page_address(gic_rdists->prop_page) + hwirq - 8192;
-
-    if (enable)
-        *cfg |= LPI_PROP_ENABLED;
-    else
-        *cfg &= ~LPI_PROP_ENABLED;
-
-    /*
-     * Make the above write visible to the redistributors.
-     * And yes, we're flushing exactly: One. Single. Byte.
-     * Humpf...
-     */
-    if (gic_rdists->flags & RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING)
-        __flush_dcache_area(cfg, sizeof(*cfg));
-    else
-        dsb(ishst);
-    its_send_inv(its_dev, id);
-}
-
-static inline u16 its_msi_get_entry_nr(struct msi_desc *desc)
-{
-    return desc->msi_attrib.entry_nr;
-}
-
-static void its_mask_irq(struct irq_data *d)
-{
-    struct its_device *its_dev = irq_data_get_irq_handler_data(d);
-    u32 id;
-
-    /* If MSI, propagate the mask to the RC */
-    if (IS_ENABLED(CONFIG_PCI_MSI) && d->msi_desc) {
-        id = its_msi_get_entry_nr(d->msi_desc);
-        mask_msi_irq(d);
-    } else {
-        id = d->hwirq;
-    }
-
-    lpi_set_config(its_dev, d->hwirq, id, 0);
-}
-
-static void its_unmask_irq(struct irq_data *d)
-{
-    struct its_device *its_dev = irq_data_get_irq_handler_data(d);
-    u32 id;
-
-    /* If MSI, propagate the unmask to the RC */
-    if (IS_ENABLED(CONFIG_PCI_MSI) && d->msi_desc) {
-        id = its_msi_get_entry_nr(d->msi_desc);
-        unmask_msi_irq(d);
-    } else {
-        id = d->hwirq;
-    }
-
-    lpi_set_config(its_dev, d->hwirq, id, 1);
-}
-
-static void its_eoi_irq(struct irq_data *d)
-{
-    gic_write_eoir(d->hwirq);
-}
-
-static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
-                            bool force)
-{
-    unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
-    struct its_device *its_dev = irq_data_get_irq_handler_data(d);
-    struct its_collection *target_col;
-    u32 id;
-
-    if (cpu >= nr_cpu_ids)
-        return -EINVAL;
-
-    target_col = &its_dev->its->collections[cpu];
-    if (IS_ENABLED(CONFIG_PCI_MSI) && d->msi_desc)
-        id = its_msi_get_entry_nr(d->msi_desc);
-    else
-        id = d->hwirq;
-    its_send_movi(its_dev, target_col, id);
-    its_dev->collection = target_col;
-
-    return IRQ_SET_MASK_OK;
-}
-
-static struct irq_chip its_irq_chip = {
-    .name            = "ITS",
-    .irq_mask        = its_mask_irq,
-    .irq_unmask        = its_unmask_irq,
-    .irq_eoi        = its_eoi_irq,
-    .irq_set_affinity    = its_set_affinity,
-};
-
-/*
  * How we allocate LPIs:
  *
  * The GIC has id_bits bits for interrupt identifiers. From there, we
@@ -640,7 +565,7 @@ static int its_lpi_to_chunk(int lpi)
     return (lpi - 8192) >> IRQS_PER_CHUNK_SHIFT;
 }
 
-static int its_chunk_to_lpi(int chunk)
+int its_chunk_to_lpi(int chunk)
 {
     return (chunk << IRQS_PER_CHUNK_SHIFT) + 8192;
 }
@@ -649,31 +574,29 @@ static int its_lpi_init(u32 id_bits)
 {
     lpi_chunks = its_lpi_to_chunk(1UL << id_bits);
 
-    lpi_bitmap = kzalloc(BITS_TO_LONGS(lpi_chunks) * sizeof(long),
-                 GFP_KERNEL);
+    lpi_bitmap =  xzalloc_bytes(lpi_chunks / 8);
     if (!lpi_bitmap) {
         lpi_chunks = 0;
         return -ENOMEM;
     }
 
-    pr_info("ITS: Allocated %d chunks for LPIs\n", (int)lpi_chunks);
+    its_info("ITS: Allocated %d chunks for LPIs\n", (int)lpi_chunks);
     return 0;
 }
 
-static unsigned long *its_lpi_alloc_chunks(int nr_irqs, int *base, int *nr_ids)
+static unsigned long *its_lpi_alloc_chunks(int nr_irq, int *base, int *nr_ids)
 {
     unsigned long *bitmap = NULL;
     int chunk_id;
     int nr_chunks;
     int i;
 
-    nr_chunks = DIV_ROUND_UP(nr_irqs, IRQS_PER_CHUNK);
+    nr_chunks = DIV_ROUND_UP(nr_irq, IRQS_PER_CHUNK);
 
     spin_lock(&lpi_lock);
 
     do {
-        chunk_id = bitmap_find_next_zero_area(lpi_bitmap, lpi_chunks,
-                                              0, nr_chunks, 0);
+        chunk_id = find_next_zero_bit(lpi_bitmap, lpi_chunks, 0);
         if (chunk_id < lpi_chunks)
             break;
 
@@ -683,8 +606,7 @@ static unsigned long *its_lpi_alloc_chunks(int nr_irqs, int 
*base, int *nr_ids)
     if (!nr_chunks)
         goto out;
 
-    bitmap = kzalloc(BITS_TO_LONGS(nr_chunks * IRQS_PER_CHUNK) * sizeof (long),
-             GFP_ATOMIC);
+    bitmap = xzalloc_bytes(BITS_TO_LONGS(nr_chunks * IRQS_PER_CHUNK) * sizeof 
(long));
     if (!bitmap)
         goto out;
 
@@ -700,7 +622,7 @@ out:
     return bitmap;
 }
 
-static void its_lpi_free(unsigned long *bitmap, int base, int nr_ids)
+void its_lpi_free(unsigned long *bitmap, int base, int nr_ids)
 {
     int lpi;
 
@@ -712,13 +634,13 @@ static void its_lpi_free(unsigned long *bitmap, int base, 
int nr_ids)
         if (test_bit(chunk, lpi_bitmap)) {
             clear_bit(chunk, lpi_bitmap);
         } else {
-            pr_err("Bad LPI chunk %d\n", chunk);
+            its_err("Bad LPI chunk %d\n", chunk);
         }
     }
 
     spin_unlock(&lpi_lock);
 
-    kfree(bitmap);
+    xfree(bitmap);
 }
 
 /*
@@ -732,31 +654,28 @@ static void its_lpi_free(unsigned long *bitmap, int base, 
int nr_ids)
 /*
  * This is how many bits of ID we need, including the useless ones.
  */
-#define LPI_NRBITS        ilog2(LPI_PROPBASE_SZ + SZ_8K)
+#define LPI_NRBITS        (fls(LPI_PROPBASE_SZ + SZ_8K) - 1)
 
-#define LPI_PROP_DEFAULT_PRIO    0xa0
+#define LPI_PROP_DEFAULT_PRIO    0xa2
 
 static int __init its_alloc_lpi_tables(void)
 {
-    phys_addr_t paddr;
+    gic_rdists->prop_page = 
alloc_xenheap_pages(get_order_from_bytes(LPI_PROPBASE_SZ), 0);
 
-    gic_rdists->prop_page = alloc_pages(GFP_NOWAIT,
-                       get_order(LPI_PROPBASE_SZ));
     if (!gic_rdists->prop_page) {
-        pr_err("Failed to allocate PROPBASE\n");
+        its_err("Failed to allocate PROPBASE\n");
         return -ENOMEM;
     }
 
-    paddr = page_to_phys(gic_rdists->prop_page);
-    pr_info("GIC: using LPI property table @%pa\n", &paddr);
+    its_info("GIC: using LPI property table @%pa\n", gic_rdists->prop_page);
 
     /* Priority 0xa0, Group-1, disabled */
-    memset(page_address(gic_rdists->prop_page),
+    memset(gic_rdists->prop_page,
            LPI_PROP_DEFAULT_PRIO | LPI_PROP_GROUP1,
            LPI_PROPBASE_SZ);
 
     /* Make sure the GIC will observe the written configuration */
-    __flush_dcache_area(page_address(gic_rdists->prop_page), LPI_PROPBASE_SZ);
+    clean_dcache_va_range(gic_rdists->prop_page, LPI_PROPBASE_SZ);
 
     return 0;
 }
@@ -777,7 +696,7 @@ static void its_free_tables(struct its_node *its)
 
     for (i = 0; i < GITS_BASER_NR_REGS; i++) {
         if (its->tables[i]) {
-            free_page((unsigned long)its->tables[i]);
+            xfree(its->tables[i]);
             its->tables[i] = NULL;
         }
     }
@@ -806,17 +725,18 @@ static int its_alloc_tables(struct its_node *its)
         if (type == GITS_BASER_TYPE_NONE)
             continue;
 
-        base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 
get_order(max_ittsize));
+        base = alloc_xenheap_pages(get_order_from_bytes(max_ittsize), 0);
         if (!base) {
             err = -ENOMEM;
             goto out_free;
         }
-
+        memset(base, 0, max_ittsize);
+        clear_page(base);
 
         its->tables[i] = base;
 
 retry_baser:
-        val = (virt_to_phys(base)                                |
+        val = (__pa(base)                                        |
                (type << GITS_BASER_TYPE_SHIFT)                   |
                ((entry_size - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) |
                GITS_BASER_WaWb                                   |
@@ -874,17 +794,16 @@ retry_baser:
         tmp = tmp << 5;
 
         if (val != tmp) {
-            pr_err("ITS: %s: GITS_BASER%d doesn't stick: %lx %lx\n",
-                   its->msi_chip.of_node->full_name, i,
-                   (unsigned long) val, (unsigned long) tmp);
+            its_err("ITS: GITS_BASER%d doesn't stick: %lx %lx\n",
+                   i, (unsigned long) val, (unsigned long) tmp);
             err = -ENXIO;
             goto out_free;
         }
 
-        pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n",
+        its_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n",
             (int)(PAGE_SIZE / entry_size),
             its_base_type_string[type],
-            (unsigned long)virt_to_phys(base),
+            (unsigned long)__pa(base),
             psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
     }
 
@@ -898,8 +817,7 @@ out_free:
 
 static int its_alloc_collections(struct its_node *its)
 {
-    its->collections = kzalloc(nr_cpu_ids * sizeof(*its->collections),
-                   GFP_KERNEL);
+    its->collections = xzalloc_array(struct its_collection, nr_cpu_ids);
     if (!its->collections)
         return -ENOMEM;
 
@@ -909,32 +827,30 @@ static int its_alloc_collections(struct its_node *its)
 static void its_cpu_init_lpis(void)
 {
     void __iomem *rbase = gic_data_rdist_rd_base();
-    struct page *pend_page;
+    void *pend_page;
     u64 val, tmp;
 
     /* If we didn't allocate the pending table yet, do it now */
-    pend_page = gic_data_rdist()->pend_page;
+    pend_page = gic_data_rdist().pend_page;
     if (!pend_page) {
-        phys_addr_t paddr;
         /*
          * The pending pages have to be at least 64kB aligned,
          * hence the 'max(LPI_PENDBASE_SZ, SZ_64K)' below.
          */
-        pend_page = alloc_pages(GFP_NOWAIT | __GFP_ZERO,
-                                get_order(max(LPI_PENDBASE_SZ, SZ_64K)));
+        pend_page = 
alloc_xenheap_pages(get_order_from_bytes(max(LPI_PENDBASE_SZ, SZ_64K)), 0);
         if (!pend_page) {
-            pr_err("Failed to allocate PENDBASE for CPU%d\n",
+            its_err("Failed to allocate PENDBASE for CPU%d\n",
                    smp_processor_id());
             return;
         }
 
+        memset(pend_page, 0, max(LPI_PENDBASE_SZ, SZ_64K));
         /* Make sure the GIC will observe the zero-ed page */
-        __flush_dcache_area(page_address(pend_page), LPI_PENDBASE_SZ);
+        clean_dcache_va_range(pend_page, LPI_PENDBASE_SZ);
 
-        paddr = page_to_phys(pend_page);
-        pr_info("CPU%d: using LPI pending table @%pa\n",
-            smp_processor_id(), &paddr);
-        gic_data_rdist()->pend_page = pend_page;
+        its_info("CPU%d: using LPI pending table @%pa\n",
+                 smp_processor_id(), pend_page);
+        gic_data_rdist().pend_page = pend_page;
     }
 
     /* Disable LPIs */
@@ -948,7 +864,7 @@ static void its_cpu_init_lpis(void)
     dsb(sy);
 
     /* set PROPBASE */
-    val = (page_to_phys(gic_rdists->prop_page) |
+    val = (__pa(gic_rdists->prop_page)         |
            GICR_PROPBASER_InnerShareable       |
            GICR_PROPBASER_WaWb                 |
            ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK));
@@ -957,12 +873,12 @@ static void its_cpu_init_lpis(void)
     tmp = readq_relaxed(rbase + GICR_PROPBASER);
 
     if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
-        pr_info_once("GIC: using cache flushing for LPI property table\n");
+        its_info("GIC: using cache flushing for LPI property table\n");
         gic_rdists->flags |= RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING;
     }
 
     /* set PENDBASE */
-    val = (page_to_phys(pend_page)       |
+    val = (__pa(pend_page)               |
            GICR_PROPBASER_InnerShareable |
            GICR_PROPBASER_WaWb);
 
@@ -997,7 +913,7 @@ static void its_cpu_init_collection(void)
              * This ITS wants the physical address of the
              * redistributor.
              */
-            target = gic_data_rdist()->phys_base;
+            target = gic_data_rdist().phys_base;
         } else {
             /*
              * This ITS wants a linear CPU number.
@@ -1017,11 +933,11 @@ static void its_cpu_init_collection(void)
     spin_unlock(&its_lock);
 }
 
-static struct its_device *its_find_device(struct its_node *its, u32 dev_id)
+struct its_device *its_find_device(struct its_node *its, u32 dev_id)
 {
     struct its_device *its_dev = NULL, *tmp;
 
-    raw_spin_lock(&its->lock);
+    spin_lock(&its->lock);
 
     list_for_each_entry(tmp, &its->its_device_list, entry) {
         if (tmp->device_id == dev_id) {
@@ -1030,13 +946,14 @@ static struct its_device *its_find_device(struct 
its_node *its, u32 dev_id)
         }
     }
 
-    raw_spin_unlock(&its->lock);
+    spin_unlock(&its->lock);
 
     return its_dev;
 }
 
-static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
-                                            int nvecs)
+/* TODO: Removed static for compilation */
+struct its_device *its_create_device(struct its_node *its, u32 dev_id,
+                                     int nvecs)
 {
     struct its_device *dev;
     unsigned long *lpi_map;
@@ -1046,16 +963,16 @@ static struct its_device *its_create_device(struct 
its_node *its, u32 dev_id,
     int cpu;
     int sz;
 
-    dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+    dev = xzalloc(struct its_device);
     sz = nvecs * its->ite_size;
     sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
-    itt = kmalloc(sz, GFP_KERNEL);
+    itt = xzalloc_bytes(sz);
     lpi_map = its_lpi_alloc_chunks(nvecs, &lpi_base, &nr_lpis);
 
     if (!dev || !itt || !lpi_map) {
-        kfree(dev);
-        kfree(itt);
-        kfree(lpi_map);
+        xfree(dev);
+        xfree(itt);
+        xfree(lpi_map);
         return NULL;
     }
 
@@ -1068,12 +985,12 @@ static struct its_device *its_create_device(struct 
its_node *its, u32 dev_id,
     dev->device_id = dev_id;
     INIT_LIST_HEAD(&dev->entry);
 
-    raw_spin_lock(&its->lock);
+    spin_lock(&its->lock);
     list_add(&dev->entry, &its->its_device_list);
-    raw_spin_unlock(&its->lock);
+    spin_unlock(&its->lock);
 
     /* Bind the device to the first possible CPU */
-    cpu = cpumask_first(cpu_online_mask);
+    cpu = cpumask_first(&cpu_online_map);
     dev->collection = &its->collections[cpu];
 
     /* Map device to its ITT */
@@ -1082,17 +999,18 @@ static struct its_device *its_create_device(struct 
its_node *its, u32 dev_id,
     return dev;
 }
 
-static void its_free_device(struct its_device *its_dev)
+void its_free_device(struct its_device *its_dev)
 {
-    raw_spin_lock(&its_dev->its->lock);
+    spin_lock(&its_dev->its->lock);
     list_del(&its_dev->entry);
-    raw_spin_unlock(&its_dev->its->lock);
-    kfree(its_dev->itt);
-    kfree(its_dev);
+    spin_unlock(&its_dev->its->lock);
+    xfree(its_dev->itt);
+    xfree(its_dev);
 }
 
-static int its_alloc_device_irq(struct its_device *dev, u32 id,
-                                int *hwirq, unsigned int *irq)
+/* TODO: Removed static for compilation */
+int its_alloc_device_irq(struct its_device *dev, u32 id,
+                         int *hwirq, unsigned int *irq)
 {
     int idx;
 
@@ -1101,9 +1019,6 @@ static int its_alloc_device_irq(struct its_device *dev, 
u32 id,
         return -ENOSPC;
 
     *hwirq = dev->lpi_base + idx;
-    *irq = irq_create_mapping(lpi_domain, *hwirq);
-    if (!*irq)
-        return -ENOSPC;    /* Don't kill the device, though */
 
     set_bit(idx, dev->lpi_map);
 
@@ -1113,134 +1028,52 @@ static int its_alloc_device_irq(struct its_device 
*dev, u32 id,
     return 0;
 }
 
-
-
-static int its_msi_get_vec_count(struct pci_dev *pdev, struct msi_desc *desc)
-{
-#ifdef CONFIG_PCI_MSI
-    if (desc->msi_attrib.is_msix)
-        return pci_msix_vec_count(pdev);
-    else
-        return pci_msi_vec_count(pdev);
-#else
-    return -EINVAL;
-#endif
-}
-
-int pci_requester_id(struct pci_dev *dev);
-static int its_msi_setup_irq(struct msi_chip *chip,
-                             struct pci_dev *pdev,
-                             struct msi_desc *desc)
-{
-    struct its_node *its = container_of(chip, struct its_node, msi_chip);
-    struct its_device *its_dev;
-    struct msi_msg msg;
-    unsigned int irq;
-    u64 addr;
-    int hwirq;
-    int err;
-    u32 dev_id = pci_requester_id(pdev);
-    u32 vec_nr;
-
-    its_dev = its_find_device(its, dev_id);
-    if (!its_dev) {
-        int nvec = its_msi_get_vec_count(pdev, desc);
-        if (WARN_ON(nvec <= 0))
-            return nvec;
-        its_dev = its_create_device(its, dev_id, nvec);
-    }
-    if (!its_dev)
-        return -ENOMEM;
-    vec_nr = its_msi_get_entry_nr(desc);
-    err = its_alloc_device_irq(its_dev, vec_nr, &hwirq, &irq);
-    if (err)
-        return err;
-
-    irq_set_msi_desc(irq, desc);
-    irq_set_handler_data(irq, its_dev);
-
-    addr = its->phys_base + GITS_TRANSLATER;
-
-    msg.address_lo        = (u32)addr;
-    msg.address_hi        = (u32)(addr >> 32);
-    msg.data        = vec_nr;
-
-    write_msi_msg(irq, &msg);
-    return 0;
-}
-
-static void its_msi_teardown_irq(struct msi_chip *chip, unsigned int irq)
-{
-    struct irq_data *d = irq_get_irq_data(irq);
-    struct its_device *its_dev = irq_data_get_irq_handler_data(d);
-
-    BUG_ON(d->hwirq < its_dev->lpi_base ||        /* OMG! */
-           d->hwirq > (its_dev->lpi_base + its_dev->nr_lpis));
-
-    /* Stop the delivery of interrupts */
-    its_send_discard(its_dev, its_msi_get_entry_nr(d->msi_desc));
-
-    /* Mark interrupt index as unused, and clear the mapping */
-    clear_bit(d->hwirq - its_dev->lpi_base, its_dev->lpi_map);
-    irq_dispose_mapping(irq);
-
-    /* If all interrupts have been freed, start mopping the floor */
-    if (bitmap_empty(its_dev->lpi_map, its_dev->nr_lpis)) {
-        its_lpi_free(its_dev->lpi_map,
-                     its_dev->lpi_base,
-                     its_dev->nr_lpis);
-
-        /* Unmap device/itt */
-        its_send_mapd(its_dev, 0);
-        its_free_device(its_dev);
-    }
-}
-
-static int its_probe(struct device_node *node)
+static int its_probe(struct dt_device_node *node)
 {
-    struct resource res;
+    paddr_t its_addr, its_size;
     struct its_node *its;
     void __iomem *its_base;
     u32 val;
     u64 baser, tmp;
     int err;
 
-    err = of_address_to_resource(node, 0, &res);
-    if (err) {
-        pr_warn("%s: no regs?\n", node->full_name);
+    err = dt_device_get_address(node, 0, &its_addr, &its_size);
+    if ( err || !its_addr )
+    {
+        its_warn("%s: cannot find GIC-ITS\n", node->full_name);
         return -ENXIO;
     }
 
-    its_base = ioremap(res.start, resource_size(&res));
-    if (!its_base) {
-        pr_warn("%s: unable to map registers\n", node->full_name);
+    its_base = ioremap_nocache(its_addr, its_size);
+    if ( !its_base)
+    {
+        its_warn("%s: unable to map registers\n", node->full_name);
         return -ENOMEM;
     }
 
-    val = readl_relaxed(its_base + GITS_PIDR2) & GIC_PIDR2_ARCH_MASK;
+    val = readl_relaxed(its_base + GITS_PIDR2) & GICR_PIDR2_ARCH_REV_MASK;
     if (val != 0x30 && val != 0x40) {
-        pr_warn("%s: no ITS detected, giving up\n", node->full_name);
+        its_warn("%s: no ITS detected, giving up\n", node->full_name);
         err = -ENODEV;
         goto out_unmap;
     }
 
-    pr_info("ITS: %s\n", node->full_name);
+    its_info("ITS: %s\n", node->full_name);
 
-    its = kzalloc(sizeof(*its), GFP_KERNEL);
+    its = xzalloc(struct its_node);
     if (!its) {
         err = -ENOMEM;
         goto out_unmap;
     }
 
-    raw_spin_lock_init(&its->lock);
+    spin_lock_init(&its->lock);
     INIT_LIST_HEAD(&its->entry);
     INIT_LIST_HEAD(&its->its_device_list);
     its->base = its_base;
-    its->phys_base = res.start;
-    its->msi_chip.of_node = node;
+    its->phys_base = its_addr;
     its->ite_size = ((readl_relaxed(its_base + GITS_TYPER) >> 4) & 0xf) + 1;
 
-    its->cmd_base = kzalloc(ITS_CMD_QUEUE_SZ, GFP_KERNEL);
+    its->cmd_base = xzalloc_bytes(ITS_CMD_QUEUE_SZ);
     if (!its->cmd_base) {
         err = -ENOMEM;
         goto out_free_its;
@@ -1255,19 +1088,19 @@ static int its_probe(struct device_node *node)
     if (err)
         goto out_free_tables;
 
-    baser = (virt_to_phys(its->cmd_base)    |
-             GITS_CBASER_WaWb               |
-             GITS_CBASER_InnerShareable     |
-             (ITS_CMD_QUEUE_SZ / SZ_4K - 1) |
-             GITS_CBASER_VALID);
+    baser = (__pa(its->cmd_base)            |
+            GITS_CBASER_WaWb                |
+            GITS_CBASER_InnerShareable      |
+            (ITS_CMD_QUEUE_SZ / SZ_4K - 1)  |
+            GITS_CBASER_VALID);
 
     writeq_relaxed(baser, its->base + GITS_CBASER);
     tmp = readq_relaxed(its->base + GITS_CBASER);
-/*    writeq_relaxed(0, its->base + GITS_CWRITER); */
+    writeq_relaxed(0, its->base + GITS_CWRITER);
     writel_relaxed(1, its->base + GITS_CTLR);
 
     if ((tmp ^ baser) & GITS_BASER_SHAREABILITY_MASK) {
-        pr_info("ITS: using cache flushing for cmd queue\n");
+        its_info("ITS: using cache flushing for cmd queue\n");
         its->flags |= ITS_FLAGS_CMDQ_NEEDS_FLUSHING;
     }
 
@@ -1275,25 +1108,17 @@ static int its_probe(struct device_node *node)
     list_add(&its->entry, &its_nodes);
     spin_unlock(&its_lock);
 
-    if (IS_ENABLED(CONFIG_PCI_MSI) && /* Remove this once we have PCI... */
-        of_property_read_bool(its->msi_chip.of_node, "msi-controller")) {
-        its->msi_chip.setup_irq        = its_msi_setup_irq;
-        its->msi_chip.teardown_irq    = its_msi_teardown_irq;
-
-        err = of_pci_msi_chip_add(&its->msi_chip);
-    }
-
     return err;
 
 out_free_tables:
     its_free_tables(its);
 out_free_cmd:
-    kfree(its->cmd_base);
+    xfree(its->cmd_base);
 out_free_its:
-    kfree(its);
+    xfree(its);
 out_unmap:
-    iounmap(its_base);
-    pr_err("ITS: failed probing %s (%d)\n", node->full_name, err);
+    //TODO: no call for iounmap in xen?
+    its_err("ITS: failed probing %s (%d)\n", node->full_name, err);
     return err;
 }
 
@@ -1305,7 +1130,7 @@ static bool gic_rdists_supports_plpis(void)
 int its_cpu_init(void)
 {
     if (!gic_rdists_supports_plpis()) {
-        pr_info("CPU%d: LPIs not supported\n", smp_processor_id());
+        its_info("CPU%d: LPIs not supported\n", smp_processor_id());
         return -ENXIO;
     }
 
@@ -1317,32 +1142,45 @@ int its_cpu_init(void)
     return 0;
 }
 
-static struct of_device_id its_device_id[] = {
-    {    .compatible    = "arm,gic-v3-its",    },
-    {},
-};
-
-struct irq_chip *its_init(struct device_node *node, struct rdists *rdists,
-                          struct irq_domain *domain)
+int its_init(struct dt_device_node *node, struct rdist_prop *rdists)
 {
-    struct device_node *np;
+    static const struct dt_device_match its_device_ids[] __initconst =
+    {
+        DT_MATCH_COMPATIBLE("arm,gic-v3-its"),
+        { /* sentinel */ },
+    };
+    struct dt_device_node *np = NULL;
 
-    for (np = of_find_matching_node(node, its_device_id); np;
-         np = of_find_matching_node(np, its_device_id)) {
-        its_probe(np);
+    while ( (np = dt_find_matching_node(np, its_device_ids)) )
+    {
+        if ( !dt_find_property(np, "msi-controller", NULL) )
+            continue;
+
+        if ( dt_get_parent(np) )
+            break;
     }
+    if ( np )
+        its_probe(np);
 
     if (list_empty(&its_nodes)) {
-        pr_info("ITS: No ITS available, not enabling LPIs\n");
-        return NULL;
+        its_info("ITS: No ITS available, not enabling LPIs\n");
+        return -ENXIO;
     }
 
     gic_rdists = rdists;
     gic_root_node = node;
-    lpi_domain = domain;
 
     its_alloc_lpi_tables();
     its_lpi_init(rdists->id_bits);
 
-    return &its_irq_chip;
+    return 0;
 }
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 47452ca..5c35ac5 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -63,6 +63,7 @@ static struct gic_info gicv3_info;
 
 /* per-cpu re-distributor base */
 static DEFINE_PER_CPU(void __iomem*, rbase);
+DEFINE_PER_CPU(struct rdist, rdist);
 
 #define GICD                   (gicv3.map_dbase)
 #define GICD_RDIST_BASE        (this_cpu(rbase))
diff --git a/xen/include/asm-arm/gic_v3_defs.h 
b/xen/include/asm-arm/gic_v3_defs.h
index 13adb53..83d75cf 100644
--- a/xen/include/asm-arm/gic_v3_defs.h
+++ b/xen/include/asm-arm/gic_v3_defs.h
@@ -110,6 +110,23 @@
 #define GICR_ICFGR1                  (0x0C04)
 #define GICR_NSACR                   (0x0E00)
 
+#define GICR_CTLR_ENABLE_LPIS        (1UL << 0)
+#define GICR_TYPER_CPU_NUMBER(r)       (((r) >> 8) & 0xffff)
+
+#define GICR_PROPBASER_NonShareable    (0U << 10)
+#define GICR_PROPBASER_InnerShareable  (1U << 10)
+#define GICR_PROPBASER_OuterShareable  (2U << 10)
+#define GICR_PROPBASER_SHAREABILITY_MASK (3UL << 10)
+#define GICR_PROPBASER_nCnB            (0U << 7)
+#define GICR_PROPBASER_nC              (1U << 7)
+#define GICR_PROPBASER_RaWt            (2U << 7)
+#define GICR_PROPBASER_RaWb            (3U << 7)
+#define GICR_PROPBASER_WaWt            (4U << 7)
+#define GICR_PROPBASER_WaWb            (5U << 7)
+#define GICR_PROPBASER_RaWaWt          (6U << 7)
+#define GICR_PROPBASER_RaWaWb          (7U << 7)
+#define GICR_PROPBASER_IDBITS_MASK     (0x1f)
+
 #define GICR_TYPER_PLPIS             (1U << 0)
 #define GICR_TYPER_VLPIS             (1U << 1)
 #define GICR_TYPER_LAST              (1U << 4)
@@ -149,6 +166,116 @@
 #define ICH_SGI_IRQ_SHIFT            24
 #define ICH_SGI_IRQ_MASK             0xf
 #define ICH_SGI_TARGETLIST_MASK      0xffff
+
+#define GICR_TYPER_PLPIS                (1U << 0)
+#define GICR_TYPER_VLPIS                (1U << 1)
+#define GICR_TYPER_LAST                 (1U << 4)
+ 
+#define LPI_PROP_GROUP1                 (1 << 1)
+#define LPI_PROP_ENABLED                (1 << 0)
+
+/*
+ * ITS registers, offsets from ITS_base
+ */
+#define GITS_CTLR                       0x0000
+#define GITS_IIDR                       0x0004
+#define GITS_TYPER                      0x0008
+#define GITS_CBASER                     0x0080
+#define GITS_CWRITER                    0x0088
+#define GITS_CREADR                     0x0090
+#define GITS_BASER                      0x0100
+#define GITS_BASERN                     0x013c
+#define GITS_PIDR0                      GICR_PIDR0
+#define GITS_PIDR1                      GICR_PIDR1
+#define GITS_PIDR2                      GICR_PIDR2
+#define GITS_PIDR3                      GICR_PIDR3
+#define GITS_PIDR4                      GICR_PIDR4
+#define GITS_PIDR5                      GICR_PIDR5
+#define GITS_PIDR7                      GICR_PIDR7
+
+#define GITS_TRANSLATER                 0x10040
+
+#define GITS_TYPER_PTA                  (1UL << 19)
+
+#define GITS_CBASER_VALID               (1UL << 63)
+#define GITS_CBASER_nCnB                (0UL << 59)
+#define GITS_CBASER_nC                  (1UL << 59)
+#define GITS_CBASER_RaWt                (2UL << 59)
+#define GITS_CBASER_RaWb                (3UL << 59)
+#define GITS_CBASER_WaWt                (4UL << 59)
+#define GITS_CBASER_WaWb                (5UL << 59)
+#define GITS_CBASER_RaWaWt              (6UL << 59)
+#define GITS_CBASER_RaWaWb              (7UL << 59)
+#define GITS_CBASER_NonShareable        (0UL << 10)
+#define GITS_CBASER_InnerShareable      (1UL << 10)
+#define GITS_CBASER_OuterShareable      (2UL << 10)
+#define GITS_CBASER_SHAREABILITY_MASK   (3UL << 10)
+
+#define GITS_BASER_NR_REGS              8
+
+#define GITS_BASER_VALID                (1UL << 63)
+#define GITS_BASER_nCnB                 (0UL << 59)
+#define GITS_BASER_nC                   (1UL << 59)
+#define GITS_BASER_RaWt                 (2UL << 59)
+#define GITS_BASER_RaWb                 (3UL << 59)
+#define GITS_BASER_WaWt                 (4UL << 59)
+#define GITS_BASER_WaWb                 (5UL << 59)
+#define GITS_BASER_RaWaWt               (6UL << 59)
+#define GITS_BASER_RaWaWb               (7UL << 59)
+#define GITS_BASER_TYPE_SHIFT          (56)
+#define GITS_BASER_TYPE(r)             (((r) >> GITS_BASER_TYPE_SHIFT) & 7)
+#define GITS_BASER_ENTRY_SIZE_SHIFT    (48)
+#define GITS_BASER_ENTRY_SIZE(r)       ((((r) >> GITS_BASER_ENTRY_SIZE_SHIFT) 
& 0xff) + 1)
+#define GITS_BASER_NonShareable                (0UL << 10)
+#define GITS_BASER_InnerShareable      (1UL << 10)
+#define GITS_BASER_OuterShareable      (2UL << 10)
+#define GITS_BASER_SHAREABILITY_SHIFT  (10)
+#define GITS_BASER_SHAREABILITY_MASK   (3UL << GITS_BASER_SHAREABILITY_SHIFT)
+#define GITS_BASER_PAGE_SIZE_SHIFT     (8)
+#define GITS_BASER_PAGE_SIZE_4K                (0UL << 
GITS_BASER_PAGE_SIZE_SHIFT)
+#define GITS_BASER_PAGE_SIZE_16K       (1UL << GITS_BASER_PAGE_SIZE_SHIFT)
+#define GITS_BASER_PAGE_SIZE_64K       (2UL << GITS_BASER_PAGE_SIZE_SHIFT)
+#define GITS_BASER_PAGE_SIZE_MASK      (3UL << GITS_BASER_PAGE_SIZE_SHIFT)
+
+#define GITS_BASER_TYPE_NONE           0
+#define GITS_BASER_TYPE_DEVICE         1
+#define GITS_BASER_TYPE_VCPU           2
+#define GITS_BASER_TYPE_CPU            3
+#define GITS_BASER_TYPE_COLLECTION     4
+#define GITS_BASER_TYPE_RESERVED5      5
+#define GITS_BASER_TYPE_RESERVED6      6
+#define GITS_BASER_TYPE_RESERVED7      7
+
+/*
+ * ITS commands
+ */
+#define GITS_CMD_MAPD                   0x08
+#define GITS_CMD_MAPC                   0x09
+#define GITS_CMD_MAPVI                  0x0a
+#define GITS_CMD_MAPI                   0x0b
+#define GITS_CMD_MOVI                   0x01
+#define GITS_CMD_DISCARD                0x0f
+#define GITS_CMD_INV                    0x0c
+#define GITS_CMD_MOVALL                 0x0e
+#define GITS_CMD_INVALL                 0x0d
+#define GITS_CMD_INT                    0x03
+#define GITS_CMD_CLEAR                  0x04
+#define GITS_CMD_SYNC                   0x05
+
+struct rdist {
+    void __iomem *rbase;
+    void * pend_page;
+    paddr_t phys_base;
+};
+
+struct rdist_prop {
+    void * prop_page;
+    int    id_bits;
+    uint64_t flags;
+};
+
+DECLARE_PER_CPU(struct rdist, rdist);
+
 #endif /* __ASM_ARM_GIC_V3_DEFS_H__ */
 
 /*
-- 
1.7.9.5


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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.