/* * hci1394_isr_isoch_it() * Process each isoch transmit context which has its interrupt asserted. The * interrupt will be asserted when an isoch transmit descriptor with the * interrupt bit is finished being processed. */ static void hci1394_isr_isoch_it(hci1394_state_t *soft_state) { uint32_t i; uint32_t mask = 0x00000001; uint32_t ev; int num_it_contexts; hci1394_iso_ctxt_t *ctxtp; ASSERT(soft_state != NULL); TNF_PROBE_0_DEBUG(hci1394_isr_isoch_it_enter, HCI1394_TNF_HAL_STACK, ""); num_it_contexts = hci1394_isoch_xmit_count_get(soft_state->isoch); /* * Main isochTx int is not clearable. it is automatically * cleared by the hw when the it_intr_event is cleared. */ /* loop until no more IT events */ while ((ev = hci1394_ohci_it_intr_asserted(soft_state->ohci)) != 0) { /* clear the events we just learned about */ hci1394_ohci_it_intr_clear(soft_state->ohci, ev); /* for each interrupting IR context, process the interrupt */ for (i = 0; i < num_it_contexts; i++) { /* * if the intr bit is on for a context, * call xmit/recv common processing code */ if (ev & mask) { ctxtp = hci1394_isoch_xmit_ctxt_get( soft_state->isoch, i); hci1394_ixl_interrupt(soft_state, ctxtp, B_FALSE); } mask <<= 1; } } TNF_PROBE_0_DEBUG(hci1394_isr_isoch_it_exit, HCI1394_TNF_HAL_STACK, ""); }
/* * hci1394_isoch_cycle_inconsistent() * Called during interrupt notification to indicate that the cycle time * has changed unexpectedly. We need to take this opportunity to * update our tracking of each running transmit context's execution. * cycle_inconsistent only affects transmit, so recv contexts are left alone. */ void hci1394_isoch_cycle_inconsistent(hci1394_state_t *soft_statep) { int i, cnt_thresh; boolean_t note; hrtime_t current_time, last_time, delta, delta_thresh; hci1394_iso_ctxt_t *ctxtp; /* current context */ ASSERT(soft_statep); TNF_PROBE_0_DEBUG(hci1394_isoch_cycle_inconsistent_enter, HCI1394_TNF_HAL_STACK_ISOCH, ""); hci1394_ohci_intr_clear(soft_statep->ohci, OHCI_INTR_CYC_INCONSISTENT); /* grab the mutex before checking each context's INUSE and RUNNING */ mutex_enter(&soft_statep->isoch->ctxt_list_mutex); /* check for transmit contexts which are inuse and running */ for (i = 0; i < soft_statep->isoch->ctxt_xmit_count; i++) { ctxtp = &soft_statep->isoch->ctxt_xmit[i]; if ((ctxtp->ctxt_flags & (HCI1394_ISO_CTXT_INUSE | HCI1394_ISO_CTXT_RUNNING)) != 0) { mutex_exit(&soft_statep->isoch->ctxt_list_mutex); hci1394_ixl_interrupt(soft_statep, ctxtp, B_FALSE); mutex_enter(&soft_statep->isoch->ctxt_list_mutex); } } /* * get the current time and calculate the delta between now and * when the last interrupt was processed. (NOTE: if the time * returned by gethrtime() rolls-over while we are counting these * interrupts, we will incorrectly restart the counting process. * However, because the probability of this happening is small and * not catching the roll-over will AT MOST double the time it takes * us to discover and correct from this condition, we can safely * ignore it.) */ current_time = gethrtime(); last_time = soft_statep->isoch->cycle_incon_thresh.last_intr_time; delta = current_time - last_time; /* * compare the calculated delta to the delta T threshold. If it * is less than the threshold, then increment the counter. If it * is not then reset the counter. */ delta_thresh = soft_statep->isoch->cycle_incon_thresh.delta_t_thresh; if (delta < delta_thresh) soft_statep->isoch->cycle_incon_thresh.delta_t_counter++; else soft_statep->isoch->cycle_incon_thresh.delta_t_counter = 0; /* * compare the counter to the counter threshold. If it is greater, * then disable the cycle inconsistent interrupt. */ cnt_thresh = soft_statep->isoch->cycle_incon_thresh.counter_thresh; note = B_FALSE; if (soft_statep->isoch->cycle_incon_thresh.delta_t_counter > cnt_thresh) { hci1394_ohci_intr_disable(soft_statep->ohci, OHCI_INTR_CYC_INCONSISTENT); note = B_TRUE; } /* save away the current time into the last_intr_time field */ soft_statep->isoch->cycle_incon_thresh.last_intr_time = current_time; mutex_exit(&soft_statep->isoch->ctxt_list_mutex); if (note == B_TRUE) { cmn_err(CE_NOTE, "!hci1394(%d): cycle_inconsistent interrupt " "disabled until next bus reset", soft_statep->drvinfo.di_instance); TNF_PROBE_1(hci1394_isoch_cycle_inconsistent_error, HCI1394_TNF_HAL_ERROR_ISOCH, "", tnf_string, msg, "CYCLE_INCONSISTENT intr disabled until next bus reset"); } TNF_PROBE_0_DEBUG(hci1394_isoch_cycle_inconsistent_exit, HCI1394_TNF_HAL_STACK_ISOCH, ""); }