forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/kernel/irq/irqdomain.c
....@@ -31,7 +31,7 @@
3131 struct fwnode_handle fwnode;
3232 unsigned int type;
3333 char *name;
34
- void *data;
34
+ phys_addr_t *pa;
3535 };
3636
3737 #ifdef CONFIG_GENERIC_IRQ_DEBUGFS
....@@ -46,12 +46,12 @@
4646 EXPORT_SYMBOL_GPL(irqchip_fwnode_ops);
4747
4848 /**
49
- * irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for
49
+ * __irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for
5050 * identifying an irq domain
5151 * @type: Type of irqchip_fwnode. See linux/irqdomain.h
52
- * @name: Optional user provided domain name
5352 * @id: Optional user provided id if name != NULL
54
- * @data: Optional user-provided data
53
+ * @name: Optional user provided domain name
54
+ * @pa: Optional user-provided physical address
5555 *
5656 * Allocate a struct irqchip_fwid, and return a poiner to the embedded
5757 * fwnode_handle (or NULL on failure).
....@@ -62,7 +62,8 @@
6262 * domain struct.
6363 */
6464 struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
65
- const char *name, void *data)
65
+ const char *name,
66
+ phys_addr_t *pa)
6667 {
6768 struct irqchip_fwid *fwid;
6869 char *n;
....@@ -77,7 +78,7 @@
7778 n = kasprintf(GFP_KERNEL, "%s-%d", name, id);
7879 break;
7980 default:
80
- n = kasprintf(GFP_KERNEL, "irqchip@%p", data);
81
+ n = kasprintf(GFP_KERNEL, "irqchip@%pa", pa);
8182 break;
8283 }
8384
....@@ -89,8 +90,8 @@
8990
9091 fwid->type = type;
9192 fwid->name = n;
92
- fwid->data = data;
93
- fwid->fwnode.ops = &irqchip_fwnode_ops;
93
+ fwid->pa = pa;
94
+ fwnode_init(&fwid->fwnode, &irqchip_fwnode_ops);
9495 return &fwid->fwnode;
9596 }
9697 EXPORT_SYMBOL_GPL(__irq_domain_alloc_fwnode);
....@@ -123,7 +124,7 @@
123124 * @ops: domain callbacks
124125 * @host_data: Controller private data pointer
125126 *
126
- * Allocates and initialize and irq_domain structure.
127
+ * Allocates and initializes an irq_domain structure.
127128 * Returns pointer to IRQ domain, or NULL on failure.
128129 */
129130 struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
....@@ -131,18 +132,17 @@
131132 const struct irq_domain_ops *ops,
132133 void *host_data)
133134 {
134
- struct device_node *of_node = to_of_node(fwnode);
135135 struct irqchip_fwid *fwid;
136136 struct irq_domain *domain;
137137
138138 static atomic_t unknown_domains;
139139
140140 domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
141
- GFP_KERNEL, of_node_to_nid(of_node));
142
- if (WARN_ON(!domain))
141
+ GFP_KERNEL, of_node_to_nid(to_of_node(fwnode)));
142
+ if (!domain)
143143 return NULL;
144144
145
- if (fwnode && is_fwnode_irqchip(fwnode)) {
145
+ if (is_fwnode_irqchip(fwnode)) {
146146 fwid = container_of(fwnode, struct irqchip_fwid, fwnode);
147147
148148 switch (fwid->type) {
....@@ -161,30 +161,16 @@
161161 domain->name = fwid->name;
162162 break;
163163 }
164
-#ifdef CONFIG_ACPI
165
- } else if (is_acpi_device_node(fwnode)) {
166
- struct acpi_buffer buf = {
167
- .length = ACPI_ALLOCATE_BUFFER,
168
- };
169
- acpi_handle handle;
170
-
171
- handle = acpi_device_handle(to_acpi_device_node(fwnode));
172
- if (acpi_get_name(handle, ACPI_FULL_PATHNAME, &buf) == AE_OK) {
173
- domain->name = buf.pointer;
174
- domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;
175
- }
176
-
177
- domain->fwnode = fwnode;
178
-#endif
179
- } else if (of_node) {
164
+ } else if (is_of_node(fwnode) || is_acpi_device_node(fwnode) ||
165
+ is_software_node(fwnode)) {
180166 char *name;
181167
182168 /*
183
- * DT paths contain '/', which debugfs is legitimately
169
+ * fwnode paths contain '/', which debugfs is legitimately
184170 * unhappy about. Replace them with ':', which does
185171 * the trick and is not as offensive as '\'...
186172 */
187
- name = kasprintf(GFP_KERNEL, "%pOF", of_node);
173
+ name = kasprintf(GFP_KERNEL, "%pfw", fwnode);
188174 if (!name) {
189175 kfree(domain);
190176 return NULL;
....@@ -209,7 +195,8 @@
209195 domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;
210196 }
211197
212
- of_node_get(of_node);
198
+ fwnode_handle_get(fwnode);
199
+ fwnode_dev_initialized(fwnode, true);
213200
214201 /* Fill structure */
215202 INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL);
....@@ -258,7 +245,8 @@
258245
259246 pr_debug("Removed domain %s\n", domain->name);
260247
261
- of_node_put(irq_domain_get_of_node(domain));
248
+ fwnode_dev_initialized(domain->fwnode, false);
249
+ fwnode_handle_put(domain->fwnode);
262250 if (domain->flags & IRQ_DOMAIN_NAME_ALLOCATED)
263251 kfree(domain->name);
264252 kfree(domain);
....@@ -460,6 +448,20 @@
460448 }
461449 EXPORT_SYMBOL_GPL(irq_set_default_host);
462450
451
+/**
452
+ * irq_get_default_host() - Retrieve the "default" irq domain
453
+ *
454
+ * Returns: the default domain, if any.
455
+ *
456
+ * Modern code should never use this. This should only be used on
457
+ * systems that cannot implement a firmware->fwnode mapping (which
458
+ * both DT and ACPI provide).
459
+ */
460
+struct irq_domain *irq_get_default_host(void)
461
+{
462
+ return irq_default_domain;
463
+}
464
+
463465 static void irq_domain_clear_mapping(struct irq_domain *domain,
464466 irq_hw_number_t hwirq)
465467 {
....@@ -624,17 +626,19 @@
624626 EXPORT_SYMBOL_GPL(irq_create_direct_mapping);
625627
626628 /**
627
- * irq_create_mapping() - Map a hardware interrupt into linux irq space
629
+ * irq_create_mapping_affinity() - Map a hardware interrupt into linux irq space
628630 * @domain: domain owning this hardware interrupt or NULL for default domain
629631 * @hwirq: hardware irq number in that domain space
632
+ * @affinity: irq affinity
630633 *
631634 * Only one mapping per hardware interrupt is permitted. Returns a linux
632635 * irq number.
633636 * If the sense/trigger is to be specified, set_irq_type() should be called
634637 * on the number returned from that call.
635638 */
636
-unsigned int irq_create_mapping(struct irq_domain *domain,
637
- irq_hw_number_t hwirq)
639
+unsigned int irq_create_mapping_affinity(struct irq_domain *domain,
640
+ irq_hw_number_t hwirq,
641
+ const struct irq_affinity_desc *affinity)
638642 {
639643 struct device_node *of_node;
640644 int virq;
....@@ -660,7 +664,8 @@
660664 }
661665
662666 /* Allocate a virtual interrupt number */
663
- virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), NULL);
667
+ virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node),
668
+ affinity);
664669 if (virq <= 0) {
665670 pr_debug("-> virq allocation failed\n");
666671 return 0;
....@@ -676,7 +681,7 @@
676681
677682 return virq;
678683 }
679
-EXPORT_SYMBOL_GPL(irq_create_mapping);
684
+EXPORT_SYMBOL_GPL(irq_create_mapping_affinity);
680685
681686 /**
682687 * irq_create_strict_mappings() - Map a range of hw irqs to fixed linux irqs
....@@ -731,16 +736,17 @@
731736 return 0;
732737 }
733738
734
-static void of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
739
+static void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args,
740
+ unsigned int count,
735741 struct irq_fwspec *fwspec)
736742 {
737743 int i;
738744
739
- fwspec->fwnode = irq_data->np ? &irq_data->np->fwnode : NULL;
740
- fwspec->param_count = irq_data->args_count;
745
+ fwspec->fwnode = np ? &np->fwnode : NULL;
746
+ fwspec->param_count = count;
741747
742
- for (i = 0; i < irq_data->args_count; i++)
743
- fwspec->param[i] = irq_data->args[i];
748
+ for (i = 0; i < count; i++)
749
+ fwspec->param[i] = args[i];
744750 }
745751
746752 unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
....@@ -838,7 +844,9 @@
838844 {
839845 struct irq_fwspec fwspec;
840846
841
- of_phandle_args_to_fwspec(irq_data, &fwspec);
847
+ of_phandle_args_to_fwspec(irq_data->np, irq_data->args,
848
+ irq_data->args_count, &fwspec);
849
+
842850 return irq_create_fwspec_mapping(&fwspec);
843851 }
844852 EXPORT_SYMBOL_GPL(irq_create_of_mapping);
....@@ -869,7 +877,7 @@
869877 EXPORT_SYMBOL_GPL(irq_dispose_mapping);
870878
871879 /**
872
- * irq_find_mapping() - Find a linux irq from an hw irq number.
880
+ * irq_find_mapping() - Find a linux irq from a hw irq number.
873881 * @domain: domain owning this hardware interrupt
874882 * @hwirq: hardware irq number in that domain space
875883 */
....@@ -930,11 +938,10 @@
930938 const u32 *intspec, unsigned int intsize,
931939 irq_hw_number_t *out_hwirq, unsigned int *out_type)
932940 {
933
- if (WARN_ON(intsize < 2))
934
- return -EINVAL;
935
- *out_hwirq = intspec[0];
936
- *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
937
- return 0;
941
+ struct irq_fwspec fwspec;
942
+
943
+ of_phandle_args_to_fwspec(ctrlr, intspec, intsize, &fwspec);
944
+ return irq_domain_translate_twocell(d, &fwspec, out_hwirq, out_type);
938945 }
939946 EXPORT_SYMBOL_GPL(irq_domain_xlate_twocell);
940947
....@@ -970,8 +977,46 @@
970977 };
971978 EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
972979
980
+/**
981
+ * irq_domain_translate_onecell() - Generic translate for direct one cell
982
+ * bindings
983
+ */
984
+int irq_domain_translate_onecell(struct irq_domain *d,
985
+ struct irq_fwspec *fwspec,
986
+ unsigned long *out_hwirq,
987
+ unsigned int *out_type)
988
+{
989
+ if (WARN_ON(fwspec->param_count < 1))
990
+ return -EINVAL;
991
+ *out_hwirq = fwspec->param[0];
992
+ *out_type = IRQ_TYPE_NONE;
993
+ return 0;
994
+}
995
+EXPORT_SYMBOL_GPL(irq_domain_translate_onecell);
996
+
997
+/**
998
+ * irq_domain_translate_twocell() - Generic translate for direct two cell
999
+ * bindings
1000
+ *
1001
+ * Device Tree IRQ specifier translation function which works with two cell
1002
+ * bindings where the cell values map directly to the hwirq number
1003
+ * and linux irq flags.
1004
+ */
1005
+int irq_domain_translate_twocell(struct irq_domain *d,
1006
+ struct irq_fwspec *fwspec,
1007
+ unsigned long *out_hwirq,
1008
+ unsigned int *out_type)
1009
+{
1010
+ if (WARN_ON(fwspec->param_count < 2))
1011
+ return -EINVAL;
1012
+ *out_hwirq = fwspec->param[0];
1013
+ *out_type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
1014
+ return 0;
1015
+}
1016
+EXPORT_SYMBOL_GPL(irq_domain_translate_twocell);
1017
+
9731018 int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq,
974
- int node, const struct cpumask *affinity)
1019
+ int node, const struct irq_affinity_desc *affinity)
9751020 {
9761021 unsigned int hint;
9771022
....@@ -992,6 +1037,18 @@
9921037
9931038 return virq;
9941039 }
1040
+
1041
+/**
1042
+ * irq_domain_reset_irq_data - Clear hwirq, chip and chip_data in @irq_data
1043
+ * @irq_data: The pointer to irq_data
1044
+ */
1045
+void irq_domain_reset_irq_data(struct irq_data *irq_data)
1046
+{
1047
+ irq_data->hwirq = 0;
1048
+ irq_data->chip = &no_irq_chip;
1049
+ irq_data->chip_data = NULL;
1050
+}
1051
+EXPORT_SYMBOL_GPL(irq_domain_reset_irq_data);
9951052
9961053 #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
9971054 /**
....@@ -1084,6 +1141,17 @@
10841141 return irq_data;
10851142 }
10861143
1144
+static void __irq_domain_free_hierarchy(struct irq_data *irq_data)
1145
+{
1146
+ struct irq_data *tmp;
1147
+
1148
+ while (irq_data) {
1149
+ tmp = irq_data;
1150
+ irq_data = irq_data->parent_data;
1151
+ kfree(tmp);
1152
+ }
1153
+}
1154
+
10871155 static void irq_domain_free_irq_data(unsigned int virq, unsigned int nr_irqs)
10881156 {
10891157 struct irq_data *irq_data, *tmp;
....@@ -1095,12 +1163,84 @@
10951163 irq_data->parent_data = NULL;
10961164 irq_data->domain = NULL;
10971165
1098
- while (tmp) {
1099
- irq_data = tmp;
1100
- tmp = tmp->parent_data;
1101
- kfree(irq_data);
1166
+ __irq_domain_free_hierarchy(tmp);
1167
+ }
1168
+}
1169
+
1170
+/**
1171
+ * irq_domain_disconnect_hierarchy - Mark the first unused level of a hierarchy
1172
+ * @domain: IRQ domain from which the hierarchy is to be disconnected
1173
+ * @virq: IRQ number where the hierarchy is to be trimmed
1174
+ *
1175
+ * Marks the @virq level belonging to @domain as disconnected.
1176
+ * Returns -EINVAL if @virq doesn't have a valid irq_data pointing
1177
+ * to @domain.
1178
+ *
1179
+ * Its only use is to be able to trim levels of hierarchy that do not
1180
+ * have any real meaning for this interrupt, and that the driver marks
1181
+ * as such from its .alloc() callback.
1182
+ */
1183
+int irq_domain_disconnect_hierarchy(struct irq_domain *domain,
1184
+ unsigned int virq)
1185
+{
1186
+ struct irq_data *irqd;
1187
+
1188
+ irqd = irq_domain_get_irq_data(domain, virq);
1189
+ if (!irqd)
1190
+ return -EINVAL;
1191
+
1192
+ irqd->chip = ERR_PTR(-ENOTCONN);
1193
+ return 0;
1194
+}
1195
+EXPORT_SYMBOL_GPL(irq_domain_disconnect_hierarchy);
1196
+
1197
+static int irq_domain_trim_hierarchy(unsigned int virq)
1198
+{
1199
+ struct irq_data *tail, *irqd, *irq_data;
1200
+
1201
+ irq_data = irq_get_irq_data(virq);
1202
+ tail = NULL;
1203
+
1204
+ /* The first entry must have a valid irqchip */
1205
+ if (!irq_data->chip || IS_ERR(irq_data->chip))
1206
+ return -EINVAL;
1207
+
1208
+ /*
1209
+ * Validate that the irq_data chain is sane in the presence of
1210
+ * a hierarchy trimming marker.
1211
+ */
1212
+ for (irqd = irq_data->parent_data; irqd; irq_data = irqd, irqd = irqd->parent_data) {
1213
+ /* Can't have a valid irqchip after a trim marker */
1214
+ if (irqd->chip && tail)
1215
+ return -EINVAL;
1216
+
1217
+ /* Can't have an empty irqchip before a trim marker */
1218
+ if (!irqd->chip && !tail)
1219
+ return -EINVAL;
1220
+
1221
+ if (IS_ERR(irqd->chip)) {
1222
+ /* Only -ENOTCONN is a valid trim marker */
1223
+ if (PTR_ERR(irqd->chip) != -ENOTCONN)
1224
+ return -EINVAL;
1225
+
1226
+ tail = irq_data;
11021227 }
11031228 }
1229
+
1230
+ /* No trim marker, nothing to do */
1231
+ if (!tail)
1232
+ return 0;
1233
+
1234
+ pr_info("IRQ%d: trimming hierarchy from %s\n",
1235
+ virq, tail->parent_data->domain->name);
1236
+
1237
+ /* Sever the inner part of the hierarchy... */
1238
+ irqd = tail;
1239
+ tail = tail->parent_data;
1240
+ irqd->parent_data = NULL;
1241
+ __irq_domain_free_hierarchy(tail);
1242
+
1243
+ return 0;
11041244 }
11051245
11061246 static int irq_domain_alloc_irq_data(struct irq_domain *domain,
....@@ -1194,18 +1334,6 @@
11941334 EXPORT_SYMBOL(irq_domain_set_info);
11951335
11961336 /**
1197
- * irq_domain_reset_irq_data - Clear hwirq, chip and chip_data in @irq_data
1198
- * @irq_data: The pointer to irq_data
1199
- */
1200
-void irq_domain_reset_irq_data(struct irq_data *irq_data)
1201
-{
1202
- irq_data->hwirq = 0;
1203
- irq_data->chip = &no_irq_chip;
1204
- irq_data->chip_data = NULL;
1205
-}
1206
-EXPORT_SYMBOL_GPL(irq_domain_reset_irq_data);
1207
-
1208
-/**
12091337 * irq_domain_free_irqs_common - Clear irq_data and free the parent
12101338 * @domain: Interrupt domain to match
12111339 * @virq: IRQ number to start with
....@@ -1243,7 +1371,6 @@
12431371 }
12441372 irq_domain_free_irqs_common(domain, virq, nr_irqs);
12451373 }
1246
-EXPORT_SYMBOL_GPL(irq_domain_free_irqs_top);
12471374
12481375 static void irq_domain_free_irqs_hierarchy(struct irq_domain *domain,
12491376 unsigned int irq_base,
....@@ -1275,7 +1402,7 @@
12751402 /**
12761403 * __irq_domain_alloc_irqs - Allocate IRQs from domain
12771404 * @domain: domain to allocate from
1278
- * @irq_base: allocate specified IRQ nubmer if irq_base >= 0
1405
+ * @irq_base: allocate specified IRQ number if irq_base >= 0
12791406 * @nr_irqs: number of IRQs to allocate
12801407 * @node: NUMA node id for memory allocation
12811408 * @arg: domain specific argument
....@@ -1296,7 +1423,7 @@
12961423 */
12971424 int __irq_domain_alloc_irqs(struct irq_domain *domain, int irq_base,
12981425 unsigned int nr_irqs, int node, void *arg,
1299
- bool realloc, const struct cpumask *affinity)
1426
+ bool realloc, const struct irq_affinity_desc *affinity)
13001427 {
13011428 int i, ret, virq;
13021429
....@@ -1330,6 +1457,15 @@
13301457 mutex_unlock(&irq_domain_mutex);
13311458 goto out_free_irq_data;
13321459 }
1460
+
1461
+ for (i = 0; i < nr_irqs; i++) {
1462
+ ret = irq_domain_trim_hierarchy(virq + i);
1463
+ if (ret) {
1464
+ mutex_unlock(&irq_domain_mutex);
1465
+ goto out_free_irq_data;
1466
+ }
1467
+ }
1468
+
13331469 for (i = 0; i < nr_irqs; i++)
13341470 irq_domain_insert_irq(virq + i);
13351471 mutex_unlock(&irq_domain_mutex);
....@@ -1752,6 +1888,7 @@
17521888 static void debugfs_remove_domain_dir(struct irq_domain *d)
17531889 {
17541890 debugfs_remove(d->debugfs_file);
1891
+ d->debugfs_file = NULL;
17551892 }
17561893
17571894 void __init irq_domain_debugfs_init(struct dentry *root)
....@@ -1759,8 +1896,6 @@
17591896 struct irq_domain *d;
17601897
17611898 domain_dir = debugfs_create_dir("domains", root);
1762
- if (!domain_dir)
1763
- return;
17641899
17651900 debugfs_create_file("default", 0444, domain_dir, NULL,
17661901 &irq_domain_debug_fops);