diff options
| -rw-r--r-- | kernel/irq/manage.c | 63 |
1 files changed, 53 insertions, 10 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 5624b2dd6b58..1d1a5b945ab4 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
| @@ -1090,6 +1090,16 @@ setup_irq_thread(struct irqaction *new, unsigned int irq, bool secondary) | |||
| 1090 | /* | 1090 | /* |
| 1091 | * Internal function to register an irqaction - typically used to | 1091 | * Internal function to register an irqaction - typically used to |
| 1092 | * allocate special interrupts that are part of the architecture. | 1092 | * allocate special interrupts that are part of the architecture. |
| 1093 | * | ||
| 1094 | * Locking rules: | ||
| 1095 | * | ||
| 1096 | * desc->request_mutex Provides serialization against a concurrent free_irq() | ||
| 1097 | * chip_bus_lock Provides serialization for slow bus operations | ||
| 1098 | * desc->lock Provides serialization against hard interrupts | ||
| 1099 | * | ||
| 1100 | * chip_bus_lock and desc->lock are sufficient for all other management and | ||
| 1101 | * interrupt related functions. desc->request_mutex solely serializes | ||
| 1102 | * request/free_irq(). | ||
| 1093 | */ | 1103 | */ |
| 1094 | static int | 1104 | static int |
| 1095 | __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | 1105 | __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) |
| @@ -1167,20 +1177,35 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 1167 | if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) | 1177 | if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) |
| 1168 | new->flags &= ~IRQF_ONESHOT; | 1178 | new->flags &= ~IRQF_ONESHOT; |
| 1169 | 1179 | ||
| 1180 | /* | ||
| 1181 | * Protects against a concurrent __free_irq() call which might wait | ||
| 1182 | * for synchronize_irq() to complete without holding the optional | ||
| 1183 | * chip bus lock and desc->lock. | ||
| 1184 | */ | ||
| 1170 | mutex_lock(&desc->request_mutex); | 1185 | mutex_lock(&desc->request_mutex); |
| 1186 | |||
| 1187 | /* | ||
| 1188 | * Acquire bus lock as the irq_request_resources() callback below | ||
| 1189 | * might rely on the serialization or the magic power management | ||
| 1190 | * functions which are abusing the irq_bus_lock() callback, | ||
| 1191 | */ | ||
| 1192 | chip_bus_lock(desc); | ||
| 1193 | |||
| 1194 | /* First installed action requests resources. */ | ||
| 1171 | if (!desc->action) { | 1195 | if (!desc->action) { |
| 1172 | ret = irq_request_resources(desc); | 1196 | ret = irq_request_resources(desc); |
| 1173 | if (ret) { | 1197 | if (ret) { |
| 1174 | pr_err("Failed to request resources for %s (irq %d) on irqchip %s\n", | 1198 | pr_err("Failed to request resources for %s (irq %d) on irqchip %s\n", |
| 1175 | new->name, irq, desc->irq_data.chip->name); | 1199 | new->name, irq, desc->irq_data.chip->name); |
| 1176 | goto out_mutex; | 1200 | goto out_bus_unlock; |
| 1177 | } | 1201 | } |
| 1178 | } | 1202 | } |
| 1179 | 1203 | ||
| 1180 | chip_bus_lock(desc); | ||
| 1181 | |||
| 1182 | /* | 1204 | /* |
| 1183 | * The following block of code has to be executed atomically | 1205 | * The following block of code has to be executed atomically |
| 1206 | * protected against a concurrent interrupt and any of the other | ||
| 1207 | * management calls which are not serialized via | ||
| 1208 | * desc->request_mutex or the optional bus lock. | ||
| 1184 | */ | 1209 | */ |
| 1185 | raw_spin_lock_irqsave(&desc->lock, flags); | 1210 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 1186 | old_ptr = &desc->action; | 1211 | old_ptr = &desc->action; |
| @@ -1286,10 +1311,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 1286 | ret = __irq_set_trigger(desc, | 1311 | ret = __irq_set_trigger(desc, |
| 1287 | new->flags & IRQF_TRIGGER_MASK); | 1312 | new->flags & IRQF_TRIGGER_MASK); |
| 1288 | 1313 | ||
| 1289 | if (ret) { | 1314 | if (ret) |
| 1290 | irq_release_resources(desc); | ||
| 1291 | goto out_unlock; | 1315 | goto out_unlock; |
| 1292 | } | ||
| 1293 | } | 1316 | } |
| 1294 | 1317 | ||
| 1295 | desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \ | 1318 | desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \ |
| @@ -1385,12 +1408,10 @@ mismatch: | |||
| 1385 | out_unlock: | 1408 | out_unlock: |
| 1386 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 1409 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 1387 | 1410 | ||
| 1388 | chip_bus_sync_unlock(desc); | ||
| 1389 | |||
| 1390 | if (!desc->action) | 1411 | if (!desc->action) |
| 1391 | irq_release_resources(desc); | 1412 | irq_release_resources(desc); |
| 1392 | 1413 | out_bus_unlock: | |
| 1393 | out_mutex: | 1414 | chip_bus_sync_unlock(desc); |
| 1394 | mutex_unlock(&desc->request_mutex); | 1415 | mutex_unlock(&desc->request_mutex); |
| 1395 | 1416 | ||
| 1396 | out_thread: | 1417 | out_thread: |
| @@ -1472,6 +1493,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id) | |||
| 1472 | WARN(1, "Trying to free already-free IRQ %d\n", irq); | 1493 | WARN(1, "Trying to free already-free IRQ %d\n", irq); |
| 1473 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 1494 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 1474 | chip_bus_sync_unlock(desc); | 1495 | chip_bus_sync_unlock(desc); |
| 1496 | mutex_unlock(&desc->request_mutex); | ||
| 1475 | return NULL; | 1497 | return NULL; |
| 1476 | } | 1498 | } |
| 1477 | 1499 | ||
| @@ -1498,6 +1520,20 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id) | |||
| 1498 | #endif | 1520 | #endif |
| 1499 | 1521 | ||
| 1500 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 1522 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 1523 | /* | ||
| 1524 | * Drop bus_lock here so the changes which were done in the chip | ||
| 1525 | * callbacks above are synced out to the irq chips which hang | ||
| 1526 | * behind a slow bus (I2C, SPI) before calling synchronize_irq(). | ||
| 1527 | * | ||
| 1528 | * Aside of that the bus_lock can also be taken from the threaded | ||
| 1529 | * handler in irq_finalize_oneshot() which results in a deadlock | ||
| 1530 | * because synchronize_irq() would wait forever for the thread to | ||
| 1531 | * complete, which is blocked on the bus lock. | ||
| 1532 | * | ||
| 1533 | * The still held desc->request_mutex() protects against a | ||
| 1534 | * concurrent request_irq() of this irq so the release of resources | ||
| 1535 | * and timing data is properly serialized. | ||
| 1536 | */ | ||
| 1501 | chip_bus_sync_unlock(desc); | 1537 | chip_bus_sync_unlock(desc); |
| 1502 | 1538 | ||
| 1503 | unregister_handler_proc(irq, action); | 1539 | unregister_handler_proc(irq, action); |
| @@ -1530,8 +1566,15 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id) | |||
| 1530 | } | 1566 | } |
| 1531 | } | 1567 | } |
| 1532 | 1568 | ||
| 1569 | /* Last action releases resources */ | ||
| 1533 | if (!desc->action) { | 1570 | if (!desc->action) { |
| 1571 | /* | ||
| 1572 | * Reaquire bus lock as irq_release_resources() might | ||
| 1573 | * require it to deallocate resources over the slow bus. | ||
| 1574 | */ | ||
| 1575 | chip_bus_lock(desc); | ||
| 1534 | irq_release_resources(desc); | 1576 | irq_release_resources(desc); |
| 1577 | chip_bus_sync_unlock(desc); | ||
| 1535 | irq_remove_timings(desc); | 1578 | irq_remove_timings(desc); |
| 1536 | } | 1579 | } |
| 1537 | 1580 | ||
