diff options
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its.c | 42 |
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 | */ | ||
61 | struct 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 | ||
1152 | static 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 | |||
1141 | static struct its_device *its_create_device(struct its_node *its, u32 dev_id, | 1164 | static 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 |