mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
Merge branch 'irq/urgent' into irq/drivers
to synchronize upstream fixes on which other changes depend on.
This commit is contained in:
commit
b257e70892
|
|
@ -85,10 +85,3 @@ static int __init ar79_cpu_intc_of_init(
|
|||
}
|
||||
IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc",
|
||||
ar79_cpu_intc_of_init);
|
||||
|
||||
void __init ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3)
|
||||
{
|
||||
irq_wb_chan[2] = irq_wb_chan2;
|
||||
irq_wb_chan[3] = irq_wb_chan3;
|
||||
mips_cpu_irq_init();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -929,14 +929,15 @@ static void gicv5_its_free_eventid(struct gicv5_its_dev *its_dev, u32 event_id_b
|
|||
static int gicv5_its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
|
||||
unsigned int nr_irqs, void *arg)
|
||||
{
|
||||
u32 device_id, event_id_base, lpi;
|
||||
struct gicv5_its_dev *its_dev;
|
||||
u32 device_id, event_id_base;
|
||||
msi_alloc_info_t *info = arg;
|
||||
irq_hw_number_t hwirq;
|
||||
struct irq_data *irqd;
|
||||
int ret, i;
|
||||
|
||||
its_dev = info->scratchpad[0].ptr;
|
||||
device_id = its_dev->device_id;
|
||||
|
||||
ret = gicv5_its_alloc_eventid(its_dev, info, nr_irqs, &event_id_base);
|
||||
if (ret)
|
||||
|
|
@ -946,22 +947,11 @@ static int gicv5_its_irq_domain_alloc(struct irq_domain *domain, unsigned int vi
|
|||
if (ret)
|
||||
goto out_eventid;
|
||||
|
||||
device_id = its_dev->device_id;
|
||||
ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, NULL);
|
||||
if (ret)
|
||||
goto out_eventid;
|
||||
|
||||
for (i = 0; i < nr_irqs; i++) {
|
||||
ret = gicv5_alloc_lpi();
|
||||
if (ret < 0) {
|
||||
pr_debug("Failed to find free LPI!\n");
|
||||
goto out_free_irqs;
|
||||
}
|
||||
lpi = ret;
|
||||
|
||||
ret = irq_domain_alloc_irqs_parent(domain, virq + i, 1, &lpi);
|
||||
if (ret) {
|
||||
gicv5_free_lpi(lpi);
|
||||
goto out_free_irqs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store eventid and deviceid into the hwirq for later use.
|
||||
*
|
||||
|
|
@ -980,13 +970,6 @@ static int gicv5_its_irq_domain_alloc(struct irq_domain *domain, unsigned int vi
|
|||
|
||||
return 0;
|
||||
|
||||
out_free_irqs:
|
||||
while (--i >= 0) {
|
||||
irqd = irq_domain_get_irq_data(domain, virq + i);
|
||||
gicv5_free_lpi(irqd->parent_data->hwirq);
|
||||
irq_domain_reset_irq_data(irqd);
|
||||
irq_domain_free_irqs_parent(domain, virq + i, 1);
|
||||
}
|
||||
out_eventid:
|
||||
gicv5_its_free_eventid(its_dev, event_id_base, nr_irqs);
|
||||
return ret;
|
||||
|
|
@ -1009,15 +992,14 @@ static void gicv5_its_irq_domain_free(struct irq_domain *domain, unsigned int vi
|
|||
bitmap_release_region(its_dev->event_map, event_id_base,
|
||||
get_count_order(nr_irqs));
|
||||
|
||||
/* Hierarchically free irq data */
|
||||
for (i = 0; i < nr_irqs; i++) {
|
||||
d = irq_domain_get_irq_data(domain, virq + i);
|
||||
|
||||
gicv5_free_lpi(d->parent_data->hwirq);
|
||||
irq_domain_reset_irq_data(d);
|
||||
irq_domain_free_irqs_parent(domain, virq + i, 1);
|
||||
}
|
||||
|
||||
/* Hierarchically free irq data */
|
||||
irq_domain_free_irqs_parent(domain, virq, nr_irqs);
|
||||
|
||||
gicv5_its_syncr(its, its_dev);
|
||||
gicv5_irs_syncr();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,16 +59,6 @@ static void release_lpi(u32 lpi)
|
|||
ida_free(&lpi_ida, lpi);
|
||||
}
|
||||
|
||||
int gicv5_alloc_lpi(void)
|
||||
{
|
||||
return alloc_lpi();
|
||||
}
|
||||
|
||||
void gicv5_free_lpi(u32 lpi)
|
||||
{
|
||||
release_lpi(lpi);
|
||||
}
|
||||
|
||||
static void gicv5_ppi_priority_init(void)
|
||||
{
|
||||
write_sysreg_s(REPEAT_BYTE(GICV5_IRQ_PRI_MI), SYS_ICC_PPI_PRIORITYR0_EL1);
|
||||
|
|
@ -806,38 +796,64 @@ static void gicv5_lpi_config_reset(struct irq_data *d)
|
|||
gicv5_lpi_irq_write_pending_state(d, false);
|
||||
}
|
||||
|
||||
static void gicv5_irq_lpi_domain_free(struct irq_domain *domain, unsigned int virq,
|
||||
unsigned int nr_irqs)
|
||||
{
|
||||
struct irq_data *d;
|
||||
|
||||
for (unsigned int i = 0; i < nr_irqs; i++, virq++) {
|
||||
d = irq_domain_get_irq_data(domain, virq);
|
||||
|
||||
release_lpi(d->hwirq);
|
||||
|
||||
irq_set_handler(virq, NULL);
|
||||
irq_domain_reset_irq_data(d);
|
||||
}
|
||||
}
|
||||
|
||||
static int gicv5_irq_lpi_domain_alloc(struct irq_domain *domain, unsigned int virq,
|
||||
unsigned int nr_irqs, void *arg)
|
||||
{
|
||||
irq_hw_number_t hwirq;
|
||||
struct irq_data *irqd;
|
||||
u32 *lpi = arg;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON_ONCE(nr_irqs != 1))
|
||||
return -EINVAL;
|
||||
for (i = 0; i < nr_irqs; i++) {
|
||||
ret = alloc_lpi();
|
||||
if (ret < 0)
|
||||
goto out_free_lpis;
|
||||
hwirq = ret;
|
||||
|
||||
hwirq = *lpi;
|
||||
ret = gicv5_irs_iste_alloc(hwirq);
|
||||
if (ret < 0) {
|
||||
/* Undo partial state first, then clean up the rest */
|
||||
release_lpi(hwirq);
|
||||
goto out_free_lpis;
|
||||
}
|
||||
|
||||
irqd = irq_domain_get_irq_data(domain, virq);
|
||||
irqd = irq_domain_get_irq_data(domain, virq + i);
|
||||
|
||||
irq_domain_set_info(domain, virq, hwirq, &gicv5_lpi_irq_chip, NULL,
|
||||
handle_fasteoi_irq, NULL, NULL);
|
||||
irqd_set_single_target(irqd);
|
||||
irq_domain_set_info(domain, virq + i, hwirq, &gicv5_lpi_irq_chip,
|
||||
NULL, handle_fasteoi_irq, NULL, NULL);
|
||||
irqd_set_single_target(irqd);
|
||||
|
||||
ret = gicv5_irs_iste_alloc(hwirq);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
gicv5_hwirq_init(hwirq, GICV5_IRQ_PRI_MI, GICV5_HWIRQ_TYPE_LPI);
|
||||
gicv5_lpi_config_reset(irqd);
|
||||
gicv5_hwirq_init(hwirq, GICV5_IRQ_PRI_MI, GICV5_HWIRQ_TYPE_LPI);
|
||||
gicv5_lpi_config_reset(irqd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_lpis:
|
||||
if (i)
|
||||
gicv5_irq_lpi_domain_free(domain, virq, i);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops gicv5_irq_lpi_domain_ops = {
|
||||
.alloc = gicv5_irq_lpi_domain_alloc,
|
||||
.free = gicv5_irq_domain_free,
|
||||
.free = gicv5_irq_lpi_domain_free,
|
||||
};
|
||||
|
||||
void __init gicv5_init_lpi_domain(void)
|
||||
|
|
@ -858,30 +874,21 @@ static int gicv5_irq_ipi_domain_alloc(struct irq_domain *domain, unsigned int vi
|
|||
unsigned int nr_irqs, void *arg)
|
||||
{
|
||||
struct irq_data *irqd;
|
||||
int ret, i;
|
||||
u32 lpi;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < nr_irqs; i++) {
|
||||
ret = gicv5_alloc_lpi();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
lpi = ret;
|
||||
for (unsigned int i = 0; i < nr_irqs; i++, virq++) {
|
||||
irqd = irq_domain_get_irq_data(domain, virq);
|
||||
|
||||
ret = irq_domain_alloc_irqs_parent(domain, virq + i, 1, &lpi);
|
||||
if (ret) {
|
||||
gicv5_free_lpi(lpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
irqd = irq_domain_get_irq_data(domain, virq + i);
|
||||
|
||||
irq_domain_set_hwirq_and_chip(domain, virq + i, i,
|
||||
&gicv5_ipi_irq_chip, NULL);
|
||||
irq_domain_set_hwirq_and_chip(domain, virq, i,
|
||||
&gicv5_ipi_irq_chip, NULL);
|
||||
|
||||
irqd_set_single_target(irqd);
|
||||
|
||||
irq_set_handler(virq + i, handle_percpu_irq);
|
||||
irq_set_handler(virq, handle_percpu_irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -899,12 +906,11 @@ static void gicv5_irq_ipi_domain_free(struct irq_domain *domain, unsigned int vi
|
|||
if (!d)
|
||||
return;
|
||||
|
||||
gicv5_free_lpi(d->parent_data->hwirq);
|
||||
|
||||
irq_set_handler(virq + i, NULL);
|
||||
irq_domain_reset_irq_data(d);
|
||||
irq_domain_free_irqs_parent(domain, virq + i, 1);
|
||||
}
|
||||
|
||||
irq_domain_free_irqs_parent(domain, virq, nr_irqs);
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops gicv5_irq_ipi_domain_ops = {
|
||||
|
|
|
|||
|
|
@ -415,8 +415,7 @@ static int meson_s4_gpio_irq_set_type(struct meson_gpio_irq_controller *ctl,
|
|||
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
|
||||
val |= BIT(ctl->params->edge_single_offset + idx);
|
||||
|
||||
meson_gpio_irq_update_bits(ctl, params->edge_pol_reg,
|
||||
BIT(idx) | BIT(12 + idx), val);
|
||||
meson_gpio_irq_update_bits(ctl, REG_EDGE_POL, BIT(idx) | BIT(12 + idx), val);
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -425,9 +425,6 @@ struct gicv5_its_itt_cfg {
|
|||
void gicv5_init_lpis(u32 max);
|
||||
void gicv5_deinit_lpis(void);
|
||||
|
||||
int gicv5_alloc_lpi(void);
|
||||
void gicv5_free_lpi(u32 lpi);
|
||||
|
||||
void __init gicv5_its_of_probe(struct device_node *parent);
|
||||
void __init gicv5_its_acpi_probe(void);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include <trace/events/irq.h>
|
||||
|
|
@ -893,7 +894,10 @@ void handle_percpu_irq(struct irq_desc *desc)
|
|||
*
|
||||
* action->percpu_dev_id is a pointer to percpu variables which
|
||||
* contain the real device id for the cpu on which this handler is
|
||||
* called
|
||||
* called.
|
||||
*
|
||||
* May be used for NMI interrupt lines, and so may be called in IRQ or NMI
|
||||
* context.
|
||||
*/
|
||||
void handle_percpu_devid_irq(struct irq_desc *desc)
|
||||
{
|
||||
|
|
@ -930,7 +934,8 @@ void handle_percpu_devid_irq(struct irq_desc *desc)
|
|||
enabled ? " and unmasked" : "", irq, cpu);
|
||||
}
|
||||
|
||||
add_interrupt_randomness(irq);
|
||||
if (!in_nmi())
|
||||
add_interrupt_randomness(irq);
|
||||
|
||||
if (chip->irq_eoi)
|
||||
chip->irq_eoi(&desc->irq_data);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user