aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c42
1 files changed, 38 insertions, 4 deletions
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 39261798c59f..6bd881be24ea 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -55,6 +55,16 @@ struct its_collection {
55}; 55};
56 56
57/* 57/*
58 * The ITS_BASER structure - contains memory information and cached
59 * value of BASER register configuration.
60 */
61struct its_baser {
62 void *base;
63 u64 val;
64 u32 order;
65};
66
67/*
58 * The ITS structure - contains most of the infrastructure, with the 68 * The ITS structure - contains most of the infrastructure, with the
59 * top-level MSI domain, the command queue, the collections, and the 69 * top-level MSI domain, the command queue, the collections, and the
60 * list of devices writing to it. 70 * list of devices writing to it.
@@ -66,14 +76,12 @@ struct its_node {
66 unsigned long phys_base; 76 unsigned long phys_base;
67 struct its_cmd_block *cmd_base; 77 struct its_cmd_block *cmd_base;
68 struct its_cmd_block *cmd_write; 78 struct its_cmd_block *cmd_write;
69 struct { 79 struct its_baser tables[GITS_BASER_NR_REGS];
70 void *base;
71 u32 order;
72 } tables[GITS_BASER_NR_REGS];
73 struct its_collection *collections; 80 struct its_collection *collections;
74 struct list_head its_device_list; 81 struct list_head its_device_list;
75 u64 flags; 82 u64 flags;
76 u32 ite_size; 83 u32 ite_size;
84 u32 device_ids;
77}; 85};
78 86
79#define ITS_ITT_ALIGN SZ_256 87#define ITS_ITT_ALIGN SZ_256
@@ -838,6 +846,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
838 ids = GITS_TYPER_DEVBITS(typer); 846 ids = GITS_TYPER_DEVBITS(typer);
839 } 847 }
840 848
849 its->device_ids = ids;
850
841 for (i = 0; i < GITS_BASER_NR_REGS; i++) { 851 for (i = 0; i < GITS_BASER_NR_REGS; i++) {
842 u64 val = readq_relaxed(its->base + GITS_BASER + i * 8); 852 u64 val = readq_relaxed(its->base + GITS_BASER + i * 8);
843 u64 type = GITS_BASER_TYPE(val); 853 u64 type = GITS_BASER_TYPE(val);
@@ -913,6 +923,7 @@ retry_baser:
913 } 923 }
914 924
915 val |= alloc_pages - 1; 925 val |= alloc_pages - 1;
926 its->tables[i].val = val;
916 927
917 writeq_relaxed(val, its->base + GITS_BASER + i * 8); 928 writeq_relaxed(val, its->base + GITS_BASER + i * 8);
918 tmp = readq_relaxed(its->base + GITS_BASER + i * 8); 929 tmp = readq_relaxed(its->base + GITS_BASER + i * 8);
@@ -1138,9 +1149,22 @@ static struct its_device *its_find_device(struct its_node *its, u32 dev_id)
1138 return its_dev; 1149 return its_dev;
1139} 1150}
1140 1151
1152static struct its_baser *its_get_baser(struct its_node *its, u32 type)
1153{
1154 int i;
1155
1156 for (i = 0; i < GITS_BASER_NR_REGS; i++) {
1157 if (GITS_BASER_TYPE(its->tables[i].val) == type)
1158 return &its->tables[i];
1159 }
1160
1161 return NULL;
1162}
1163
1141static struct its_device *its_create_device(struct its_node *its, u32 dev_id, 1164static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
1142 int nvecs) 1165 int nvecs)
1143{ 1166{
1167 struct its_baser *baser;
1144 struct its_device *dev; 1168 struct its_device *dev;
1145 unsigned long *lpi_map; 1169 unsigned long *lpi_map;
1146 unsigned long flags; 1170 unsigned long flags;
@@ -1151,6 +1175,16 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
1151 int nr_ites; 1175 int nr_ites;
1152 int sz; 1176 int sz;
1153 1177
1178 baser = its_get_baser(its, GITS_BASER_TYPE_DEVICE);
1179
1180 /* Don't allow 'dev_id' that exceeds single, flat table limit */
1181 if (baser) {
1182 if (dev_id >= (PAGE_ORDER_TO_SIZE(baser->order) /
1183 GITS_BASER_ENTRY_SIZE(baser->val)))
1184 return NULL;
1185 } else if (ilog2(dev_id) >= its->device_ids)
1186 return NULL;
1187
1154 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 1188 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1155 /* 1189 /*
1156 * At least one bit of EventID is being used, hence a minimum 1190 * At least one bit of EventID is being used, hence a minimum