[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH v2 06/22] 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> --- v2: - put unused code under #if0/endif - changes to redistributor is moved to separate patch - Fixed comments from RFC version --- xen/arch/arm/Makefile | 1 + xen/arch/arm/gic-v3-its.c | 337 +++++++++++++++++++++---------------- xen/include/asm-arm/gic_v3_defs.h | 116 ++++++++++++- 3 files changed, 304 insertions(+), 150 deletions(-) diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile index 41aba2e..66ea264 100644 --- a/xen/arch/arm/Makefile +++ b/xen/arch/arm/Makefile @@ -31,6 +31,7 @@ obj-y += shutdown.o obj-y += traps.o obj-y += vgic.o vgic-v2.o obj-$(CONFIG_ARM_64) += vgic-v3.o +obj-$(CONFIG_ARM_64) += gic-v3-its.o obj-y += vtimer.o obj-y += vuart.o obj-y += hvm.o diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c index 596b0a9..ce7ced6 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,41 @@ * 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/bitops.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 <xen/vmap.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, ...) \ #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1 << 0) @@ -58,10 +75,8 @@ struct its_collection { * devices writing to it. */ struct its_node { - raw_spinlock_t lock; + spinlock_t lock; struct list_head entry; - struct msi_controller msi_chip; - struct irq_domain *domain; void __iomem *base; unsigned long phys_base; struct its_cmd_block *cmd_base; @@ -85,7 +100,7 @@ struct its_device { struct its_collection *collection; void *itt; unsigned long *lpi_map; - irq_hw_number_t lpi_base; + u32 lpi_base; int nr_lpis; u32 nr_ites; u32 device_id; @@ -93,11 +108,11 @@ struct its_device { static LIST_HEAD(its_nodes); static DEFINE_SPINLOCK(its_lock); -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 +243,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 = ilog2(desc->its_mapd_cmd.dev->nr_ites); + 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 = ROUNDUP(itt_addr, ITS_ITT_ALIGN); its_encode_cmd(cmd, GITS_CMD_MAPD); its_encode_devid(cmd, desc->its_mapd_cmd.dev->device_id); @@ -348,7 +363,7 @@ static struct its_cmd_block *its_allocate_entry(struct its_node *its) while (its_queue_full(its)) { count--; if (!count) { - pr_err_ratelimited("ITS queue not draining\n"); + its_err("ITS queue not draining\n"); return NULL; } cpu_relax(); @@ -380,7 +395,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_and_invalidate_dcache_va_range(cmd, sizeof(*cmd)); else dsb(ishst); } @@ -402,7 +417,7 @@ static void its_wait_for_range_completion(struct its_node *its, count--; if (!count) { - pr_err_ratelimited("ITS queue timeout\n"); + its_err("ITS queue timeout\n"); return; } cpu_relax(); @@ -418,12 +433,12 @@ static void its_send_single_command(struct its_node *its, struct its_collection *sync_col; unsigned long flags; - raw_spin_lock_irqsave(&its->lock, flags); + spin_lock_irqsave(&its->lock, flags); cmd = its_allocate_entry(its); if (!cmd) { /* We're soooooo screewed... */ - pr_err_ratelimited("ITS can't allocate, dropping command\n"); - raw_spin_unlock_irqrestore(&its->lock, flags); + its_err("ITS can't allocate, dropping command\n"); + spin_unlock_irqrestore(&its->lock, flags); return; } sync_col = builder(cmd, desc); @@ -432,7 +447,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_err("ITS can't SYNC, skipping\n"); goto post; } its_encode_cmd(sync_cmd, GITS_CMD_SYNC); @@ -443,12 +458,13 @@ static void its_send_single_command(struct its_node *its, post: next_cmd = its_post_commands(its); - raw_spin_unlock_irqrestore(&its->lock, flags); + spin_unlock_irqrestore(&its->lock, flags); its_wait_for_range_completion(its, cmd, next_cmd); } -static void its_send_inv(struct its_device *dev, u32 event_id) +/* TODO: Remove static for the sake of compilation */ +void its_send_inv(struct its_device *dev, u32 event_id) { struct its_cmd_desc desc; @@ -479,7 +495,8 @@ static void its_send_mapc(struct its_node *its, struct its_collection *col, its_send_single_command(its, its_build_mapc_cmd, &desc); } -static void its_send_mapvi(struct its_device *dev, u32 irq_id, u32 id) +/* TODO: Remove static for the sake of compilation */ +void its_send_mapvi(struct its_device *dev, u32 irq_id, u32 id) { struct its_cmd_desc desc; @@ -490,7 +507,8 @@ 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, +/* TODO: Remove static for the sake of compilation */ +void its_send_movi(struct its_device *dev, struct its_collection *col, u32 id) { struct its_cmd_desc desc; @@ -502,7 +520,8 @@ 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) +/* TODO: Remove static for the sake of compilation */ +void its_send_discard(struct its_device *dev, u32 id) { struct its_cmd_desc desc; @@ -522,6 +541,11 @@ static void its_send_invall(struct its_node *its, struct its_collection *col) } /* + * The below irqchip functions are no more required. + * TODO: Will be implemented as separate patch + */ +#if 0 +/* * irqchip functions - assumes MSI, mostly. */ @@ -630,6 +654,7 @@ static struct irq_chip its_msi_irq_chip = { .irq_eoi = irq_chip_eoi_parent, .irq_write_msi_msg = pci_msi_domain_write_msg, }; +#endif /* * How we allocate LPIs: @@ -662,25 +687,24 @@ 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(BITS_TO_LONGS(lpi_chunks) * sizeof(long)); 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 nirqs, 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(nirqs, IRQS_PER_CHUNK); spin_lock(&lpi_lock); @@ -696,8 +720,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; @@ -713,7 +736,8 @@ out: return bitmap; } -static void its_lpi_free(unsigned long *bitmap, int base, int nr_ids) +/* TODO: Remove static for the sake of compilation */ +void its_lpi_free(unsigned long *bitmap, int base, int nr_ids) { int lpi; @@ -725,13 +749,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); } /* @@ -745,31 +769,31 @@ 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 static int __init its_alloc_lpi_tables(void) { - phys_addr_t paddr; + paddr_t paddr; - gic_rdists->prop_page = alloc_pages(GFP_NOWAIT, - get_order(LPI_PROPBASE_SZ)); + gic_rdists->prop_page = alloc_xenheap_pages(get_order_from_bytes(LPI_PROPBASE_SZ), 0); 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); + paddr = __pa(gic_rdists->prop_page); + its_info("GIC: using LPI property table @%pa\n", &paddr); /* 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_and_invalidate_dcache_va_range(gic_rdists->prop_page, + LPI_PROPBASE_SZ); return 0; } @@ -790,7 +814,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; } } @@ -807,7 +831,7 @@ static int its_alloc_tables(struct its_node *its) u64 val = readq_relaxed(its->base + GITS_BASER + i * 8); u64 type = GITS_BASER_TYPE(val); u64 entry_size = GITS_BASER_ENTRY_SIZE(val); - int order = get_order(psz); + int order = get_order_from_bytes(psz); int alloc_size; u64 tmp; void *base; @@ -827,25 +851,25 @@ static int its_alloc_tables(struct its_node *its) u64 typer = readq_relaxed(its->base + GITS_TYPER); u32 ids = GITS_TYPER_DEVBITS(typer); - order = get_order((1UL << ids) * entry_size); + order = get_order_from_bytes((1UL << ids) * entry_size); if (order >= MAX_ORDER) { order = MAX_ORDER - 1; - pr_warn("%s: Device Table too large, reduce its page order to %u\n", - its->msi_chip.of_node->full_name, order); + its_warn("Device Table too large, reduce its page order to %u\n", + order); } } alloc_size = (1 << order) * PAGE_SIZE; - base = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order); + base = alloc_xenheap_pages(order, 0); if (!base) { err = -ENOMEM; goto out_free; } - + memset(base, 0, alloc_size); 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 | @@ -897,17 +921,17 @@ retry_baser: } if (val != tmp) { - pr_err("ITS: %s: GITS_BASER%d doesn't stick: %lx %lx\n", - its->msi_chip.of_node->full_name, i, + 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)(alloc_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); } @@ -921,8 +945,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; @@ -932,32 +955,31 @@ 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; + paddr_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_and_invalidate_dcache_va_range(pend_page, LPI_PENDBASE_SZ); - paddr = page_to_phys(pend_page); - pr_info("CPU%d: using LPI pending table @%pa\n", + paddr = __pa(pend_page); + its_info("CPU%d: using LPI pending table @%pa\n", smp_processor_id(), &paddr); - gic_data_rdist()->pend_page = pend_page; + gic_data_rdist().pend_page = pend_page; } /* Disable LPIs */ @@ -971,7 +993,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)); @@ -980,12 +1002,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); @@ -1020,7 +1042,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. @@ -1040,12 +1062,13 @@ 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) +/* TODO: Remove static for the sake of compilation */ +struct its_device *its_find_device(struct its_node *its, u32 dev_id) { struct its_device *its_dev = NULL, *tmp; unsigned long flags; - raw_spin_lock_irqsave(&its->lock, flags); + spin_lock_irqsave(&its->lock, flags); list_for_each_entry(tmp, &its->its_device_list, entry) { if (tmp->device_id == dev_id) { @@ -1054,12 +1077,13 @@ static struct its_device *its_find_device(struct its_node *its, u32 dev_id) } } - raw_spin_unlock_irqrestore(&its->lock, flags); + spin_unlock_irqrestore(&its->lock, flags); return its_dev; } -static struct its_device *its_create_device(struct its_node *its, u32 dev_id, +/* TODO: Remove static for the sake of compilation */ +struct its_device *its_create_device(struct its_node *its, u32 dev_id, int nvecs) { struct its_device *dev; @@ -1072,22 +1096,26 @@ 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); /* * At least one bit of EventID is being used, hence a minimum * of two entries. No, the architecture doesn't let you * express an ITT with a single entry. */ - nr_ites = max(2UL, roundup_pow_of_two(nvecs)); + /* + * TODO: replace roundup_pow_of_2 with shift for now. + * This code is not used later + */ + nr_ites = max(2UL, (1UL << (nvecs))); sz = nr_ites * its->ite_size; sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1; - itt = kzalloc(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; } @@ -1100,12 +1128,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_irqsave(&its->lock, flags); + spin_lock_irqsave(&its->lock, flags); list_add(&dev->entry, &its->its_device_list); - raw_spin_unlock_irqrestore(&its->lock, flags); + spin_unlock_irqrestore(&its->lock, flags); /* 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 */ @@ -1114,18 +1142,20 @@ 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) +/* TODO: Remove static for the sake of compilation */ +void its_free_device(struct its_device *its_dev) { unsigned long flags; - raw_spin_lock_irqsave(&its_dev->its->lock, flags); + spin_lock_irqsave(&its_dev->its->lock, flags); list_del(&its_dev->entry); - raw_spin_unlock_irqrestore(&its_dev->its->lock, flags); - kfree(its_dev->itt); - kfree(its_dev); + spin_unlock_irqrestore(&its_dev->its->lock, flags); + xfree(its_dev->itt); + xfree(its_dev); } -static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq) +/* TODO: Remove static for the sake of compilation */ +int its_alloc_device_irq(struct its_device *dev, int *hwirq) { int idx; @@ -1139,6 +1169,8 @@ static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq) return 0; } +/* pci and msi handling no more required here */ +#if 0 struct its_pci_alias { struct pci_dev *pdev; u32 dev_id; @@ -1218,6 +1250,9 @@ static struct msi_domain_info its_pci_msi_domain_info = { .chip = &its_msi_irq_chip, }; +#endif +/* IRQ domain management is not required */ +#if 0 static int its_irq_gic_domain_alloc(struct irq_domain *domain, unsigned int virq, irq_hw_number_t hwirq) @@ -1319,6 +1354,7 @@ static const struct irq_domain_ops its_domain_ops = { .activate = its_irq_domain_activate, .deactivate = its_irq_domain_deactivate, }; +#endif static int its_force_quiescent(void __iomem *base) { @@ -1348,58 +1384,57 @@ static int its_force_quiescent(void __iomem *base) } } -static int its_probe(struct device_node *node, struct irq_domain *parent) +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); + err = dt_device_get_address(node, 0, &its_addr, &its_size); if (err) { - pr_warn("%s: no regs?\n", node->full_name); + its_warn("%s: no regs?\n", node->full_name); return -ENXIO; } - its_base = ioremap(res.start, resource_size(&res)); + its_base = ioremap_nocache(its_addr, its_size); if (!its_base) { - pr_warn("%s: unable to map registers\n", node->full_name); + 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) & GIC_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; } err = its_force_quiescent(its_base); if (err) { - pr_warn("%s: failed to quiesce, giving up\n", + its_warn("%s: failed to quiesce, giving up\n", node->full_name); 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; @@ -1414,7 +1449,7 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) if (err) goto out_free_tables; - baser = (virt_to_phys(its->cmd_base) | + baser = (__pa(its->cmd_base) | GITS_CBASER_WaWb | GITS_CBASER_InnerShareable | (ITS_CMD_QUEUE_SZ / SZ_4K - 1) | @@ -1426,10 +1461,10 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) writel_relaxed(GITS_CTLR_ENABLE, 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; } - +#if 0 if (of_property_read_bool(its->msi_chip.of_node, "msi-controller")) { its->domain = irq_domain_add_tree(NULL, &its_domain_ops, its); if (!its->domain) { @@ -1451,27 +1486,28 @@ static int its_probe(struct device_node *node, struct irq_domain *parent) if (err) goto out_free_domains; } - +#endif spin_lock(&its_lock); list_add(&its->entry, &its_nodes); spin_unlock(&its_lock); return 0; - +#if 0 out_free_domains: if (its->msi_chip.domain) irq_domain_remove(its->msi_chip.domain); if (its->domain) irq_domain_remove(its->domain); +#endif 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); + its_err("ITS: failed probing %s (%d)\n", node->full_name, err); return err; } @@ -1484,7 +1520,7 @@ int its_cpu_init(void) { if (!list_empty(&its_nodes)) { 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; } its_cpu_init_lpis(); @@ -1494,23 +1530,28 @@ int its_cpu_init(void) return 0; } -static struct of_device_id its_device_id[] = { - { .compatible = "arm,gic-v3-its", }, - {}, -}; - -int its_init(struct device_node *node, struct rdists *rdists, - struct irq_domain *parent_domain) +int its_init(struct dt_device_node *node, struct rdist_prop *rdists) { - struct device_node *np; + struct dt_device_node *np = NULL; + + static const struct dt_device_match its_device_ids[] __initconst = + { + DT_MATCH_COMPATIBLE("arm,gic-v3-its"), + { /* sentinel */ }, + }; + + while ((np = dt_find_matching_node(np, its_device_ids))) + { + if (!dt_find_property(np, "msi-controller", NULL)) + continue; + } - for (np = of_find_matching_node(node, its_device_id); np; - np = of_find_matching_node(np, its_device_id)) { - its_probe(np, parent_domain); + if (np) { + its_probe(np); } if (list_empty(&its_nodes)) { - pr_warn("ITS: No ITS available, not enabling LPIs\n"); + its_warn("ITS: No ITS available, not enabling LPIs\n"); return -ENXIO; } diff --git a/xen/include/asm-arm/gic_v3_defs.h b/xen/include/asm-arm/gic_v3_defs.h index 4e64b56..f8bac52 100644 --- a/xen/include/asm-arm/gic_v3_defs.h +++ b/xen/include/asm-arm/gic_v3_defs.h @@ -59,11 +59,12 @@ #define GICR_WAKER_ProcessorSleep (1U << 1) #define GICR_WAKER_ChildrenAsleep (1U << 2) -#define GICD_PIDR2_ARCH_REV_MASK (0xf0) +#define GIC_PIDR2_ARCH_REV_MASK (0xf0) +#define GICD_PIDR2_ARCH_REV_MASK GIC_PIDR2_ARCH_REV_MASK #define GICD_PIDR2_ARCH_REV_SHIFT (0x4) #define GICD_PIDR2_ARCH_GICV3 (0x3) -#define GICR_PIDR2_ARCH_REV_MASK GICD_PIDR2_ARCH_REV_MASK +#define GICR_PIDR2_ARCH_REV_MASK GIC_PIDR2_ARCH_REV_MASK #define GICR_PIDR2_ARCH_REV_SHIFT GICD_PIDR2_ARCH_REV_SHIFT #define GICR_PIDR2_ARCH_GICV3 GICD_PIDR2_ARCH_GICV3 @@ -113,6 +114,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) @@ -153,6 +171,100 @@ #define ICH_SGI_IRQ_MASK 0xf #define ICH_SGI_TARGETLIST_MASK 0xffff +#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_CTLR_QUIESCENT (1U << 31) +#define GITS_CTLR_ENABLE (1U << 0) + +#define GITS_TYPER_DEVBITS_SHIFT 13 +#define GITS_TYPER_DEVBITS(r) ((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1) +#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; -- 1.7.9.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |