History

genirq/irq_sim: Simplify the API

The interrupt simulator API exposes a lot of custom data structures and functions and doesn't reuse the interfaces already exposed by the irq subsystem. This patch tries to address it. We hide all the simulator-related data structures from users and instead rely on the well-known irq domain. When creating the interrupt simulator the user receives a pointer to a newly created irq_domain and can use it to create mappings for simulated interrupts. It is also possible to pass a handle to fwnode when creating the simulator domain and retrieve it using irq_find_matching_fwnode(). The irq_sim_fire() function is dropped as well. Instead we implement the irq_get/set_irqchip_state interface. We modify the two modules that use the simulator at the same time as adding these changes in order to reduce the intermediate bloat that would result when trying to migrate the drivers in separate patches.

Bartosz Golaszewski committed 6 years ago

Commit 337cbeb1 parent 5c8f77a5 files · +237 −151Browse files

Unified · Split

5 files
  1. drivers/gpio/gpio-mockup.c +42 −11
  2. drivers/iio/dummy/iio_dummy_evgen.c +20 −14
  3. include/linux/irq_sim.h +9 −24
  4. kernel/irq/Kconfig +1 −0
  5. kernel/irq/irq_sim.c +165 −102
drivers/gpio/gpio-mockup.c+42−11
@@ -14,6 +14,7 @@ · 13 unmodified lines
1414 #include <linux/interrupt.h>
1515 #include <linux/irq.h>
1616 #include <linux/irq_sim.h>
17+#include <linux/irqdomain.h>
1718 #include <linux/module.h>
1819 #include <linux/platform_device.h>
1920 #include <linux/property.h>
@@ -48,7 +49,7 @@ struct gpio_mockup_line_status { · 28 unmodified lines
4849 struct gpio_mockup_chip {
4950 struct gpio_chip gc;
5051 struct gpio_mockup_line_status *lines;
51− struct irq_sim irqsim;
52+ struct irq_domain *irq_sim_domain;
5253 struct dentry *dbg_dir;
5354 struct mutex lock;
5455 };
@@ -144,14 +145,12 @@ static void gpio_mockup_set_multiple(struct gpio_chip *gc, · 89 unmodified lines
144145 static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
145146 unsigned int offset, int value)
146147 {
148+ int curr, irq, irq_type, ret = 0;
147149 struct gpio_desc *desc;
148150 struct gpio_chip *gc;
149− struct irq_sim *sim;
150− int curr, irq, irq_type;
151151
152152 gc = &chip->gc;
153153 desc = &gc->gpiodev->descs[offset];
154− sim = &chip->irqsim;
155154
156155 mutex_lock(&chip->lock);
157156
@@ -161,14 +160,28 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip, · 3 unmodified lines
161160 if (curr == value)
162161 goto out;
163162
164− irq = irq_sim_irqnum(sim, offset);
163+ irq = irq_find_mapping(chip->irq_sim_domain, offset);
164+ if (!irq)
165+ /*
166+ * This is fine - it just means, nobody is listening
167+ * for interrupts on this line, otherwise
168+ * irq_create_mapping() would have been called from
169+ * the to_irq() callback.
170+ */
171+ goto set_value;
172+
165173 irq_type = irq_get_trigger_type(irq);
166174
167175 if ((value == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) ||
168− (value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING)))
169− irq_sim_fire(sim, offset);
176+ (value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING))) {
177+ ret = irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING,
178+ true);
179+ if (ret)
180+ goto out;
181+ }
170182 }
171183
184+set_value:
172185 /* Change the value unless we're actively driving the line. */
173186 if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
174187 !test_bit(FLAG_IS_OUT, &desc->flags))
@@ -177,7 +190,7 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip, · 2 unmodified lines
177190 out:
178191 chip->lines[offset].pull = value;
179192 mutex_unlock(&chip->lock);
180− return 0;
193+ return ret;
181194 }
182195
183196 static int gpio_mockup_set_config(struct gpio_chip *gc,
@@ -236,7 +249,7 @@ static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset) · 52 unmodified lines
236249 {
237250 struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
238251
239− return irq_sim_irqnum(&chip->irqsim, offset);
252+ return irq_create_mapping(chip->irq_sim_domain, offset);
240253 }
241254
242255 static void gpio_mockup_free(struct gpio_chip *gc, unsigned int offset)
@@ -389,6 +402,19 @@ static int gpio_mockup_name_lines(struct device *dev, · 146 unmodified lines
389402 return 0;
390403 }
391404
405+static void gpio_mockup_dispose_mappings(void *data)
406+{
407+ struct gpio_mockup_chip *chip = data;
408+ struct gpio_chip *gc = &chip->gc;
409+ int i, irq;
410+
411+ for (i = 0; i < gc->ngpio; i++) {
412+ irq = irq_find_mapping(chip->irq_sim_domain, i);
413+ if (irq)
414+ irq_dispose_mapping(irq);
415+ }
416+}
417+
392418 static int gpio_mockup_probe(struct platform_device *pdev)
393419 {
394420 struct gpio_mockup_chip *chip;
@@ -456,8 +482,13 @@ static int gpio_mockup_probe(struct platform_device *pdev) · 61 unmodified lines
456482 return rv;
457483 }
458484
459− rv = devm_irq_sim_init(dev, &chip->irqsim, gc->ngpio);
460− if (rv < 0)
485+ chip->irq_sim_domain = devm_irq_domain_create_sim(dev, NULL,
486+ gc->ngpio);
487+ if (IS_ERR(chip->irq_sim_domain))
488+ return PTR_ERR(chip->irq_sim_domain);
489+
490+ rv = devm_add_action_or_reset(dev, gpio_mockup_dispose_mappings, chip);
491+ if (rv)
461492 return rv;
462493
463494 rv = devm_gpiochip_add_data(dev, &chip->gc, chip);
drivers/iio/dummy/iio_dummy_evgen.c+20−14
@@ -37,8 +37,7 @@ struct iio_dummy_eventgen { · 36 unmodified lines
3737 struct iio_dummy_regs regs[IIO_EVENTGEN_NO];
3838 struct mutex lock;
3939 bool inuse[IIO_EVENTGEN_NO];
40− struct irq_sim irq_sim;
41− int base;
40+ struct irq_domain *irq_sim_domain;
4241 };
4342
4443 /* We can only ever have one instance of this 'device' */
@@ -46,19 +45,17 @@ static struct iio_dummy_eventgen *iio_evgen; · 1 unmodified line
4645
4746 static int iio_dummy_evgen_create(void)
4847 {
49− int ret;
50−
5148 iio_evgen = kzalloc(sizeof(*iio_evgen), GFP_KERNEL);
5249 if (!iio_evgen)
5350 return -ENOMEM;
5451
55− ret = irq_sim_init(&iio_evgen->irq_sim, IIO_EVENTGEN_NO);
56− if (ret < 0) {
52+ iio_evgen->irq_sim_domain = irq_domain_create_sim(NULL,
53+ IIO_EVENTGEN_NO);
54+ if (IS_ERR(iio_evgen->irq_sim_domain)) {
5755 kfree(iio_evgen);
58− return ret;
56+ return PTR_ERR(iio_evgen->irq_sim_domain);
5957 }
6058
61− iio_evgen->base = irq_sim_irqnum(&iio_evgen->irq_sim, 0);
6259 mutex_init(&iio_evgen->lock);
6360
6461 return 0;
@@ -80,7 +77,7 @@ int iio_dummy_evgen_get_irq(void) · 15 unmodified lines
8077 mutex_lock(&iio_evgen->lock);
8178 for (i = 0; i < IIO_EVENTGEN_NO; i++) {
8279 if (!iio_evgen->inuse[i]) {
83− ret = irq_sim_irqnum(&iio_evgen->irq_sim, i);
80+ ret = irq_create_mapping(iio_evgen->irq_sim_domain, i);
8481 iio_evgen->inuse[i] = true;
8582 break;
8683 }
@@ -101,21 +98,27 @@ EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_irq); · 14 unmodified lines
10198 */
10299 void iio_dummy_evgen_release_irq(int irq)
103100 {
101+ struct irq_data *irqd = irq_get_irq_data(irq);
102+
104103 mutex_lock(&iio_evgen->lock);
105− iio_evgen->inuse[irq - iio_evgen->base] = false;
104+ iio_evgen->inuse[irqd_to_hwirq(irqd)] = false;
105+ irq_dispose_mapping(irq);
106106 mutex_unlock(&iio_evgen->lock);
107107 }
108108 EXPORT_SYMBOL_GPL(iio_dummy_evgen_release_irq);
109109
110110 struct iio_dummy_regs *iio_dummy_evgen_get_regs(int irq)
111111 {
112− return &iio_evgen->regs[irq - iio_evgen->base];
112+ struct irq_data *irqd = irq_get_irq_data(irq);
113+
114+ return &iio_evgen->regs[irqd_to_hwirq(irqd)];
115+
113116 }
114117 EXPORT_SYMBOL_GPL(iio_dummy_evgen_get_regs);
115118
116119 static void iio_dummy_evgen_free(void)
117120 {
118− irq_sim_fini(&iio_evgen->irq_sim);
121+ irq_domain_remove_sim(iio_evgen->irq_sim_domain);
119122 kfree(iio_evgen);
120123 }
121124
@@ -131,7 +134,7 @@ static ssize_t iio_evgen_poke(struct device *dev, · 9 unmodified lines
131134 {
132135 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
133136 unsigned long event;
134− int ret;
137+ int ret, irq;
135138
136139 ret = kstrtoul(buf, 10, &event);
137140 if (ret)
@@ -140,7 +143,10 @@ static ssize_t iio_evgen_poke(struct device *dev, · 2 unmodified lines
140143 iio_evgen->regs[this_attr->address].reg_id = this_attr->address;
141144 iio_evgen->regs[this_attr->address].reg_data = event;
142145
143− irq_sim_fire(&iio_evgen->irq_sim, this_attr->address);
146+ irq = irq_find_mapping(iio_evgen->irq_sim_domain, this_attr->address);
147+ ret = irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING, true);
148+ if (ret)
149+ return ret;
144150
145151 return len;
146152 }
include/linux/irq_sim.h+9−24
@@ -1,41 +1,26 @@
11 /* SPDX-License-Identifier: GPL-2.0+ */
22 /*
33 * Copyright (C) 2017-2018 Bartosz Golaszewski <brgl@bgdev.pl>
4+ * Copyright (C) 2020 Bartosz Golaszewski <bgolaszewski@baylibre.com>
45 */
56
67 #ifndef _LINUX_IRQ_SIM_H
78 #define _LINUX_IRQ_SIM_H
89
9−#include <linux/irq_work.h>
1010 #include <linux/device.h>
11+#include <linux/fwnode.h>
12+#include <linux/irqdomain.h>
1113
1214 /*
1315 * Provides a framework for allocating simulated interrupts which can be
1416 * requested like normal irqs and enqueued from process context.
1517 */
1618
17−struct irq_sim_work_ctx {
18− struct irq_work work;
19− unsigned long *pending;
20−};
21−
22−struct irq_sim_irq_ctx {
23− int irqnum;
24− bool enabled;
25−};
26−
27−struct irq_sim {
28− struct irq_sim_work_ctx work_ctx;
29− int irq_base;
30− unsigned int irq_count;
31− struct irq_sim_irq_ctx *irqs;
32−};
33−
34−int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs);
35−int devm_irq_sim_init(struct device *dev, struct irq_sim *sim,
36− unsigned int num_irqs);
37−void irq_sim_fini(struct irq_sim *sim);
38−void irq_sim_fire(struct irq_sim *sim, unsigned int offset);
39−int irq_sim_irqnum(struct irq_sim *sim, unsigned int offset);
19+struct irq_domain *irq_domain_create_sim(struct fwnode_handle *fwnode,
20+ unsigned int num_irqs);
21+struct irq_domain *devm_irq_domain_create_sim(struct device *dev,
22+ struct fwnode_handle *fwnode,
23+ unsigned int num_irqs);
24+void irq_domain_remove_sim(struct irq_domain *domain);
4025
4126 #endif /* _LINUX_IRQ_SIM_H */
kernel/irq/Kconfig+1−0
@@ -72,6 +72,7 @@ config IRQ_DOMAIN · 71 unmodified lines
7272 config IRQ_SIM
7373 bool
7474 select IRQ_WORK
75+ select IRQ_DOMAIN
7576
7677 # Support for hierarchical irq domains
7778 config IRQ_DOMAIN_HIERARCHY
kernel/irq/irq_sim.c+165−102
@@ -1,14 +1,31 @@
11 // SPDX-License-Identifier: GPL-2.0+
22 /*
33 * Copyright (C) 2017-2018 Bartosz Golaszewski <brgl@bgdev.pl>
4+ * Copyright (C) 2020 Bartosz Golaszewski <bgolaszewski@baylibre.com>
45 */
56
6−#include <linux/slab.h>
7−#include <linux/irq_sim.h>
87 #include <linux/irq.h>
8+#include <linux/irq_sim.h>
9+#include <linux/irq_work.h>
10+#include <linux/interrupt.h>
11+#include <linux/slab.h>
12+
13+struct irq_sim_work_ctx {
14+ struct irq_work work;
15+ int irq_base;
16+ unsigned int irq_count;
17+ unsigned long *pending;
18+ struct irq_domain *domain;
19+};
20+
21+struct irq_sim_irq_ctx {
22+ int irqnum;
23+ bool enabled;
24+ struct irq_sim_work_ctx *work_ctx;
25+};
926
1027 struct irq_sim_devres {
11− struct irq_sim *sim;
28+ struct irq_domain *domain;
1229 };
1330
1431 static void irq_sim_irqmask(struct irq_data *data)
@@ -36,159 +53,205 @@ static int irq_sim_set_type(struct irq_data *data, unsigned int type) · 21 unmodified lines
3653 return 0;
3754 }
3855
56+static int irq_sim_get_irqchip_state(struct irq_data *data,
57+ enum irqchip_irq_state which, bool *state)
58+{
59+ struct irq_sim_irq_ctx *irq_ctx = irq_data_get_irq_chip_data(data);
60+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
61+
62+ switch (which) {
63+ case IRQCHIP_STATE_PENDING:
64+ if (irq_ctx->enabled)
65+ *state = test_bit(hwirq, irq_ctx->work_ctx->pending);
66+ break;
67+ default:
68+ return -EINVAL;
69+ }
70+
71+ return 0;
72+}
73+
74+static int irq_sim_set_irqchip_state(struct irq_data *data,
75+ enum irqchip_irq_state which, bool state)
76+{
77+ struct irq_sim_irq_ctx *irq_ctx = irq_data_get_irq_chip_data(data);
78+ irq_hw_number_t hwirq = irqd_to_hwirq(data);
79+
80+ switch (which) {
81+ case IRQCHIP_STATE_PENDING:
82+ if (irq_ctx->enabled) {
83+ assign_bit(hwirq, irq_ctx->work_ctx->pending, state);
84+ if (state)
85+ irq_work_queue(&irq_ctx->work_ctx->work);
86+ }
87+ break;
88+ default:
89+ return -EINVAL;
90+ }
91+
92+ return 0;
93+}
94+
3995 static struct irq_chip irq_sim_irqchip = {
40− .name = "irq_sim",
41− .irq_mask = irq_sim_irqmask,
42− .irq_unmask = irq_sim_irqunmask,
43− .irq_set_type = irq_sim_set_type,
96+ .name = "irq_sim",
97+ .irq_mask = irq_sim_irqmask,
98+ .irq_unmask = irq_sim_irqunmask,
99+ .irq_set_type = irq_sim_set_type,
100+ .irq_get_irqchip_state = irq_sim_get_irqchip_state,
101+ .irq_set_irqchip_state = irq_sim_set_irqchip_state,
44102 };
45103
46104 static void irq_sim_handle_irq(struct irq_work *work)
47105 {
48106 struct irq_sim_work_ctx *work_ctx;
49107 unsigned int offset = 0;
50− struct irq_sim *sim;
51108 int irqnum;
52109
53110 work_ctx = container_of(work, struct irq_sim_work_ctx, work);
54− sim = container_of(work_ctx, struct irq_sim, work_ctx);
55111
56− while (!bitmap_empty(work_ctx->pending, sim->irq_count)) {
112+ while (!bitmap_empty(work_ctx->pending, work_ctx->irq_count)) {
57113 offset = find_next_bit(work_ctx->pending,
58− sim->irq_count, offset);
114+ work_ctx->irq_count, offset);
59115 clear_bit(offset, work_ctx->pending);
60− irqnum = irq_sim_irqnum(sim, offset);
116+ irqnum = irq_find_mapping(work_ctx->domain, offset);
61117 handle_simple_irq(irq_to_desc(irqnum));
62118 }
63119 }
64120
121+static int irq_sim_domain_map(struct irq_domain *domain,
122+ unsigned int virq, irq_hw_number_t hw)
123+{
124+ struct irq_sim_work_ctx *work_ctx = domain->host_data;
125+ struct irq_sim_irq_ctx *irq_ctx;
126+
127+ irq_ctx = kzalloc(sizeof(*irq_ctx), GFP_KERNEL);
128+ if (!irq_ctx)
129+ return -ENOMEM;
130+
131+ irq_set_chip(virq, &irq_sim_irqchip);
132+ irq_set_chip_data(virq, irq_ctx);
133+ irq_set_handler(virq, handle_simple_irq);
134+ irq_modify_status(virq, IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
135+ irq_ctx->work_ctx = work_ctx;
136+
137+ return 0;
138+}
139+
140+static void irq_sim_domain_unmap(struct irq_domain *domain, unsigned int virq)
141+{
142+ struct irq_sim_irq_ctx *irq_ctx;
143+ struct irq_data *irqd;
144+
145+ irqd = irq_domain_get_irq_data(domain, virq);
146+ irq_ctx = irq_data_get_irq_chip_data(irqd);
147+
148+ irq_set_handler(virq, NULL);
149+ irq_domain_reset_irq_data(irqd);
150+ kfree(irq_ctx);
151+}
152+
153+static const struct irq_domain_ops irq_sim_domain_ops = {
154+ .map = irq_sim_domain_map,
155+ .unmap = irq_sim_domain_unmap,
156+};
157+
65158 /**
66− * irq_sim_init - Initialize the interrupt simulator: allocate a range of
67− * dummy interrupts.
159+ * irq_domain_create_sim - Create a new interrupt simulator irq_domain and
160+ * allocate a range of dummy interrupts.
68161 *
69− * @sim: The interrupt simulator object to initialize.
70− * @num_irqs: Number of interrupts to allocate
162+ * @fnode: struct fwnode_handle to be associated with this domain.
163+ * @num_irqs: Number of interrupts to allocate.
71164 *
72− * On success: return the base of the allocated interrupt range.
73− * On failure: a negative errno.
165+ * On success: return a new irq_domain object.
166+ * On failure: a negative errno wrapped with ERR_PTR().
74167 */
75−int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs)
168+struct irq_domain *irq_domain_create_sim(struct fwnode_handle *fwnode,
169+ unsigned int num_irqs)
76170 {
77− int i;
171+ struct irq_sim_work_ctx *work_ctx;
78172
79− sim->irqs = kmalloc_array(num_irqs, sizeof(*sim->irqs), GFP_KERNEL);
80− if (!sim->irqs)
81− return -ENOMEM;
173+ work_ctx = kmalloc(sizeof(*work_ctx), GFP_KERNEL);
174+ if (!work_ctx)
175+ goto err_out;
82176
83− sim->irq_base = irq_alloc_descs(-1, 0, num_irqs, 0);
84− if (sim->irq_base < 0) {
85− kfree(sim->irqs);
86− return sim->irq_base;
87− }
177+ work_ctx->pending = bitmap_zalloc(num_irqs, GFP_KERNEL);
178+ if (!work_ctx->pending)
179+ goto err_free_work_ctx;
88180
89− sim->work_ctx.pending = bitmap_zalloc(num_irqs, GFP_KERNEL);
90− if (!sim->work_ctx.pending) {
91− kfree(sim->irqs);
92− irq_free_descs(sim->irq_base, num_irqs);
93− return -ENOMEM;
94− }
181+ work_ctx->domain = irq_domain_create_linear(fwnode, num_irqs,
182+ &irq_sim_domain_ops,
183+ work_ctx);
184+ if (!work_ctx->domain)
185+ goto err_free_bitmap;
95186
96− for (i = 0; i < num_irqs; i++) {
97− sim->irqs[i].irqnum = sim->irq_base + i;
98− sim->irqs[i].enabled = false;
99− irq_set_chip(sim->irq_base + i, &irq_sim_irqchip);
100− irq_set_chip_data(sim->irq_base + i, &sim->irqs[i]);
101− irq_set_handler(sim->irq_base + i, &handle_simple_irq);
102− irq_modify_status(sim->irq_base + i,
103− IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
104− }
187+ work_ctx->irq_count = num_irqs;
188+ init_irq_work(&work_ctx->work, irq_sim_handle_irq);
105189
106− init_irq_work(&sim->work_ctx.work, irq_sim_handle_irq);
107− sim->irq_count = num_irqs;
190+ return work_ctx->domain;
108191
109− return sim->irq_base;
192+err_free_bitmap:
193+ bitmap_free(work_ctx->pending);
194+err_free_work_ctx:
195+ kfree(work_ctx);
196+err_out:
197+ return ERR_PTR(-ENOMEM);
110198 }
111−EXPORT_SYMBOL_GPL(irq_sim_init);
199+EXPORT_SYMBOL_GPL(irq_domain_create_sim);
112200
113201 /**
114− * irq_sim_fini - Deinitialize the interrupt simulator: free the interrupt
115− * descriptors and allocated memory.
202+ * irq_domain_remove_sim - Deinitialize the interrupt simulator domain: free
203+ * the interrupt descriptors and allocated memory.
116204 *
117− * @sim: The interrupt simulator to tear down.
205+ * @domain: The interrupt simulator domain to tear down.
118206 */
119−void irq_sim_fini(struct irq_sim *sim)
207+void irq_domain_remove_sim(struct irq_domain *domain)
120208 {
121− irq_work_sync(&sim->work_ctx.work);
122− bitmap_free(sim->work_ctx.pending);
123− irq_free_descs(sim->irq_base, sim->irq_count);
124− kfree(sim->irqs);
209+ struct irq_sim_work_ctx *work_ctx = domain->host_data;
210+
211+ irq_work_sync(&work_ctx->work);
212+ bitmap_free(work_ctx->pending);
213+ kfree(work_ctx);
214+
215+ irq_domain_remove(domain);
125216 }
126−EXPORT_SYMBOL_GPL(irq_sim_fini);
217+EXPORT_SYMBOL_GPL(irq_domain_remove_sim);
127218
128−static void devm_irq_sim_release(struct device *dev, void *res)
219+static void devm_irq_domain_release_sim(struct device *dev, void *res)
129220 {
130221 struct irq_sim_devres *this = res;
131222
132− irq_sim_fini(this->sim);
223+ irq_domain_remove_sim(this->domain);
133224 }
134225
135226 /**
136− * irq_sim_init - Initialize the interrupt simulator for a managed device.
227+ * devm_irq_domain_create_sim - Create a new interrupt simulator for
228+ * a managed device.
137229 *
138230 * @dev: Device to initialize the simulator object for.
139− * @sim: The interrupt simulator object to initialize.
231+ * @fnode: struct fwnode_handle to be associated with this domain.
140232 * @num_irqs: Number of interrupts to allocate
141233 *
142− * On success: return the base of the allocated interrupt range.
143− * On failure: a negative errno.
234+ * On success: return a new irq_domain object.
235+ * On failure: a negative errno wrapped with ERR_PTR().
144236 */
145−int devm_irq_sim_init(struct device *dev, struct irq_sim *sim,
146− unsigned int num_irqs)
237+struct irq_domain *devm_irq_domain_create_sim(struct device *dev,
238+ struct fwnode_handle *fwnode,
239+ unsigned int num_irqs)
147240 {
148241 struct irq_sim_devres *dr;
149− int rv;
150242
151− dr = devres_alloc(devm_irq_sim_release, sizeof(*dr), GFP_KERNEL);
243+ dr = devres_alloc(devm_irq_domain_release_sim,
244+ sizeof(*dr), GFP_KERNEL);
152245 if (!dr)
153− return -ENOMEM;
246+ return ERR_PTR(-ENOMEM);
154247
155− rv = irq_sim_init(sim, num_irqs);
156− if (rv < 0) {
248+ dr->domain = irq_domain_create_sim(fwnode, num_irqs);
249+ if (IS_ERR(dr->domain)) {
157250 devres_free(dr);
158− return rv;
251+ return dr->domain;
159252 }
160253
161− dr->sim = sim;
162254 devres_add(dev, dr);
163−
164− return rv;
165−}
166−EXPORT_SYMBOL_GPL(devm_irq_sim_init);
167−
168−/**
169− * irq_sim_fire - Enqueue an interrupt.
170− *
171− * @sim: The interrupt simulator object.
172− * @offset: Offset of the simulated interrupt which should be fired.
173− */
174−void irq_sim_fire(struct irq_sim *sim, unsigned int offset)
175−{
176− if (sim->irqs[offset].enabled) {
177− set_bit(offset, sim->work_ctx.pending);
178− irq_work_queue(&sim->work_ctx.work);
179− }
180−}
181−EXPORT_SYMBOL_GPL(irq_sim_fire);
182−
183−/**
184− * irq_sim_irqnum - Get the allocated number of a dummy interrupt.
185− *
186− * @sim: The interrupt simulator object.
187− * @offset: Offset of the simulated interrupt for which to retrieve
188− * the number.
189− */
190−int irq_sim_irqnum(struct irq_sim *sim, unsigned int offset)
191−{
192− return sim->irqs[offset].irqnum;
255+ return dr->domain;
193256 }
194−EXPORT_SYMBOL_GPL(irq_sim_irqnum);
257+EXPORT_SYMBOL_GPL(devm_irq_domain_create_sim);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t