aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2014-11-24 09:35:15 -0500
committerJason Cooper <jason@lakedaemon.net>2014-11-26 10:55:14 -0500
commit84a6a2e7fc18dae444c5c88cc6af8878552867a5 (patch)
treed62abf1f3e14340a777f662cf86f91c7cc89f932 /drivers/irqchip
parent1ac19ca6bf97392a3a631551bac223893d24d21f (diff)
irqchip: GICv3: ITS: device allocation and configuration
The ITS has a notion of "device" that can write to it in order to generate an interrupt. Conversly, the driver maintains a per-ITS list of devices, together with their configuration information, and uses this to configure the HW. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Link: https://lkml.kernel.org/r/1416839720-18400-9-git-send-email-marc.zyngier@arm.com Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 03f9831da7b1..d687fd43fbbb 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -981,3 +981,77 @@ static void its_cpu_init_collection(void)
981 981
982 spin_unlock(&its_lock); 982 spin_unlock(&its_lock);
983} 983}
984
985static struct its_device *its_find_device(struct its_node *its, u32 dev_id)
986{
987 struct its_device *its_dev = NULL, *tmp;
988
989 raw_spin_lock(&its->lock);
990
991 list_for_each_entry(tmp, &its->its_device_list, entry) {
992 if (tmp->device_id == dev_id) {
993 its_dev = tmp;
994 break;
995 }
996 }
997
998 raw_spin_unlock(&its->lock);
999
1000 return its_dev;
1001}
1002
1003static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
1004 int nvecs)
1005{
1006 struct its_device *dev;
1007 unsigned long *lpi_map;
1008 void *itt;
1009 int lpi_base;
1010 int nr_lpis;
1011 int cpu;
1012 int sz;
1013
1014 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1015 sz = nvecs * its->ite_size;
1016 sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
1017 itt = kmalloc(sz, GFP_KERNEL);
1018 lpi_map = its_lpi_alloc_chunks(nvecs, &lpi_base, &nr_lpis);
1019
1020 if (!dev || !itt || !lpi_map) {
1021 kfree(dev);
1022 kfree(itt);
1023 kfree(lpi_map);
1024 return NULL;
1025 }
1026
1027 dev->its = its;
1028 dev->itt = itt;
1029 dev->nr_ites = nvecs;
1030 dev->lpi_map = lpi_map;
1031 dev->lpi_base = lpi_base;
1032 dev->nr_lpis = nr_lpis;
1033 dev->device_id = dev_id;
1034 INIT_LIST_HEAD(&dev->entry);
1035
1036 raw_spin_lock(&its->lock);
1037 list_add(&dev->entry, &its->its_device_list);
1038 raw_spin_unlock(&its->lock);
1039
1040 /* Bind the device to the first possible CPU */
1041 cpu = cpumask_first(cpu_online_mask);
1042 dev->collection = &its->collections[cpu];
1043
1044 /* Map device to its ITT */
1045 its_send_mapd(dev, 1);
1046
1047 return dev;
1048}
1049
1050static void its_free_device(struct its_device *its_dev)
1051{
1052 raw_spin_lock(&its_dev->its->lock);
1053 list_del(&its_dev->entry);
1054 raw_spin_unlock(&its_dev->its->lock);
1055 kfree(its_dev->itt);
1056 kfree(its_dev);
1057}