diff options
author | Jiri Kosina <jkosina@suse.cz> | 2011-11-13 14:55:35 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-11-13 14:55:53 -0500 |
commit | 2290c0d06d82faee87b1ab2d9d4f7bf81ef64379 (patch) | |
tree | e075e4d5534193f28e6059904f61e5ca03958d3c /kernel/irq/manage.c | |
parent | 4da669a2e3e5bc70b30a0465f3641528681b5f77 (diff) | |
parent | 52e4c2a05256cb83cda12f3c2137ab1533344edb (diff) |
Merge branch 'master' into for-next
Sync with Linus tree to have 157550ff ("mtd: add GPMI-NAND driver
in the config and Makefile") as I have patch depending on that one.
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r-- | kernel/irq/manage.c | 218 |
1 files changed, 209 insertions, 9 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 3261c4d478a2..63c16254e449 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -195,7 +195,7 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *mask) | |||
195 | int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m) | 195 | int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m) |
196 | { | 196 | { |
197 | unsigned long flags; | 197 | unsigned long flags; |
198 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); | 198 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); |
199 | 199 | ||
200 | if (!desc) | 200 | if (!desc) |
201 | return -EINVAL; | 201 | return -EINVAL; |
@@ -356,7 +356,7 @@ void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend) | |||
356 | static int __disable_irq_nosync(unsigned int irq) | 356 | static int __disable_irq_nosync(unsigned int irq) |
357 | { | 357 | { |
358 | unsigned long flags; | 358 | unsigned long flags; |
359 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); | 359 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); |
360 | 360 | ||
361 | if (!desc) | 361 | if (!desc) |
362 | return -EINVAL; | 362 | return -EINVAL; |
@@ -448,7 +448,7 @@ void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume) | |||
448 | void enable_irq(unsigned int irq) | 448 | void enable_irq(unsigned int irq) |
449 | { | 449 | { |
450 | unsigned long flags; | 450 | unsigned long flags; |
451 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); | 451 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); |
452 | 452 | ||
453 | if (!desc) | 453 | if (!desc) |
454 | return; | 454 | return; |
@@ -467,6 +467,9 @@ static int set_irq_wake_real(unsigned int irq, unsigned int on) | |||
467 | struct irq_desc *desc = irq_to_desc(irq); | 467 | struct irq_desc *desc = irq_to_desc(irq); |
468 | int ret = -ENXIO; | 468 | int ret = -ENXIO; |
469 | 469 | ||
470 | if (irq_desc_get_chip(desc)->flags & IRQCHIP_SKIP_SET_WAKE) | ||
471 | return 0; | ||
472 | |||
470 | if (desc->irq_data.chip->irq_set_wake) | 473 | if (desc->irq_data.chip->irq_set_wake) |
471 | ret = desc->irq_data.chip->irq_set_wake(&desc->irq_data, on); | 474 | ret = desc->irq_data.chip->irq_set_wake(&desc->irq_data, on); |
472 | 475 | ||
@@ -488,7 +491,7 @@ static int set_irq_wake_real(unsigned int irq, unsigned int on) | |||
488 | int irq_set_irq_wake(unsigned int irq, unsigned int on) | 491 | int irq_set_irq_wake(unsigned int irq, unsigned int on) |
489 | { | 492 | { |
490 | unsigned long flags; | 493 | unsigned long flags; |
491 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags); | 494 | struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); |
492 | int ret = 0; | 495 | int ret = 0; |
493 | 496 | ||
494 | if (!desc) | 497 | if (!desc) |
@@ -529,7 +532,7 @@ EXPORT_SYMBOL(irq_set_irq_wake); | |||
529 | int can_request_irq(unsigned int irq, unsigned long irqflags) | 532 | int can_request_irq(unsigned int irq, unsigned long irqflags) |
530 | { | 533 | { |
531 | unsigned long flags; | 534 | unsigned long flags; |
532 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags); | 535 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0); |
533 | int canrequest = 0; | 536 | int canrequest = 0; |
534 | 537 | ||
535 | if (!desc) | 538 | if (!desc) |
@@ -1118,6 +1121,8 @@ int setup_irq(unsigned int irq, struct irqaction *act) | |||
1118 | int retval; | 1121 | int retval; |
1119 | struct irq_desc *desc = irq_to_desc(irq); | 1122 | struct irq_desc *desc = irq_to_desc(irq); |
1120 | 1123 | ||
1124 | if (WARN_ON(irq_settings_is_per_cpu_devid(desc))) | ||
1125 | return -EINVAL; | ||
1121 | chip_bus_lock(desc); | 1126 | chip_bus_lock(desc); |
1122 | retval = __setup_irq(irq, desc, act); | 1127 | retval = __setup_irq(irq, desc, act); |
1123 | chip_bus_sync_unlock(desc); | 1128 | chip_bus_sync_unlock(desc); |
@@ -1126,7 +1131,7 @@ int setup_irq(unsigned int irq, struct irqaction *act) | |||
1126 | } | 1131 | } |
1127 | EXPORT_SYMBOL_GPL(setup_irq); | 1132 | EXPORT_SYMBOL_GPL(setup_irq); |
1128 | 1133 | ||
1129 | /* | 1134 | /* |
1130 | * Internal function to unregister an irqaction - used to free | 1135 | * Internal function to unregister an irqaction - used to free |
1131 | * regular and special interrupts that are part of the architecture. | 1136 | * regular and special interrupts that are part of the architecture. |
1132 | */ | 1137 | */ |
@@ -1224,7 +1229,10 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id) | |||
1224 | */ | 1229 | */ |
1225 | void remove_irq(unsigned int irq, struct irqaction *act) | 1230 | void remove_irq(unsigned int irq, struct irqaction *act) |
1226 | { | 1231 | { |
1227 | __free_irq(irq, act->dev_id); | 1232 | struct irq_desc *desc = irq_to_desc(irq); |
1233 | |||
1234 | if (desc && !WARN_ON(irq_settings_is_per_cpu_devid(desc))) | ||
1235 | __free_irq(irq, act->dev_id); | ||
1228 | } | 1236 | } |
1229 | EXPORT_SYMBOL_GPL(remove_irq); | 1237 | EXPORT_SYMBOL_GPL(remove_irq); |
1230 | 1238 | ||
@@ -1246,7 +1254,7 @@ void free_irq(unsigned int irq, void *dev_id) | |||
1246 | { | 1254 | { |
1247 | struct irq_desc *desc = irq_to_desc(irq); | 1255 | struct irq_desc *desc = irq_to_desc(irq); |
1248 | 1256 | ||
1249 | if (!desc) | 1257 | if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc))) |
1250 | return; | 1258 | return; |
1251 | 1259 | ||
1252 | #ifdef CONFIG_SMP | 1260 | #ifdef CONFIG_SMP |
@@ -1324,7 +1332,8 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler, | |||
1324 | if (!desc) | 1332 | if (!desc) |
1325 | return -EINVAL; | 1333 | return -EINVAL; |
1326 | 1334 | ||
1327 | if (!irq_settings_can_request(desc)) | 1335 | if (!irq_settings_can_request(desc) || |
1336 | WARN_ON(irq_settings_is_per_cpu_devid(desc))) | ||
1328 | return -EINVAL; | 1337 | return -EINVAL; |
1329 | 1338 | ||
1330 | if (!handler) { | 1339 | if (!handler) { |
@@ -1409,3 +1418,194 @@ int request_any_context_irq(unsigned int irq, irq_handler_t handler, | |||
1409 | return !ret ? IRQC_IS_HARDIRQ : ret; | 1418 | return !ret ? IRQC_IS_HARDIRQ : ret; |
1410 | } | 1419 | } |
1411 | EXPORT_SYMBOL_GPL(request_any_context_irq); | 1420 | EXPORT_SYMBOL_GPL(request_any_context_irq); |
1421 | |||
1422 | void enable_percpu_irq(unsigned int irq, unsigned int type) | ||
1423 | { | ||
1424 | unsigned int cpu = smp_processor_id(); | ||
1425 | unsigned long flags; | ||
1426 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_PERCPU); | ||
1427 | |||
1428 | if (!desc) | ||
1429 | return; | ||
1430 | |||
1431 | type &= IRQ_TYPE_SENSE_MASK; | ||
1432 | if (type != IRQ_TYPE_NONE) { | ||
1433 | int ret; | ||
1434 | |||
1435 | ret = __irq_set_trigger(desc, irq, type); | ||
1436 | |||
1437 | if (ret) { | ||
1438 | WARN(1, "failed to set type for IRQ%d\n", irq); | ||
1439 | goto out; | ||
1440 | } | ||
1441 | } | ||
1442 | |||
1443 | irq_percpu_enable(desc, cpu); | ||
1444 | out: | ||
1445 | irq_put_desc_unlock(desc, flags); | ||
1446 | } | ||
1447 | |||
1448 | void disable_percpu_irq(unsigned int irq) | ||
1449 | { | ||
1450 | unsigned int cpu = smp_processor_id(); | ||
1451 | unsigned long flags; | ||
1452 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_PERCPU); | ||
1453 | |||
1454 | if (!desc) | ||
1455 | return; | ||
1456 | |||
1457 | irq_percpu_disable(desc, cpu); | ||
1458 | irq_put_desc_unlock(desc, flags); | ||
1459 | } | ||
1460 | |||
1461 | /* | ||
1462 | * Internal function to unregister a percpu irqaction. | ||
1463 | */ | ||
1464 | static struct irqaction *__free_percpu_irq(unsigned int irq, void __percpu *dev_id) | ||
1465 | { | ||
1466 | struct irq_desc *desc = irq_to_desc(irq); | ||
1467 | struct irqaction *action; | ||
1468 | unsigned long flags; | ||
1469 | |||
1470 | WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq); | ||
1471 | |||
1472 | if (!desc) | ||
1473 | return NULL; | ||
1474 | |||
1475 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
1476 | |||
1477 | action = desc->action; | ||
1478 | if (!action || action->percpu_dev_id != dev_id) { | ||
1479 | WARN(1, "Trying to free already-free IRQ %d\n", irq); | ||
1480 | goto bad; | ||
1481 | } | ||
1482 | |||
1483 | if (!cpumask_empty(desc->percpu_enabled)) { | ||
1484 | WARN(1, "percpu IRQ %d still enabled on CPU%d!\n", | ||
1485 | irq, cpumask_first(desc->percpu_enabled)); | ||
1486 | goto bad; | ||
1487 | } | ||
1488 | |||
1489 | /* Found it - now remove it from the list of entries: */ | ||
1490 | desc->action = NULL; | ||
1491 | |||
1492 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
1493 | |||
1494 | unregister_handler_proc(irq, action); | ||
1495 | |||
1496 | module_put(desc->owner); | ||
1497 | return action; | ||
1498 | |||
1499 | bad: | ||
1500 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
1501 | return NULL; | ||
1502 | } | ||
1503 | |||
1504 | /** | ||
1505 | * remove_percpu_irq - free a per-cpu interrupt | ||
1506 | * @irq: Interrupt line to free | ||
1507 | * @act: irqaction for the interrupt | ||
1508 | * | ||
1509 | * Used to remove interrupts statically setup by the early boot process. | ||
1510 | */ | ||
1511 | void remove_percpu_irq(unsigned int irq, struct irqaction *act) | ||
1512 | { | ||
1513 | struct irq_desc *desc = irq_to_desc(irq); | ||
1514 | |||
1515 | if (desc && irq_settings_is_per_cpu_devid(desc)) | ||
1516 | __free_percpu_irq(irq, act->percpu_dev_id); | ||
1517 | } | ||
1518 | |||
1519 | /** | ||
1520 | * free_percpu_irq - free an interrupt allocated with request_percpu_irq | ||
1521 | * @irq: Interrupt line to free | ||
1522 | * @dev_id: Device identity to free | ||
1523 | * | ||
1524 | * Remove a percpu interrupt handler. The handler is removed, but | ||
1525 | * the interrupt line is not disabled. This must be done on each | ||
1526 | * CPU before calling this function. The function does not return | ||
1527 | * until any executing interrupts for this IRQ have completed. | ||
1528 | * | ||
1529 | * This function must not be called from interrupt context. | ||
1530 | */ | ||
1531 | void free_percpu_irq(unsigned int irq, void __percpu *dev_id) | ||
1532 | { | ||
1533 | struct irq_desc *desc = irq_to_desc(irq); | ||
1534 | |||
1535 | if (!desc || !irq_settings_is_per_cpu_devid(desc)) | ||
1536 | return; | ||
1537 | |||
1538 | chip_bus_lock(desc); | ||
1539 | kfree(__free_percpu_irq(irq, dev_id)); | ||
1540 | chip_bus_sync_unlock(desc); | ||
1541 | } | ||
1542 | |||
1543 | /** | ||
1544 | * setup_percpu_irq - setup a per-cpu interrupt | ||
1545 | * @irq: Interrupt line to setup | ||
1546 | * @act: irqaction for the interrupt | ||
1547 | * | ||
1548 | * Used to statically setup per-cpu interrupts in the early boot process. | ||
1549 | */ | ||
1550 | int setup_percpu_irq(unsigned int irq, struct irqaction *act) | ||
1551 | { | ||
1552 | struct irq_desc *desc = irq_to_desc(irq); | ||
1553 | int retval; | ||
1554 | |||
1555 | if (!desc || !irq_settings_is_per_cpu_devid(desc)) | ||
1556 | return -EINVAL; | ||
1557 | chip_bus_lock(desc); | ||
1558 | retval = __setup_irq(irq, desc, act); | ||
1559 | chip_bus_sync_unlock(desc); | ||
1560 | |||
1561 | return retval; | ||
1562 | } | ||
1563 | |||
1564 | /** | ||
1565 | * request_percpu_irq - allocate a percpu interrupt line | ||
1566 | * @irq: Interrupt line to allocate | ||
1567 | * @handler: Function to be called when the IRQ occurs. | ||
1568 | * @devname: An ascii name for the claiming device | ||
1569 | * @dev_id: A percpu cookie passed back to the handler function | ||
1570 | * | ||
1571 | * This call allocates interrupt resources, but doesn't | ||
1572 | * automatically enable the interrupt. It has to be done on each | ||
1573 | * CPU using enable_percpu_irq(). | ||
1574 | * | ||
1575 | * Dev_id must be globally unique. It is a per-cpu variable, and | ||
1576 | * the handler gets called with the interrupted CPU's instance of | ||
1577 | * that variable. | ||
1578 | */ | ||
1579 | int request_percpu_irq(unsigned int irq, irq_handler_t handler, | ||
1580 | const char *devname, void __percpu *dev_id) | ||
1581 | { | ||
1582 | struct irqaction *action; | ||
1583 | struct irq_desc *desc; | ||
1584 | int retval; | ||
1585 | |||
1586 | if (!dev_id) | ||
1587 | return -EINVAL; | ||
1588 | |||
1589 | desc = irq_to_desc(irq); | ||
1590 | if (!desc || !irq_settings_can_request(desc) || | ||
1591 | !irq_settings_is_per_cpu_devid(desc)) | ||
1592 | return -EINVAL; | ||
1593 | |||
1594 | action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); | ||
1595 | if (!action) | ||
1596 | return -ENOMEM; | ||
1597 | |||
1598 | action->handler = handler; | ||
1599 | action->flags = IRQF_PERCPU; | ||
1600 | action->name = devname; | ||
1601 | action->percpu_dev_id = dev_id; | ||
1602 | |||
1603 | chip_bus_lock(desc); | ||
1604 | retval = __setup_irq(irq, desc, action); | ||
1605 | chip_bus_sync_unlock(desc); | ||
1606 | |||
1607 | if (retval) | ||
1608 | kfree(action); | ||
1609 | |||
1610 | return retval; | ||
1611 | } | ||