mirror of https://gitee.com/openkylin/linux.git
powerpc: Make IRQ_NOREQUEST last to clear, first to set
When creating an irq, don't allow a concurent driver request until we have caled map, which will likley call set_chip_and_handler to change the irq_chip and its operations. Similarly, when tearing down an IRQ, make sure no new uses come along while we change the irq back to the nop chip and then reset the descriptor to freed status. Signed-off-by: Milton Miller <miltonm@bga.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
1e8c23013e
commit
41fb5e6260
|
@ -586,14 +586,14 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
|
||||||
irq_map[i].host = host;
|
irq_map[i].host = host;
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
|
|
||||||
/* Clear norequest flags */
|
|
||||||
irq_clear_status_flags(i, IRQ_NOREQUEST);
|
|
||||||
|
|
||||||
/* Legacy flags are left to default at this point,
|
/* Legacy flags are left to default at this point,
|
||||||
* one can then use irq_create_mapping() to
|
* one can then use irq_create_mapping() to
|
||||||
* explicitly change them
|
* explicitly change them
|
||||||
*/
|
*/
|
||||||
ops->map(host, i, i);
|
ops->map(host, i, i);
|
||||||
|
|
||||||
|
/* Clear norequest flags */
|
||||||
|
irq_clear_status_flags(i, IRQ_NOREQUEST);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IRQ_HOST_MAP_LINEAR:
|
case IRQ_HOST_MAP_LINEAR:
|
||||||
|
@ -664,8 +664,6 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq_clear_status_flags(virq, IRQ_NOREQUEST);
|
|
||||||
|
|
||||||
/* map it */
|
/* map it */
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
irq_map[virq].hwirq = hwirq;
|
irq_map[virq].hwirq = hwirq;
|
||||||
|
@ -676,6 +674,8 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,
|
||||||
goto errdesc;
|
goto errdesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
irq_clear_status_flags(virq, IRQ_NOREQUEST);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
errdesc:
|
errdesc:
|
||||||
|
@ -819,6 +819,8 @@ void irq_dispose_mapping(unsigned int virq)
|
||||||
if (host->revmap_type == IRQ_HOST_MAP_LEGACY)
|
if (host->revmap_type == IRQ_HOST_MAP_LEGACY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
irq_set_status_flags(virq, IRQ_NOREQUEST);
|
||||||
|
|
||||||
/* remove chip and handler */
|
/* remove chip and handler */
|
||||||
irq_set_chip_and_handler(virq, NULL, NULL);
|
irq_set_chip_and_handler(virq, NULL, NULL);
|
||||||
|
|
||||||
|
@ -848,8 +850,6 @@ void irq_dispose_mapping(unsigned int virq)
|
||||||
smp_mb();
|
smp_mb();
|
||||||
irq_map[virq].hwirq = host->inval_irq;
|
irq_map[virq].hwirq = host->inval_irq;
|
||||||
|
|
||||||
irq_set_status_flags(virq, IRQ_NOREQUEST);
|
|
||||||
|
|
||||||
irq_free_descs(virq, 1);
|
irq_free_descs(virq, 1);
|
||||||
/* Free it */
|
/* Free it */
|
||||||
irq_free_virt(virq, 1);
|
irq_free_virt(virq, 1);
|
||||||
|
|
Loading…
Reference in New Issue