diff options
Diffstat (limited to 'kernel/irq/chip.c')
-rw-r--r-- | kernel/irq/chip.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index a3cc37c0c85e..23958980189d 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -1092,6 +1092,112 @@ void irq_cpu_offline(void) | |||
1092 | } | 1092 | } |
1093 | 1093 | ||
1094 | #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY | 1094 | #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY |
1095 | |||
1096 | #ifdef CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS | ||
1097 | /** | ||
1098 | * handle_fasteoi_ack_irq - irq handler for edge hierarchy | ||
1099 | * stacked on transparent controllers | ||
1100 | * | ||
1101 | * @desc: the interrupt description structure for this irq | ||
1102 | * | ||
1103 | * Like handle_fasteoi_irq(), but for use with hierarchy where | ||
1104 | * the irq_chip also needs to have its ->irq_ack() function | ||
1105 | * called. | ||
1106 | */ | ||
1107 | void handle_fasteoi_ack_irq(struct irq_desc *desc) | ||
1108 | { | ||
1109 | struct irq_chip *chip = desc->irq_data.chip; | ||
1110 | |||
1111 | raw_spin_lock(&desc->lock); | ||
1112 | |||
1113 | if (!irq_may_run(desc)) | ||
1114 | goto out; | ||
1115 | |||
1116 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); | ||
1117 | |||
1118 | /* | ||
1119 | * If its disabled or no action available | ||
1120 | * then mask it and get out of here: | ||
1121 | */ | ||
1122 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) { | ||
1123 | desc->istate |= IRQS_PENDING; | ||
1124 | mask_irq(desc); | ||
1125 | goto out; | ||
1126 | } | ||
1127 | |||
1128 | kstat_incr_irqs_this_cpu(desc); | ||
1129 | if (desc->istate & IRQS_ONESHOT) | ||
1130 | mask_irq(desc); | ||
1131 | |||
1132 | /* Start handling the irq */ | ||
1133 | desc->irq_data.chip->irq_ack(&desc->irq_data); | ||
1134 | |||
1135 | preflow_handler(desc); | ||
1136 | handle_irq_event(desc); | ||
1137 | |||
1138 | cond_unmask_eoi_irq(desc, chip); | ||
1139 | |||
1140 | raw_spin_unlock(&desc->lock); | ||
1141 | return; | ||
1142 | out: | ||
1143 | if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED)) | ||
1144 | chip->irq_eoi(&desc->irq_data); | ||
1145 | raw_spin_unlock(&desc->lock); | ||
1146 | } | ||
1147 | EXPORT_SYMBOL_GPL(handle_fasteoi_ack_irq); | ||
1148 | |||
1149 | /** | ||
1150 | * handle_fasteoi_mask_irq - irq handler for level hierarchy | ||
1151 | * stacked on transparent controllers | ||
1152 | * | ||
1153 | * @desc: the interrupt description structure for this irq | ||
1154 | * | ||
1155 | * Like handle_fasteoi_irq(), but for use with hierarchy where | ||
1156 | * the irq_chip also needs to have its ->irq_mask_ack() function | ||
1157 | * called. | ||
1158 | */ | ||
1159 | void handle_fasteoi_mask_irq(struct irq_desc *desc) | ||
1160 | { | ||
1161 | struct irq_chip *chip = desc->irq_data.chip; | ||
1162 | |||
1163 | raw_spin_lock(&desc->lock); | ||
1164 | mask_ack_irq(desc); | ||
1165 | |||
1166 | if (!irq_may_run(desc)) | ||
1167 | goto out; | ||
1168 | |||
1169 | desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); | ||
1170 | |||
1171 | /* | ||
1172 | * If its disabled or no action available | ||
1173 | * then mask it and get out of here: | ||
1174 | */ | ||
1175 | if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) { | ||
1176 | desc->istate |= IRQS_PENDING; | ||
1177 | mask_irq(desc); | ||
1178 | goto out; | ||
1179 | } | ||
1180 | |||
1181 | kstat_incr_irqs_this_cpu(desc); | ||
1182 | if (desc->istate & IRQS_ONESHOT) | ||
1183 | mask_irq(desc); | ||
1184 | |||
1185 | preflow_handler(desc); | ||
1186 | handle_irq_event(desc); | ||
1187 | |||
1188 | cond_unmask_eoi_irq(desc, chip); | ||
1189 | |||
1190 | raw_spin_unlock(&desc->lock); | ||
1191 | return; | ||
1192 | out: | ||
1193 | if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED)) | ||
1194 | chip->irq_eoi(&desc->irq_data); | ||
1195 | raw_spin_unlock(&desc->lock); | ||
1196 | } | ||
1197 | EXPORT_SYMBOL_GPL(handle_fasteoi_mask_irq); | ||
1198 | |||
1199 | #endif /* CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS */ | ||
1200 | |||
1095 | /** | 1201 | /** |
1096 | * irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if | 1202 | * irq_chip_enable_parent - Enable the parent interrupt (defaults to unmask if |
1097 | * NULL) | 1203 | * NULL) |
@@ -1105,6 +1211,7 @@ void irq_chip_enable_parent(struct irq_data *data) | |||
1105 | else | 1211 | else |
1106 | data->chip->irq_unmask(data); | 1212 | data->chip->irq_unmask(data); |
1107 | } | 1213 | } |
1214 | EXPORT_SYMBOL_GPL(irq_chip_enable_parent); | ||
1108 | 1215 | ||
1109 | /** | 1216 | /** |
1110 | * irq_chip_disable_parent - Disable the parent interrupt (defaults to mask if | 1217 | * irq_chip_disable_parent - Disable the parent interrupt (defaults to mask if |
@@ -1119,6 +1226,7 @@ void irq_chip_disable_parent(struct irq_data *data) | |||
1119 | else | 1226 | else |
1120 | data->chip->irq_mask(data); | 1227 | data->chip->irq_mask(data); |
1121 | } | 1228 | } |
1229 | EXPORT_SYMBOL_GPL(irq_chip_disable_parent); | ||
1122 | 1230 | ||
1123 | /** | 1231 | /** |
1124 | * irq_chip_ack_parent - Acknowledge the parent interrupt | 1232 | * irq_chip_ack_parent - Acknowledge the parent interrupt |
@@ -1181,6 +1289,7 @@ int irq_chip_set_affinity_parent(struct irq_data *data, | |||
1181 | 1289 | ||
1182 | return -ENOSYS; | 1290 | return -ENOSYS; |
1183 | } | 1291 | } |
1292 | EXPORT_SYMBOL_GPL(irq_chip_set_affinity_parent); | ||
1184 | 1293 | ||
1185 | /** | 1294 | /** |
1186 | * irq_chip_set_type_parent - Set IRQ type on the parent interrupt | 1295 | * irq_chip_set_type_parent - Set IRQ type on the parent interrupt |