.. | .. |
---|
282 | 282 | } |
---|
283 | 283 | } |
---|
284 | 284 | if (resend) |
---|
285 | | - check_irq_resend(desc); |
---|
| 285 | + check_irq_resend(desc, false); |
---|
286 | 286 | |
---|
287 | 287 | return ret; |
---|
288 | 288 | } |
---|
.. | .. |
---|
674 | 674 | } |
---|
675 | 675 | EXPORT_SYMBOL_GPL(handle_level_irq); |
---|
676 | 676 | |
---|
677 | | -#ifdef CONFIG_IRQ_PREFLOW_FASTEOI |
---|
678 | | -static inline void preflow_handler(struct irq_desc *desc) |
---|
679 | | -{ |
---|
680 | | - if (desc->preflow_handler) |
---|
681 | | - desc->preflow_handler(&desc->irq_data); |
---|
682 | | -} |
---|
683 | | -#else |
---|
684 | | -static inline void preflow_handler(struct irq_desc *desc) { } |
---|
685 | | -#endif |
---|
686 | | - |
---|
687 | 677 | static void cond_unmask_eoi_irq(struct irq_desc *desc, struct irq_chip *chip) |
---|
688 | 678 | { |
---|
689 | 679 | if (!(desc->istate & IRQS_ONESHOT)) { |
---|
.. | .. |
---|
739 | 729 | if (desc->istate & IRQS_ONESHOT) |
---|
740 | 730 | mask_irq(desc); |
---|
741 | 731 | |
---|
742 | | - preflow_handler(desc); |
---|
743 | 732 | handle_irq_event(desc); |
---|
744 | 733 | |
---|
745 | 734 | cond_unmask_eoi_irq(desc, chip); |
---|
.. | .. |
---|
752 | 741 | raw_spin_unlock(&desc->lock); |
---|
753 | 742 | } |
---|
754 | 743 | EXPORT_SYMBOL_GPL(handle_fasteoi_irq); |
---|
| 744 | + |
---|
| 745 | +/** |
---|
| 746 | + * handle_fasteoi_nmi - irq handler for NMI interrupt lines |
---|
| 747 | + * @desc: the interrupt description structure for this irq |
---|
| 748 | + * |
---|
| 749 | + * A simple NMI-safe handler, considering the restrictions |
---|
| 750 | + * from request_nmi. |
---|
| 751 | + * |
---|
| 752 | + * Only a single callback will be issued to the chip: an ->eoi() |
---|
| 753 | + * call when the interrupt has been serviced. This enables support |
---|
| 754 | + * for modern forms of interrupt handlers, which handle the flow |
---|
| 755 | + * details in hardware, transparently. |
---|
| 756 | + */ |
---|
| 757 | +void handle_fasteoi_nmi(struct irq_desc *desc) |
---|
| 758 | +{ |
---|
| 759 | + struct irq_chip *chip = irq_desc_get_chip(desc); |
---|
| 760 | + struct irqaction *action = desc->action; |
---|
| 761 | + unsigned int irq = irq_desc_get_irq(desc); |
---|
| 762 | + irqreturn_t res; |
---|
| 763 | + |
---|
| 764 | + __kstat_incr_irqs_this_cpu(desc); |
---|
| 765 | + |
---|
| 766 | + trace_irq_handler_entry(irq, action); |
---|
| 767 | + /* |
---|
| 768 | + * NMIs cannot be shared, there is only one action. |
---|
| 769 | + */ |
---|
| 770 | + res = action->handler(irq, action->dev_id); |
---|
| 771 | + trace_irq_handler_exit(irq, action, res); |
---|
| 772 | + |
---|
| 773 | + if (chip->irq_eoi) |
---|
| 774 | + chip->irq_eoi(&desc->irq_data); |
---|
| 775 | +} |
---|
| 776 | +EXPORT_SYMBOL_GPL(handle_fasteoi_nmi); |
---|
755 | 777 | |
---|
756 | 778 | /** |
---|
757 | 779 | * handle_edge_irq - edge type IRQ handler |
---|
.. | .. |
---|
940 | 962 | chip->irq_eoi(&desc->irq_data); |
---|
941 | 963 | } |
---|
942 | 964 | |
---|
| 965 | +/** |
---|
| 966 | + * handle_percpu_devid_fasteoi_ipi - Per CPU local IPI handler with per cpu |
---|
| 967 | + * dev ids |
---|
| 968 | + * @desc: the interrupt description structure for this irq |
---|
| 969 | + * |
---|
| 970 | + * The biggest difference with the IRQ version is that the interrupt is |
---|
| 971 | + * EOIed early, as the IPI could result in a context switch, and we need to |
---|
| 972 | + * make sure the IPI can fire again. We also assume that the arch code has |
---|
| 973 | + * registered an action. If not, we are positively doomed. |
---|
| 974 | + */ |
---|
| 975 | +void handle_percpu_devid_fasteoi_ipi(struct irq_desc *desc) |
---|
| 976 | +{ |
---|
| 977 | + struct irq_chip *chip = irq_desc_get_chip(desc); |
---|
| 978 | + struct irqaction *action = desc->action; |
---|
| 979 | + unsigned int irq = irq_desc_get_irq(desc); |
---|
| 980 | + irqreturn_t res; |
---|
| 981 | + |
---|
| 982 | + __kstat_incr_irqs_this_cpu(desc); |
---|
| 983 | + |
---|
| 984 | + if (chip->irq_eoi) |
---|
| 985 | + chip->irq_eoi(&desc->irq_data); |
---|
| 986 | + |
---|
| 987 | + trace_irq_handler_entry(irq, action); |
---|
| 988 | + res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id)); |
---|
| 989 | + trace_irq_handler_exit(irq, action, res); |
---|
| 990 | +} |
---|
| 991 | + |
---|
| 992 | +/** |
---|
| 993 | + * handle_percpu_devid_fasteoi_nmi - Per CPU local NMI handler with per cpu |
---|
| 994 | + * dev ids |
---|
| 995 | + * @desc: the interrupt description structure for this irq |
---|
| 996 | + * |
---|
| 997 | + * Similar to handle_fasteoi_nmi, but handling the dev_id cookie |
---|
| 998 | + * as a percpu pointer. |
---|
| 999 | + */ |
---|
| 1000 | +void handle_percpu_devid_fasteoi_nmi(struct irq_desc *desc) |
---|
| 1001 | +{ |
---|
| 1002 | + struct irq_chip *chip = irq_desc_get_chip(desc); |
---|
| 1003 | + struct irqaction *action = desc->action; |
---|
| 1004 | + unsigned int irq = irq_desc_get_irq(desc); |
---|
| 1005 | + irqreturn_t res; |
---|
| 1006 | + |
---|
| 1007 | + __kstat_incr_irqs_this_cpu(desc); |
---|
| 1008 | + |
---|
| 1009 | + trace_irq_handler_entry(irq, action); |
---|
| 1010 | + res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id)); |
---|
| 1011 | + trace_irq_handler_exit(irq, action, res); |
---|
| 1012 | + |
---|
| 1013 | + if (chip->irq_eoi) |
---|
| 1014 | + chip->irq_eoi(&desc->irq_data); |
---|
| 1015 | +} |
---|
| 1016 | + |
---|
943 | 1017 | static void |
---|
944 | 1018 | __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, |
---|
945 | 1019 | int is_chained, const char *name) |
---|
.. | .. |
---|
961 | 1035 | break; |
---|
962 | 1036 | /* |
---|
963 | 1037 | * Bail out if the outer chip is not set up |
---|
964 | | - * and the interrrupt supposed to be started |
---|
| 1038 | + * and the interrupt supposed to be started |
---|
965 | 1039 | * right away. |
---|
966 | 1040 | */ |
---|
967 | 1041 | if (WARN_ON(is_chained)) |
---|
.. | .. |
---|
1051 | 1125 | } |
---|
1052 | 1126 | EXPORT_SYMBOL_GPL(irq_set_chip_and_handler_name); |
---|
1053 | 1127 | |
---|
1054 | | -void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) |
---|
| 1128 | +void __irq_modify_status(unsigned int irq, unsigned long clr, |
---|
| 1129 | + unsigned long set, unsigned long mask) |
---|
1055 | 1130 | { |
---|
1056 | 1131 | unsigned long flags, trigger, tmp; |
---|
1057 | 1132 | struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0); |
---|
.. | .. |
---|
1065 | 1140 | */ |
---|
1066 | 1141 | WARN_ON_ONCE(!desc->depth && (set & _IRQ_NOAUTOEN)); |
---|
1067 | 1142 | |
---|
1068 | | - irq_settings_clr_and_set(desc, clr, set); |
---|
| 1143 | + /* Warn when trying to clear or set a bit disallowed by the mask */ |
---|
| 1144 | + WARN_ON((clr | set) & ~mask); |
---|
| 1145 | + __irq_settings_clr_and_set(desc, clr, set, mask); |
---|
1069 | 1146 | |
---|
1070 | 1147 | trigger = irqd_get_trigger_type(&desc->irq_data); |
---|
1071 | 1148 | |
---|
.. | .. |
---|
1087 | 1164 | irqd_set(&desc->irq_data, trigger); |
---|
1088 | 1165 | |
---|
1089 | 1166 | irq_put_desc_unlock(desc, flags); |
---|
| 1167 | +} |
---|
| 1168 | + |
---|
| 1169 | +void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) |
---|
| 1170 | +{ |
---|
| 1171 | + __irq_modify_status(irq, clr, set, _IRQF_MODIFY_MASK); |
---|
1090 | 1172 | } |
---|
1091 | 1173 | EXPORT_SYMBOL_GPL(irq_modify_status); |
---|
1092 | 1174 | |
---|
.. | .. |
---|
1191 | 1273 | /* Start handling the irq */ |
---|
1192 | 1274 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
---|
1193 | 1275 | |
---|
1194 | | - preflow_handler(desc); |
---|
1195 | 1276 | handle_irq_event(desc); |
---|
1196 | 1277 | |
---|
1197 | 1278 | cond_unmask_eoi_irq(desc, chip); |
---|
.. | .. |
---|
1241 | 1322 | if (desc->istate & IRQS_ONESHOT) |
---|
1242 | 1323 | mask_irq(desc); |
---|
1243 | 1324 | |
---|
1244 | | - preflow_handler(desc); |
---|
1245 | 1325 | handle_irq_event(desc); |
---|
1246 | 1326 | |
---|
1247 | 1327 | cond_unmask_eoi_irq(desc, chip); |
---|
.. | .. |
---|
1258 | 1338 | #endif /* CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS */ |
---|
1259 | 1339 | |
---|
1260 | 1340 | /** |
---|
1261 | | - * irq_chip_set_parent_state - set the state of a parent interrupt. |
---|
1262 | | - * @data: Pointer to interrupt specific data |
---|
1263 | | - * @which: State to be restored (one of IRQCHIP_STATE_*) |
---|
1264 | | - * @val: Value corresponding to @which |
---|
| 1341 | + * irq_chip_set_parent_state - set the state of a parent interrupt. |
---|
1265 | 1342 | * |
---|
| 1343 | + * @data: Pointer to interrupt specific data |
---|
| 1344 | + * @which: State to be restored (one of IRQCHIP_STATE_*) |
---|
| 1345 | + * @val: Value corresponding to @which |
---|
| 1346 | + * |
---|
| 1347 | + * Conditional success, if the underlying irqchip does not implement it. |
---|
1266 | 1348 | */ |
---|
1267 | 1349 | int irq_chip_set_parent_state(struct irq_data *data, |
---|
1268 | 1350 | enum irqchip_irq_state which, |
---|
1269 | 1351 | bool val) |
---|
1270 | 1352 | { |
---|
1271 | 1353 | data = data->parent_data; |
---|
1272 | | - if (!data) |
---|
| 1354 | + |
---|
| 1355 | + if (!data || !data->chip->irq_set_irqchip_state) |
---|
1273 | 1356 | return 0; |
---|
1274 | 1357 | |
---|
1275 | | - if (data->chip->irq_set_irqchip_state) |
---|
1276 | | - return data->chip->irq_set_irqchip_state(data, which, val); |
---|
1277 | | - |
---|
1278 | | - return 0; |
---|
| 1358 | + return data->chip->irq_set_irqchip_state(data, which, val); |
---|
1279 | 1359 | } |
---|
1280 | | -EXPORT_SYMBOL(irq_chip_set_parent_state); |
---|
| 1360 | +EXPORT_SYMBOL_GPL(irq_chip_set_parent_state); |
---|
1281 | 1361 | |
---|
1282 | 1362 | /** |
---|
1283 | | - * irq_chip_get_parent_state - get the state of a parent interrupt. |
---|
1284 | | - * @data: Pointer to interrupt specific data |
---|
1285 | | - * @which: one of IRQCHIP_STATE_* the caller wants to know |
---|
1286 | | - * @state: a pointer to a boolean where the state is to be stored |
---|
| 1363 | + * irq_chip_get_parent_state - get the state of a parent interrupt. |
---|
1287 | 1364 | * |
---|
| 1365 | + * @data: Pointer to interrupt specific data |
---|
| 1366 | + * @which: one of IRQCHIP_STATE_* the caller wants to know |
---|
| 1367 | + * @state: a pointer to a boolean where the state is to be stored |
---|
| 1368 | + * |
---|
| 1369 | + * Conditional success, if the underlying irqchip does not implement it. |
---|
1288 | 1370 | */ |
---|
1289 | 1371 | int irq_chip_get_parent_state(struct irq_data *data, |
---|
1290 | 1372 | enum irqchip_irq_state which, |
---|
1291 | 1373 | bool *state) |
---|
1292 | 1374 | { |
---|
1293 | 1375 | data = data->parent_data; |
---|
1294 | | - if (!data) |
---|
| 1376 | + |
---|
| 1377 | + if (!data || !data->chip->irq_get_irqchip_state) |
---|
1295 | 1378 | return 0; |
---|
1296 | 1379 | |
---|
1297 | | - if (data->chip->irq_get_irqchip_state) |
---|
1298 | | - return data->chip->irq_get_irqchip_state(data, which, state); |
---|
1299 | | - |
---|
1300 | | - return 0; |
---|
| 1380 | + return data->chip->irq_get_irqchip_state(data, which, state); |
---|
1301 | 1381 | } |
---|
1302 | | -EXPORT_SYMBOL(irq_chip_get_parent_state); |
---|
| 1382 | +EXPORT_SYMBOL_GPL(irq_chip_get_parent_state); |
---|
1303 | 1383 | |
---|
1304 | 1384 | /** |
---|
1305 | 1385 | * irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if |
---|
.. | .. |
---|
1352 | 1432 | data->chip->irq_mask(data); |
---|
1353 | 1433 | } |
---|
1354 | 1434 | EXPORT_SYMBOL_GPL(irq_chip_mask_parent); |
---|
| 1435 | + |
---|
| 1436 | +/** |
---|
| 1437 | + * irq_chip_mask_ack_parent - Mask and acknowledge the parent interrupt |
---|
| 1438 | + * @data: Pointer to interrupt specific data |
---|
| 1439 | + */ |
---|
| 1440 | +void irq_chip_mask_ack_parent(struct irq_data *data) |
---|
| 1441 | +{ |
---|
| 1442 | + data = data->parent_data; |
---|
| 1443 | + data->chip->irq_mask_ack(data); |
---|
| 1444 | +} |
---|
| 1445 | +EXPORT_SYMBOL_GPL(irq_chip_mask_ack_parent); |
---|
1355 | 1446 | |
---|
1356 | 1447 | /** |
---|
1357 | 1448 | * irq_chip_unmask_parent - Unmask the parent interrupt |
---|
.. | .. |
---|
1443 | 1534 | return -ENOSYS; |
---|
1444 | 1535 | } |
---|
1445 | 1536 | EXPORT_SYMBOL_GPL(irq_chip_set_vcpu_affinity_parent); |
---|
1446 | | - |
---|
1447 | 1537 | /** |
---|
1448 | 1538 | * irq_chip_set_wake_parent - Set/reset wake-up on the parent interrupt |
---|
1449 | 1539 | * @data: Pointer to interrupt specific data |
---|
.. | .. |
---|
1464 | 1554 | return -ENOSYS; |
---|
1465 | 1555 | } |
---|
1466 | 1556 | EXPORT_SYMBOL_GPL(irq_chip_set_wake_parent); |
---|
| 1557 | + |
---|
| 1558 | +/** |
---|
| 1559 | + * irq_chip_request_resources_parent - Request resources on the parent interrupt |
---|
| 1560 | + * @data: Pointer to interrupt specific data |
---|
| 1561 | + */ |
---|
| 1562 | +int irq_chip_request_resources_parent(struct irq_data *data) |
---|
| 1563 | +{ |
---|
| 1564 | + data = data->parent_data; |
---|
| 1565 | + |
---|
| 1566 | + if (data->chip->irq_request_resources) |
---|
| 1567 | + return data->chip->irq_request_resources(data); |
---|
| 1568 | + |
---|
| 1569 | + /* no error on missing optional irq_chip::irq_request_resources */ |
---|
| 1570 | + return 0; |
---|
| 1571 | +} |
---|
| 1572 | +EXPORT_SYMBOL_GPL(irq_chip_request_resources_parent); |
---|
| 1573 | + |
---|
| 1574 | +/** |
---|
| 1575 | + * irq_chip_release_resources_parent - Release resources on the parent interrupt |
---|
| 1576 | + * @data: Pointer to interrupt specific data |
---|
| 1577 | + */ |
---|
| 1578 | +void irq_chip_release_resources_parent(struct irq_data *data) |
---|
| 1579 | +{ |
---|
| 1580 | + data = data->parent_data; |
---|
| 1581 | + if (data->chip->irq_release_resources) |
---|
| 1582 | + data->chip->irq_release_resources(data); |
---|
| 1583 | +} |
---|
| 1584 | +EXPORT_SYMBOL_GPL(irq_chip_release_resources_parent); |
---|
1467 | 1585 | #endif |
---|
1468 | 1586 | |
---|
1469 | 1587 | /** |
---|
.. | .. |
---|
1477 | 1595 | */ |
---|
1478 | 1596 | int irq_chip_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) |
---|
1479 | 1597 | { |
---|
1480 | | - struct irq_data *pos = NULL; |
---|
| 1598 | + struct irq_data *pos; |
---|
1481 | 1599 | |
---|
1482 | | -#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY |
---|
1483 | | - for (; data; data = data->parent_data) |
---|
1484 | | -#endif |
---|
| 1600 | + for (pos = NULL; !pos && data; data = irqd_get_parent_data(data)) { |
---|
1485 | 1601 | if (data->chip && data->chip->irq_compose_msi_msg) |
---|
1486 | 1602 | pos = data; |
---|
| 1603 | + } |
---|
| 1604 | + |
---|
1487 | 1605 | if (!pos) |
---|
1488 | 1606 | return -ENOSYS; |
---|
1489 | 1607 | |
---|
1490 | 1608 | pos->chip->irq_compose_msi_msg(pos, msg); |
---|
1491 | | - |
---|
1492 | 1609 | return 0; |
---|
1493 | 1610 | } |
---|
1494 | 1611 | |
---|