- IOReturn ret;
- int intType;
- IOInterruptAction intHandler;
-
- ret = inProvider->getInterruptType(inIntIndex, &intType);
- if (kIOReturnSuccess != ret)
- return (ret);
-
- autoDisable = (intType == kIOInterruptTypeLevel);
- if (autoDisable) {
- intHandler = OSMemberFunctionCast(IOInterruptAction,
- this, &IOInterruptEventSource::disableInterruptOccurred);
- }
- else
- intHandler = OSMemberFunctionCast(IOInterruptAction,
- this, &IOInterruptEventSource::normalInterruptOccurred);
-
- ret = provider->registerInterrupt(inIntIndex, this, intHandler);
-
- return (ret);
+ IOReturn ret;
+ int intType;
+ IOInterruptAction intHandler;
+
+ ret = inProvider->getInterruptType(inIntIndex, &intType);
+ if (kIOReturnSuccess != ret) {
+ return ret;
+ }
+
+ autoDisable = (intType == kIOInterruptTypeLevel);
+ if (autoDisable) {
+ intHandler = OSMemberFunctionCast(IOInterruptAction,
+ this, &IOInterruptEventSource::disableInterruptOccurred);
+ } else {
+ intHandler = OSMemberFunctionCast(IOInterruptAction,
+ this, &IOInterruptEventSource::normalInterruptOccurred);
+ }
+
+ ret = provider->registerInterrupt(inIntIndex, this, intHandler);
+
+ /*
+ * Add statistics to the provider. The setWorkLoop convention should ensure
+ * that we always go down the unregister path before we register (outside of
+ * init()), so we don't have to worry that we will invoke addInterruptStatistics
+ * erroneously.
+ */
+ if ((ret == kIOReturnSuccess) && (reserved->statistics)) {
+ /*
+ * Stash the normal index value, for the sake of debugging.
+ */
+ reserved->statistics->interruptIndex = inIntIndex;
+
+ /*
+ * We need to hook the interrupt information up to the provider so that it
+ * can find the statistics for this interrupt when desired. The provider is
+ * responsible for maintaining the reporter for a particular interrupt, and
+ * needs a handle on the statistics so that it can request that the reporter
+ * be updated as needed. Errors are considered "soft" for the moment (it
+ * will either panic, or fail in a way such that we can still service the
+ * interrupt).
+ */
+ provider->addInterruptStatistics(reserved->statistics, inIntIndex);
+
+ /*
+ * Add the statistics object to the global list of statistics objects; this
+ * is an aid to debugging (we can trivially find statistics for all eligible
+ * interrupts, and dump them; potentially helpful if the system is wedged
+ * due to interrupt activity).
+ */
+ interruptAccountingDataAddToList(reserved->statistics);
+ }
+
+ return ret;
+}
+
+void
+IOInterruptEventSource::unregisterInterruptHandler(IOService *inProvider,
+ int inIntIndex)
+{
+ if (reserved->statistics) {
+ interruptAccountingDataRemoveFromList(reserved->statistics);
+ provider->removeInterruptStatistics(reserved->statistics->interruptIndex);
+ }
+
+ provider->unregisterInterrupt(inIntIndex);