/* * nx1394_post_event() * Called when a child node calls ddi_post_event. If the event is one of * the events supported by us (bus reset/insert/remove, for now), builds * a t1394_localinfo_t structure and calls ndi_event_run_callbacks(). This * will result in all registered callbacks being invoked with * t1394_localinfo_t as the impl_data. (see ddi_add_eventcall for callback * arguments.) If the event is not defined by us, the request is * propagated up the device tree by calling ndi_post_event(). */ static int nx1394_post_event(dev_info_t *dip, dev_info_t *rdip, ddi_eventcookie_t cookie, void *impl_data) { int ret; char *name; s1394_hal_t *hal; t1394_localinfo_t localinfo; hal = s1394_dip_to_hal(dip); ASSERT(hal); TNF_PROBE_0_DEBUG(nx1394_post_event_enter, S1394_TNF_SL_NEXUS_STACK, ""); name = ndi_event_cookie_to_name(hal->hal_ndi_event_hdl, cookie); /* name is NULL if we don't generate the event */ if (name != NULL) { mutex_enter(&hal->topology_tree_mutex); localinfo.bus_generation = hal->generation_count; localinfo.local_nodeID = hal->node_id; mutex_exit(&hal->topology_tree_mutex); impl_data = &localinfo; ret = ndi_event_run_callbacks(hal->hal_ndi_event_hdl, rdip, cookie, impl_data); TNF_PROBE_4_DEBUG(nx1394_post_event_exit, S1394_TNF_SL_NEXUS_STACK, "", tnf_opaque, parent_dip, (void *)dip, tnf_opaque, requestor_dip, (void *)rdip, tnf_string, event_name, name, tnf_int, request_status, ret); return (ret); } else { ret = ndi_post_event(ddi_get_parent(dip), rdip, cookie, impl_data); TNF_PROBE_2_DEBUG(nx1394_post_event_exit, S1394_TNF_SL_NEXUS_STACK, "", tnf_string, msg, "Not our event", tnf_int, ret, ret); return (ret); } }
/* * hci1394_tlabel_lookup() * returns (in cmd) the opaque command which was registered with the * specified tlabel from alloc(). If a tlabel was not registered, cmd ='s * NULL. */ void hci1394_tlabel_lookup(hci1394_tlabel_handle_t tlabel_handle, hci1394_tlabel_info_t *tlabel_info, void **cmd) { uint_t node_number; uint_t tlabel; ASSERT(tlabel_handle != NULL); ASSERT(tlabel_info != NULL); ASSERT(cmd != NULL); ASSERT(tlabel_info->tbi_tlabel <= TLABEL_MASK); TNF_PROBE_0_DEBUG(hci1394_tlabel_lookup_enter, HCI1394_TNF_HAL_STACK, ""); /* figure out what node and tlabel we are using */ node_number = IEEE1394_NODE_NUM(tlabel_info->tbi_destination); tlabel = tlabel_info->tbi_tlabel; mutex_enter(&tlabel_handle->tb_mutex); /* * fetch the (void *) from the lookup table. The case where the pointer * equals NULL will be handled by the layer above. */ *cmd = tlabel_handle->tb_lookup[node_number][tlabel]; mutex_exit(&tlabel_handle->tb_mutex); TNF_PROBE_2_DEBUG(hci1394_tlabel_lookup, HCI1394_TNF_HAL_TLABEL, "", tnf_uint, nodeid, node_number, tnf_uint, lookup_tlabel, tlabel_info->tbi_tlabel); TNF_PROBE_0_DEBUG(hci1394_tlabel_lookup_exit, HCI1394_TNF_HAL_STACK, ""); }
/* * hci1394_tlabel_free() * free the previously alloc()'d tlabel. Once a tlabel has been free'd, it * can be used again when alloc() is called. */ void hci1394_tlabel_free(hci1394_tlabel_handle_t tlabel_handle, hci1394_tlabel_info_t *tlabel_info) { uint_t node_number; uint_t tlabel; ASSERT(tlabel_handle != NULL); ASSERT(tlabel_info != NULL); ASSERT(tlabel_info->tbi_tlabel <= TLABEL_MASK); TNF_PROBE_0_DEBUG(hci1394_tlabel_free_enter, HCI1394_TNF_HAL_STACK, ""); /* figure out what node and tlabel we are using */ node_number = IEEE1394_NODE_NUM(tlabel_info->tbi_destination); tlabel = tlabel_info->tbi_tlabel; TNF_PROBE_2_DEBUG(hci1394_tlabel_free, HCI1394_TNF_HAL_TLABEL, "", tnf_uint, nodeid, node_number, tnf_uint, freed_tlabel, tlabel_info->tbi_tlabel); mutex_enter(&tlabel_handle->tb_mutex); /* * Put the tlabel back in the free list and NULL out the (void *) in the * lookup structure. You wouldn't expect to have to null out the lookup * structure, but we know first hand that bad HW will send invalid * tlabels which could really mess things up if you didn't :-) */ tlabel_handle->tb_lookup[node_number][tlabel] = NULL; tlabel_handle->tb_free[node_number] |= ((uint64_t)1 << tlabel); mutex_exit(&tlabel_handle->tb_mutex); TNF_PROBE_0_DEBUG(hci1394_tlabel_free_exit, HCI1394_TNF_HAL_STACK, ""); }
/* * hci1394_tlabel_alloc() * alloc a tlabel based on the node id. If alloc fails, we are out of * tlabels for that node. See comments before set_reclaim_time() on when * bad tlabel's are free to be used again. */ int hci1394_tlabel_alloc(hci1394_tlabel_handle_t tlabel_handle, uint_t destination, hci1394_tlabel_info_t *tlabel_info) { uint_t node_number; uint_t index; uint64_t bad; uint64_t free; hrtime_t time; uint8_t last; ASSERT(tlabel_handle != NULL); ASSERT(tlabel_info != NULL); TNF_PROBE_0_DEBUG(hci1394_tlabel_alloc_enter, HCI1394_TNF_HAL_STACK, ""); /* copy destination into tlabel_info */ tlabel_info->tbi_destination = destination; /* figure out what node we are going to */ node_number = IEEE1394_NODE_NUM(destination); mutex_enter(&tlabel_handle->tb_mutex); /* * Keep track of if we have sent out a broadcast request and what the * maximum # node we have sent to for reset processing optimization */ if (node_number == IEEE1394_BROADCAST_NODEID) { tlabel_handle->tb_bcast_sent = B_TRUE; } else if (node_number > tlabel_handle->tb_max_node) { tlabel_handle->tb_max_node = node_number; } /* setup copies so we don't take up so much space :-) */ bad = tlabel_handle->tb_bad[node_number]; free = tlabel_handle->tb_free[node_number]; time = tlabel_handle->tb_bad_timestamp[node_number]; last = tlabel_handle->tb_last[node_number]; /* * If there are any bad tlabels, see if the last bad tlabel recorded for * this nodeid is now good to use. If so, add all bad tlabels for that * node id back into the free list * * NOTE: This assumes that bad tlabels are infrequent. */ if (bad != 0) { if (gethrtime() > time) { /* add the bad tlabels back into the free list */ free |= bad; /* clear the bad list */ bad = 0; TNF_PROBE_1(hci1394_tlabel_free_bad, HCI1394_TNF_HAL_ERROR, "", tnf_uint, nodeid, node_number); } } /* * Find a free tlabel. This will break out of the loop once it finds a * tlabel. There are a total of TLABEL_RANGE tlabels. The alloc * rotates the check so that we don't always use the same tlabel. It * stores the last tlabel used in last. */ for (index = 0; index < TLABEL_RANGE; index++) { /* if the next tlabel to check is free */ if ((free & ((uint64_t)1 << last)) != 0) { /* we are using this tlabel */ tlabel_info->tbi_tlabel = last; TNF_PROBE_2_DEBUG(hci1394_tlabel_alloc, HCI1394_TNF_HAL_TLABEL, "", tnf_uint, nodeid, node_number, tnf_uint, alloced_tlabel, tlabel_info->tbi_tlabel); /* take it out of the free list */ free = free & ~((uint64_t)1 << last); /* * increment the last count so we start checking on the * next tlabel next alloc(). Note the rollover at * TLABEL_RANGE since we only have TLABEL_RANGE tlabels. */ (last)++; if (last >= TLABEL_RANGE) { last = 0; } /* Copy the copies back */ tlabel_handle->tb_bad[node_number] = bad; tlabel_handle->tb_free[node_number] = free; tlabel_handle->tb_bad_timestamp[node_number] = time; tlabel_handle->tb_last[node_number] = last; /* unlock the tlabel structure */ mutex_exit(&tlabel_handle->tb_mutex); TNF_PROBE_0_DEBUG(hci1394_tlabel_alloc_exit, HCI1394_TNF_HAL_STACK, ""); return (DDI_SUCCESS); } /* * This tlabel is not free, lets go to the next one. Note the * rollover at TLABEL_RANGE since we only have TLABEL_RANGE * tlabels. */ (last)++; if (last >= TLABEL_RANGE) { last = 0; } } /* Copy the copies back */ tlabel_handle->tb_bad[node_number] = bad; tlabel_handle->tb_free[node_number] = free; tlabel_handle->tb_bad_timestamp[node_number] = time; tlabel_handle->tb_last[node_number] = last; mutex_exit(&tlabel_handle->tb_mutex); TNF_PROBE_1(hci1394_tlabel_alloc_empty, HCI1394_TNF_HAL_ERROR, "", tnf_string, errmsg, "No more tlabels left to alloc"); TNF_PROBE_0_DEBUG(hci1394_tlabel_alloc_exit, HCI1394_TNF_HAL_STACK, ""); return (DDI_FAILURE); }