void cl_event_wheel_unreg(IN cl_event_wheel_t * const p_event_wheel, IN uint64_t key) { cl_event_wheel_reg_info_t *p_event; cl_map_item_t *p_map_item; CL_DBG("cl_event_wheel_unreg: " "Removing key:0x%" PRIx64 "\n", key); cl_spinlock_acquire(&p_event_wheel->lock); p_map_item = cl_qmap_get(&p_event_wheel->events_map, key); if (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) { /* we found such an item. */ p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item); /* remove the item from the qlist */ cl_qlist_remove_item(&p_event_wheel->events_wheel, &(p_event->list_item)); /* remove the item from the qmap */ cl_qmap_remove_item(&p_event_wheel->events_map, &(p_event->map_item)); CL_DBG("cl_event_wheel_unreg: Removed key:0x%" PRIx64 "\n", key); /* free the item */ free(p_event); } else { CL_DBG("cl_event_wheel_unreg: did not find key:0x%" PRIx64 "\n", key); } cl_spinlock_release(&p_event_wheel->lock); }
void cl_timer_stop(IN cl_timer_t * const p_timer) { CL_ASSERT(p_timer); CL_ASSERT(p_timer->state == CL_INITIALIZED); pthread_mutex_lock(&gp_timer_prov->mutex); switch (p_timer->timer_state) { case CL_TIMER_RUNNING: /* Wait for the callback to complete. */ pthread_cond_wait(&p_timer->cond, &gp_timer_prov->mutex); /* Timer could have been queued while we were waiting. */ if (p_timer->timer_state != CL_TIMER_QUEUED) break; case CL_TIMER_QUEUED: /* Change the state of the timer. */ p_timer->timer_state = CL_TIMER_IDLE; /* Remove the timer from the queue. */ cl_qlist_remove_item(&gp_timer_prov->queue, &p_timer->list_item); /* * Signal the timer provider thread to move onto the * next timer in the queue. */ pthread_cond_signal(&gp_timer_prov->cond); break; case CL_TIMER_IDLE: break; } pthread_mutex_unlock(&gp_timer_prov->mutex); }
void osm_vendor_unbind(IN osm_bind_handle_t h_bind) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_log_t *p_log = p_bo->p_vendor->p_log; cl_list_obj_t *p_obj = NULL; cl_list_item_t *p_item, *p_item_tmp; cl_qlist_t *const p_bh_list = (cl_qlist_t * const)&p_bo->p_vendor->bind_handles; OSM_LOG_ENTER(p_log); /* go over all the items in the list and remove the specific item */ p_item = cl_qlist_head(p_bh_list); while (p_item != cl_qlist_end(p_bh_list)) { p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); if (cl_qlist_obj(p_obj) == h_bind) { break; } p_item_tmp = cl_qlist_next(p_item); p_item = p_item_tmp; } CL_ASSERT(p_item != cl_qlist_end(p_bh_list)); cl_qlist_remove_item(p_bh_list, p_item); if (p_obj) free(p_obj); if (h_bind != 0) { __osm_vendor_internal_unbind(h_bind); } OSM_LOG_EXIT(p_log); }
void osm_vendor_unbind(IN osm_bind_handle_t h_bind) { mad_bind_info_t *p_mad_bind_info; umadt_obj_t *p_umadt_obj; cl_list_item_t *p_list_item, *p_next_list_item; CL_ASSERT(h_bind); p_mad_bind_info = (mad_bind_info_t *) h_bind; p_umadt_obj = p_mad_bind_info->p_umadt_obj; /* sanity check */ CL_ASSERT(p_umadt_obj); CL_ASSERT(p_umadt_obj->init_done); CL_ASSERT(__valid_mad_handle(p_mad_bind_info)); p_umadt_obj->uMadtInterface.uMadtDestroy(&p_mad_bind_info-> umadt_handle); cl_timer_destroy(&p_mad_bind_info->timeout_timer); cl_thread_destroy(&p_mad_bind_info->recv_processor_thread); cl_spinlock_acquire(&p_mad_bind_info->trans_ctxt_lock); p_list_item = cl_qlist_head(&p_mad_bind_info->trans_ctxt_list); while (p_list_item != cl_qlist_end(&p_mad_bind_info->trans_ctxt_list)) { p_next_list_item = cl_qlist_next(p_list_item); cl_qlist_remove_item(&p_mad_bind_info->trans_ctxt_list, p_list_item); free(p_list_item); p_list_item = p_next_list_item; } cl_spinlock_release(&p_mad_bind_info->trans_ctxt_lock); cl_spinlock_acquire(&p_mad_bind_info->timeout_list_lock); p_list_item = cl_qlist_head(&p_mad_bind_info->timeout_list); while (p_list_item != cl_qlist_end(&p_mad_bind_info->timeout_list)) { p_next_list_item = cl_qlist_next(p_list_item); cl_qlist_remove_item(&p_mad_bind_info->timeout_list, p_list_item); free(p_list_item); p_list_item = p_next_list_item; } cl_spinlock_release(&p_mad_bind_info->timeout_list_lock); free(p_mad_bind_info); }
cl_status_t cl_timer_start(IN cl_timer_t * const p_timer, IN const uint32_t time_ms) { struct timeval curtime; cl_list_item_t *p_list_item; uint32_t delta_time = time_ms; CL_ASSERT(p_timer); CL_ASSERT(p_timer->state == CL_INITIALIZED); pthread_mutex_lock(&gp_timer_prov->mutex); /* Signal the timer provider thread to wake up. */ pthread_cond_signal(&gp_timer_prov->cond); /* Remove the timer from the queue if currently queued. */ if (p_timer->timer_state == CL_TIMER_QUEUED) cl_qlist_remove_item(&gp_timer_prov->queue, &p_timer->list_item); /* Get the current time */ #ifndef timerclear #define timerclear(tvp) (tvp)->tv_sec = (time_t)0, (tvp)->tv_usec = 0L #endif timerclear(&curtime); gettimeofday(&curtime, NULL); /* do not do 0 wait ! */ /* if (delta_time < 1000.0) {delta_time = 1000;} */ /* Calculate the timeout. */ p_timer->timeout.tv_sec = curtime.tv_sec + (delta_time / 1000); p_timer->timeout.tv_nsec = (curtime.tv_usec + ((delta_time % 1000) * 1000)) * 1000; /* Add the timer to the queue. */ if (cl_is_qlist_empty(&gp_timer_prov->queue)) { /* The timer list is empty. Add to the head. */ cl_qlist_insert_head(&gp_timer_prov->queue, &p_timer->list_item); } else { /* Find the correct insertion place in the list for the timer. */ p_list_item = cl_qlist_find_from_tail(&gp_timer_prov->queue, __cl_timer_find, p_timer); /* Insert the timer. */ cl_qlist_insert_next(&gp_timer_prov->queue, p_list_item, &p_timer->list_item); } /* Set the state. */ p_timer->timer_state = CL_TIMER_QUEUED; pthread_mutex_unlock(&gp_timer_prov->mutex); return (CL_SUCCESS); }
ib_api_status_t osm_transaction_mgr_get_madw_for_tid(IN osm_vendor_t * const p_vend, IN ib_mad_t * const p_mad, OUT osm_madw_t ** req_madw_p) { osm_transaction_mgr_t *trans_mgr_p; osm_madw_req_t *osm_madw_req_p; cl_map_item_t *p_map_item; uint64_t key; OSM_LOG_ENTER(p_vend->p_log); trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr; *req_madw_p = NULL; osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_transaction_mgr_get_madw_for_tid: " "Looking for TID:<0x%" PRIx64 ">.\n", p_mad->trans_id); key = (uint64_t) p_mad->trans_id; cl_spinlock_acquire(&(trans_mgr_p->transaction_mgr_lock)); p_map_item = cl_qmap_get(trans_mgr_p->madw_by_tid_map_p, key); if (p_map_item != cl_qmap_end(trans_mgr_p->madw_by_tid_map_p)) { /* we found such an item. */ /* get the osm_madw_req_p */ osm_madw_req_p = PARENT_STRUCT(p_map_item, osm_madw_req_t, map_item); /* Since the Transaction was looked up and provided for */ /* processing we retire it */ cl_qlist_remove_item(trans_mgr_p->madw_reqs_list_p, &(osm_madw_req_p->list_item)); /* remove the item from the qmap */ cl_qmap_remove_item(trans_mgr_p->madw_by_tid_map_p, &(osm_madw_req_p->map_item)); osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_transaction_mgr_get_madw_for_tid: " "Removed TID:<0x%" PRIx64 ">.\n", p_mad->trans_id); *req_madw_p = osm_madw_req_p->p_madw; } cl_spinlock_release(&(trans_mgr_p->transaction_mgr_lock)); osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_transaction_mgr_get_madw_for_tid: " "Got MADW:%p.\n", *req_madw_p); OSM_LOG_EXIT(p_vend->p_log); return (IB_SUCCESS); }
ib_api_status_t osm_transaction_mgr_erase_madw(IN osm_vendor_t * const p_vend, IN ib_mad_t * p_mad) { osm_transaction_mgr_t *trans_mgr_p; osm_madw_req_t *osm_madw_req_p; uint64_t key; cl_map_item_t *p_map_item; OSM_LOG_ENTER(p_vend->p_log); trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr; key = (uint64_t) p_mad->trans_id; osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_transaction_mgr_erase_madw: " "Removing TID:<0x%" PRIx64 ">.\n", p_mad->trans_id); cl_spinlock_acquire(&trans_mgr_p->transaction_mgr_lock); p_map_item = cl_qmap_get(trans_mgr_p->madw_by_tid_map_p, key); if (p_map_item != cl_qmap_end(trans_mgr_p->madw_by_tid_map_p)) { /* we found such an item. */ /* get the osm_madw_req_p */ osm_madw_req_p = PARENT_STRUCT(p_map_item, osm_madw_req_t, map_item); /* remove the item from the qlist */ cl_qlist_remove_item(trans_mgr_p->madw_reqs_list_p, &(osm_madw_req_p->list_item)); /* remove the item from the qmap */ cl_qmap_remove_item(trans_mgr_p->madw_by_tid_map_p, &(osm_madw_req_p->map_item)); osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_transaction_mgr_erase_madw: " "Removed TID:<0x%" PRIx64 ">.\n", p_mad->trans_id); /* free the item */ free(osm_madw_req_p); } else { osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_transaction_mgr_erase_madw: " "osm_transaction_mgr_erase_madw:<0x%" PRIx64 "> NOT FOUND.\n", p_mad->trans_id); } cl_spinlock_release(&trans_mgr_p->transaction_mgr_lock); OSM_LOG_EXIT(p_vend->p_log); return (IB_SUCCESS); }
/* * This is the internal work function executed by the timer's thread. */ static void *__cl_timer_prov_cb(IN void *const context) { int ret; cl_timer_t *p_timer; pthread_mutex_lock(&gp_timer_prov->mutex); while (!gp_timer_prov->exit) { if (cl_is_qlist_empty(&gp_timer_prov->queue)) { /* Wait until we exit or a timer is queued. */ /* cond wait does: * pthread_cond_wait atomically unlocks the mutex (as per * pthread_unlock_mutex) and waits for the condition variable * cond to be signaled. The thread execution is suspended and * does not consume any CPU time until the condition variable is * signaled. The mutex must be locked by the calling thread on * entrance to pthread_cond_wait. Before RETURNING TO THE * CALLING THREAD, PTHREAD_COND_WAIT RE-ACQUIRES MUTEX (as per * pthread_lock_mutex). */ ret = pthread_cond_wait(&gp_timer_prov->cond, &gp_timer_prov->mutex); } else { /* * The timer elements are on the queue in expiration order. * Get the first in the list to determine how long to wait. */ p_timer = (cl_timer_t *) cl_qlist_head(&gp_timer_prov->queue); ret = pthread_cond_timedwait(&gp_timer_prov->cond, &gp_timer_prov->mutex, &p_timer->timeout); /* Sleep again on every event other than timeout and invalid Note: EINVAL means that we got behind. This can occur when we are very busy... */ if (ret != ETIMEDOUT && ret != EINVAL) continue; /* * The timer expired. Check the state in case it was cancelled * after it expired but before we got a chance to invoke the * callback. */ if (p_timer->timer_state != CL_TIMER_QUEUED) continue; /* * Mark the timer as running to synchronize with its * cancelation since we can't hold the mutex during the * callback. */ p_timer->timer_state = CL_TIMER_RUNNING; /* Remove the item from the timer queue. */ cl_qlist_remove_item(&gp_timer_prov->queue, &p_timer->list_item); pthread_mutex_unlock(&gp_timer_prov->mutex); /* Invoke the callback. */ p_timer->pfn_callback((void *)p_timer->context); /* Acquire the mutex again. */ pthread_mutex_lock(&gp_timer_prov->mutex); /* * Only set the state to idle if the timer has not been accessed * from the callback */ if (p_timer->timer_state == CL_TIMER_RUNNING) p_timer->timer_state = CL_TIMER_IDLE; /* * Signal any thread trying to manipulate the timer * that expired. */ pthread_cond_signal(&p_timer->cond); } } gp_timer_prov->thread = 0; pthread_mutex_unlock(&gp_timer_prov->mutex); pthread_exit(NULL); }
void __mad_recv_processor(IN void *context) { mad_bind_info_t *p_mad_bind_info = (mad_bind_info_t *) context; umadt_obj_t *p_umadt_obj; osm_madw_t *p_osm_madw = NULL; osm_vend_wrap_t *p_vend_wrap = NULL; osm_mad_addr_t osm_mad_addr = { 0 }; cl_list_item_t *p_list_item; void *transaction_context; FSTATUS Status; MadtStruct *pRecvMad = NULL; MadWorkCompletion *pRecvCmp = NULL; CL_ASSERT(context); p_mad_bind_info = (mad_bind_info_t *) context; p_umadt_obj = p_mad_bind_info->p_umadt_obj; /* PollFor a completion */ /* if FNOTFOND, then wait for a completion then again poll and return the MAD */ while (1) { Status = p_umadt_obj->uMadtInterface. uMadtPollForRecvCompletion(p_mad_bind_info->umadt_handle, &pRecvMad, &pRecvCmp); if (Status != FSUCCESS) { if (Status == FNOT_FOUND) { /* Wait for a completion */ Status = p_umadt_obj->uMadtInterface.uMadtWaitForAnyCompletion(p_mad_bind_info->umadt_handle, RECV_COMPLETION, 0x5000); /* 5 sec timeout */ if (Status == FTIMEOUT) { continue; } CL_ASSERT(Status == FSUCCESS); Status = p_umadt_obj->uMadtInterface. uMadtPollForRecvCompletion(p_mad_bind_info-> umadt_handle, &pRecvMad, &pRecvCmp); if (Status != FSUCCESS) { printf (" mad_recv_worker: Error in PollForRecv returning <%x>\n", Status); CL_ASSERT(0); } } else { printf ("uMadtPollForRecvCompletion Status=<%x>\n", Status); CL_ASSERT(0); } } CL_ASSERT(pRecvMad); CL_ASSERT(pRecvCmp); if (((ib_sa_mad_t_vM3 *) (&pRecvMad->IBMad))->frag_flag & 0x20) { /* Ignore the ACK packet */ Status = p_umadt_obj->uMadtInterface. uMadtReleaseRecvMad(p_mad_bind_info->umadt_handle, pRecvMad); continue; } /* */ /* Extract the return address to pass it on to the client */ /* */ osm_mad_addr.dest_lid = pRecvCmp->AddressInfo.DestLid; osm_mad_addr.path_bits = pRecvCmp->AddressInfo.PathBits; osm_mad_addr.static_rate = pRecvCmp->AddressInfo.StaticRate; if (p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_LID || p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_DIR) { osm_mad_addr.addr_type.smi.source_lid = pRecvCmp->AddressInfo.AddrType.Smi.SourceLid; /* osm_mad_addr.addr_type.smi.port_num = pRecvCmp->AddressInfo.AddrType.Smi.PortNumber; */ } else { osm_mad_addr.addr_type.gsi.remote_qp = pRecvCmp->AddressInfo.AddrType.Gsi.RemoteQpNumber; osm_mad_addr.addr_type.gsi.remote_qkey = pRecvCmp->AddressInfo.AddrType.Gsi.RemoteQkey; osm_mad_addr.addr_type.gsi.pkey_ix = 0; osm_mad_addr.addr_type.gsi.service_level = pRecvCmp->AddressInfo.AddrType.Gsi.ServiceLevel; osm_mad_addr.addr_type.gsi.global_route = pRecvCmp->AddressInfo.AddrType.Gsi.GlobalRoute; /* osm_mad_addr.addr_type.gsi.grh_info = pRecvCmp->AddressInfo.AddrType.Gsi.GRHInfo; */ } p_osm_madw = osm_mad_pool_get_wrapper(p_mad_bind_info->p_mad_pool, p_mad_bind_info, MAD_BLOCK_SIZE, (ib_mad_t *) & pRecvMad->IBMad, &osm_mad_addr); CL_ASSERT(p_osm_madw); p_vend_wrap = osm_madw_get_vend_ptr(p_osm_madw); CL_ASSERT(p_vend_wrap); p_vend_wrap->p_madt_struct = pRecvMad; p_vend_wrap->direction = RECEIVE; osm_log(p_mad_bind_info->p_umadt_obj->p_log, OSM_LOG_DEBUG, "__mad_recv_processor: " "Received data p_osm_madw[0x%p].\n", p_osm_madw); /* */ /* Do TID Processing. */ /* */ /* If R bit is set swap the TID */ cl_spinlock_acquire(&p_mad_bind_info->trans_ctxt_lock); p_list_item = cl_qlist_find_from_head(&p_mad_bind_info->trans_ctxt_list, __match_tid_context, &p_osm_madw->p_mad->trans_id); if (p_list_item == cl_qlist_end(&p_mad_bind_info->trans_ctxt_list)) { transaction_context = NULL; } else { transaction_context = ((trans_context_t *) p_list_item)->context; cl_qlist_remove_item(&p_mad_bind_info->trans_ctxt_list, p_list_item); free(p_list_item); } cl_spinlock_release(&p_mad_bind_info->trans_ctxt_lock); ((ib_mad_t *) p_osm_madw->p_mad)->trans_id = cl_ntoh64(p_osm_madw->p_mad->trans_id >> 24); osm_log(p_mad_bind_info->p_umadt_obj->p_log, OSM_LOG_DEBUG, "__mad_recv_processor: " "Received data p_osm_madw [0x%p]" "\n\t\t\t\tTID[0x%" PRIx64 ", context[%p]. \n", p_osm_madw, ((ib_mad_t *) p_osm_madw->p_mad)->trans_id, transaction_context); (*(p_mad_bind_info->mad_recv_callback)) (p_osm_madw, p_mad_bind_info-> client_context, transaction_context); } }
void __osm_vendor_timer_callback(IN void *context) { uint64_t current_time; mad_bind_info_t *p_mad_bind_info; umadt_obj_t *p_umadt_obj; uint32_t timeout; cl_list_item_t *p_list_item, *p_next_list_item; CL_ASSERT(context); p_mad_bind_info = (mad_bind_info_t *) context; p_umadt_obj = p_mad_bind_info->p_umadt_obj; timeout = p_umadt_obj->timeout * 1000; current_time = cl_get_time_stamp(); cl_spinlock_acquire(&p_mad_bind_info->trans_ctxt_lock); p_list_item = cl_qlist_head(&p_mad_bind_info->trans_ctxt_list); while (p_list_item != cl_qlist_end(&p_mad_bind_info->trans_ctxt_list)) { p_next_list_item = cl_qlist_next(p_list_item); /* DEFAULT_PKT_TIMEOUT is in milli seconds */ if (current_time - ((trans_context_t *) p_list_item)->sent_time > timeout) { /* Add this transaction to the timeout_list */ cl_qlist_remove_item(&p_mad_bind_info->trans_ctxt_list, p_list_item); cl_qlist_insert_tail(&p_mad_bind_info->timeout_list, p_list_item); } p_list_item = p_next_list_item; } cl_spinlock_release(&p_mad_bind_info->trans_ctxt_lock); p_list_item = cl_qlist_head(&p_mad_bind_info->timeout_list); while (p_list_item != cl_qlist_end(&p_mad_bind_info->timeout_list)) { osm_log(p_mad_bind_info->p_umadt_obj->p_log, OSM_LOG_DEBUG, "__osm_vendor_timer_callback: " "Timing out transaction context [0x%p].\n", ((trans_context_t *) p_list_item)->context); (*(p_mad_bind_info->mad_recv_callback)) (NULL, p_mad_bind_info-> client_context, ((trans_context_t *) p_list_item)-> context); p_next_list_item = cl_qlist_next(p_list_item); cl_qlist_remove_item(&p_mad_bind_info->timeout_list, p_list_item); free(p_list_item); p_list_item = p_next_list_item; } cl_timer_start(&p_mad_bind_info->timeout_timer, DEFAULT_TIMER_INTERVAL_MSEC); }
/* this is the callback function of the timer */ void __osm_transaction_mgr_callback(IN void *context) { osm_transaction_mgr_t *trans_mgr_p; osm_vendor_t *p_vend = (osm_vendor_t *) context; cl_list_item_t *p_list_item; cl_list_item_t *p_list_next_item; osm_madw_req_t *osm_madw_req_p; uint64_t current_time; /* [usec] */ uint32_t new_timeout; /* [msec] */ cl_status_t cl_status; ib_mad_t *p_mad; #ifdef OSM_VENDOR_INTF_MTL osm_mtl_bind_info_t *p_bind; #else osm_ts_bind_info_t *p_bind; #endif cl_list_t tmp_madw_p_list; /* this list will include all the madw_p that should be removed. */ cl_list_t retry_madw_p_list; /* this list will include all the madw_p that were retried and need to be removed. */ osm_madw_t *madw_p; OSM_LOG_ENTER(p_vend->p_log); trans_mgr_p = (osm_transaction_mgr_t *) p_vend->p_transaction_mgr; /* initialize the tmp_madw_p_list */ cl_list_construct(&tmp_madw_p_list); cl_status = cl_list_init(&tmp_madw_p_list, 50); if (cl_status != CL_SUCCESS) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__osm_transaction_mgr_callback : ERROR 1000: " "Failed to create tmp_madw_p_list\n"); } cl_list_construct(&retry_madw_p_list); cl_status = cl_list_init(&retry_madw_p_list, 50); if (cl_status != CL_SUCCESS) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__osm_transaction_mgr_callback : ERROR 1000: " "Failed to create retry_madw_p_list\n"); } current_time = cl_get_time_stamp(); cl_spinlock_acquire(&(trans_mgr_p->transaction_mgr_lock)); p_list_item = cl_qlist_head(trans_mgr_p->madw_reqs_list_p); if (p_list_item == cl_qlist_end(trans_mgr_p->madw_reqs_list_p)) { /* the list is empty - nothing to do */ cl_spinlock_release(&trans_mgr_p->transaction_mgr_lock); osm_log(p_vend->p_log, OSM_LOG_DEBUG, "__osm_transaction_mgr_callback : Nothing to do\n"); goto Exit; } /* non empty list: */ /* get the osm_madw_req_p */ osm_madw_req_p = PARENT_STRUCT(p_list_item, osm_madw_req_t, list_item); while (osm_madw_req_p->waking_time <= current_time) { /* this object was supposed to have gotten a response */ /* we need to decide if we need to retry or done with it. */ if (osm_madw_req_p->retry_cnt > 0) { /* add to the list of the retrys : */ cl_list_insert_tail(&retry_madw_p_list, osm_madw_req_p); /* update wakeup time and retry count */ osm_madw_req_p->waking_time = p_vend->timeout * 1000 + cl_get_time_stamp(); osm_madw_req_p->retry_cnt--; /* make sure we will get some timer call if not earlier */ osm_log(p_vend->p_log, OSM_LOG_DEBUG, "__osm_transaction_mgr_callback : Timer restart:%u\n", p_vend->timeout); cl_status = cl_timer_start(&trans_mgr_p->madw_list_timer, p_vend->timeout); /* go to the next object and check if it also needs to be removed - didn't receive response */ /* we need to do it before we move current item to the end of the list */ p_list_next_item = cl_qlist_next(p_list_item); /* remove from the head */ cl_qlist_remove_item(trans_mgr_p->madw_reqs_list_p, &(osm_madw_req_p->list_item)); /* insert the object to the qlist and the qmap */ cl_qlist_insert_tail(trans_mgr_p->madw_reqs_list_p, &(osm_madw_req_p->list_item)); } else { /* go to the next object and check if it also needs to be removed - didn't receive response */ p_list_next_item = cl_qlist_next(p_list_item); /* remove from the head */ cl_qlist_remove_item(trans_mgr_p->madw_reqs_list_p, &(osm_madw_req_p->list_item)); /* add it to the tmp_madw_p_list to be removed */ cl_list_insert_tail(&tmp_madw_p_list, osm_madw_req_p->p_madw); osm_log(p_vend->p_log, OSM_LOG_DEBUG, "__osm_transaction_mgr_callback : Found failed transaction madw: %p\n", osm_madw_req_p->p_madw); } /* Advance */ p_list_item = p_list_next_item; if (p_list_item == cl_qlist_end(trans_mgr_p->madw_reqs_list_p)) { /* the list is empty - nothing to do */ break; } /* get the osm_madw_req_p */ osm_madw_req_p = PARENT_STRUCT(p_list_item, osm_madw_req_t, list_item); } /* look at the current p_list_item. If it is not the end item - then we need to */ /* re-start the timer */ if (p_list_item != cl_qlist_end(trans_mgr_p->madw_reqs_list_p)) { /* get the osm_madw_req_p */ osm_madw_req_p = PARENT_STRUCT(p_list_item, osm_madw_req_t, list_item); /* we have the object that still didn't get response - re-start the timer */ /* start the timer to the timeout (in miliseconds) */ new_timeout = (osm_madw_req_p->waking_time - cl_get_time_stamp()) / 1000 + 1; cl_status = cl_timer_start(&trans_mgr_p->madw_list_timer, new_timeout); osm_log(p_vend->p_log, OSM_LOG_DEBUG, "__osm_transaction_mgr_callback : Timer restart:%u\n", new_timeout); if (cl_status != CL_SUCCESS) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__osm_transaction_mgr_callback : ERROR 1000: " "Failed to start timer\n"); } } /* if not empty - retry on retry list: */ if (!cl_is_list_empty(&retry_madw_p_list)) { /* remove all elements that were retried: */ osm_madw_req_p = (osm_madw_req_t *) (cl_list_remove_head(&retry_madw_p_list)); while (osm_madw_req_p != NULL) { /* resend: */ osm_log(p_vend->p_log, OSM_LOG_DEBUG, "__osm_transaction_mgr_callback : " "Retry %d of madw %p\n", OSM_DEFAULT_RETRY_COUNT - osm_madw_req_p->retry_cnt, osm_madw_req_p->p_madw); /* actually send it */ #ifdef OSM_VENDOR_INTF_MTL osm_mtl_send_mad((osm_mtl_bind_info_t *) osm_madw_req_p->p_bind, osm_madw_req_p->p_madw); #else ib_api_status_t osm_ts_send_mad(osm_ts_bind_info_t * p_bind, osm_madw_t * const p_madw); osm_ts_send_mad((osm_ts_bind_info_t *) osm_madw_req_p-> p_bind, osm_madw_req_p->p_madw); #endif /* next one */ osm_madw_req_p = (osm_madw_req_t *) (cl_list_remove_head(&retry_madw_p_list)); } } /* if the tmp_madw_p_list has elements - need to call the send_err_callback */ madw_p = (osm_madw_t *) (cl_list_remove_head(&tmp_madw_p_list)); while (madw_p != NULL) { /* need to remove it from pool */ /* obtain the madw_p stored as the wrid in the send call */ p_mad = osm_madw_get_mad_ptr(madw_p); p_bind = madw_p->h_bind; /* Return any wrappers to the pool that may have been pre-emptively allocated to handle a receive. */ if (madw_p->vend_wrap.p_resp_madw) { #ifdef OSM_VENDOR_INTF_MTL osm_mad_pool_put(p_bind->p_osm_pool, madw_p->vend_wrap.p_resp_madw); #else osm_mad_pool_put(p_bind->p_osm_pool, madw_p->vend_wrap.p_resp_madw); #endif madw_p->vend_wrap.p_resp_madw = NULL; } /* invoke the CB */ (*(osm_vend_mad_send_err_callback_t) (p_bind->send_err_callback)) (p_bind->client_context, madw_p); madw_p = (osm_madw_t *) (cl_list_remove_head(&tmp_madw_p_list)); } Exit: OSM_LOG_EXIT(p_vend->p_log); }
int osm_qos_setup(osm_opensm_t * p_osm) { struct qos_config ca_config, sw0_config, swe_config, rtr_config; struct qos_config *cfg; cl_qmap_t *p_tbl; cl_map_item_t *p_next; osm_port_t *p_port; osm_node_t *p_node; int ret = 0; int vlarb_only; qos_mad_list_t *p_list, *p_list_next; qos_mad_item_t *p_port_mad; cl_qlist_t qos_mad_list; if (!p_osm->subn.opt.qos) return 0; OSM_LOG_ENTER(&p_osm->log); qos_build_config(&ca_config, &p_osm->subn.opt.qos_ca_options, &p_osm->subn.opt.qos_options); qos_build_config(&sw0_config, &p_osm->subn.opt.qos_sw0_options, &p_osm->subn.opt.qos_options); qos_build_config(&swe_config, &p_osm->subn.opt.qos_swe_options, &p_osm->subn.opt.qos_options); qos_build_config(&rtr_config, &p_osm->subn.opt.qos_rtr_options, &p_osm->subn.opt.qos_options); cl_qlist_init(&qos_mad_list); cl_plock_excl_acquire(&p_osm->lock); /* read QoS policy config file */ osm_qos_parse_policy_file(&p_osm->subn); p_tbl = &p_osm->subn.port_guid_tbl; p_next = cl_qmap_head(p_tbl); while (p_next != cl_qmap_end(p_tbl)) { vlarb_only = 0; p_port = (osm_port_t *) p_next; p_next = cl_qmap_next(p_next); p_list = (qos_mad_list_t *) malloc(sizeof(*p_list)); if (!p_list) return -1; memset(p_list, 0, sizeof(*p_list)); cl_qlist_init(&p_list->port_mad_list); p_node = p_port->p_node; if (p_node->sw) { if (qos_extports_setup(&p_osm->sm, p_node, &swe_config, &p_list->port_mad_list)) ret = -1; /* skip base port 0 */ if (!ib_switch_info_is_enhanced_port0 (&p_node->sw->switch_info)) goto Continue; if (ib_switch_info_get_opt_sl2vlmapping(&p_node->sw->switch_info) && p_osm->sm.p_subn->opt.use_optimized_slvl && !memcmp(&swe_config.sl2vl, &sw0_config.sl2vl, sizeof(swe_config.sl2vl))) vlarb_only = 1; cfg = &sw0_config; } else if (osm_node_get_type(p_node) == IB_NODE_TYPE_ROUTER) cfg = &rtr_config; else cfg = &ca_config; if (qos_endport_setup(&p_osm->sm, p_port->p_physp, cfg, vlarb_only, &p_list->port_mad_list)) ret = -1; Continue: /* if MAD list is not empty, add it to the global MAD list */ if (cl_qlist_count(&p_list->port_mad_list)) { cl_qlist_insert_tail(&qos_mad_list, &p_list->list_item); } else { free(p_list); } } while (cl_qlist_count(&qos_mad_list)) { p_list_next = (qos_mad_list_t *) cl_qlist_head(&qos_mad_list); while (p_list_next != (qos_mad_list_t *) cl_qlist_end(&qos_mad_list)) { p_list = p_list_next; p_list_next = (qos_mad_list_t *) cl_qlist_next(&p_list->list_item); /* next MAD to send*/ p_port_mad = (qos_mad_item_t *) cl_qlist_remove_head(&p_list->port_mad_list); osm_send_req_mad(&p_osm->sm, p_port_mad->p_madw); osm_qos_mad_delete(&p_port_mad); /* remove the QoS MAD from global MAD list */ if (cl_qlist_count(&p_list->port_mad_list) == 0) { cl_qlist_remove_item(&qos_mad_list, &p_list->list_item); free(p_list); } } } cl_plock_release(&p_osm->lock); OSM_LOG_EXIT(&p_osm->log); return ret; }
cl_status_t cl_event_wheel_reg(IN cl_event_wheel_t * const p_event_wheel, IN const uint64_t key, IN const uint64_t aging_time_usec, IN cl_pfn_event_aged_cb_t pfn_callback, IN void *const context) { cl_event_wheel_reg_info_t *p_event; uint64_t timeout; uint32_t to; cl_status_t cl_status = CL_SUCCESS; cl_list_item_t *prev_event_list_item; cl_map_item_t *p_map_item; /* Get the lock on the manager */ cl_spinlock_acquire(&(p_event_wheel->lock)); cl_event_wheel_dump(p_event_wheel); /* Make sure such a key does not exists */ p_map_item = cl_qmap_get(&p_event_wheel->events_map, key); if (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) { CL_DBG("cl_event_wheel_reg: Already exists key:0x%" PRIx64 "\n", key); /* already there - remove it from the list as it is getting a new time */ p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item); /* remove the item from the qlist */ cl_qlist_remove_item(&p_event_wheel->events_wheel, &p_event->list_item); /* and the qmap */ cl_qmap_remove_item(&p_event_wheel->events_map, &p_event->map_item); } else { /* make a new one */ p_event = (cl_event_wheel_reg_info_t *) malloc(sizeof(cl_event_wheel_reg_info_t)); p_event->num_regs = 0; } p_event->key = key; p_event->aging_time = aging_time_usec; p_event->pfn_aged_callback = pfn_callback; p_event->context = context; p_event->num_regs++; CL_DBG("cl_event_wheel_reg: Registering event key:0x%" PRIx64 " aging in %u [msec]\n", p_event->key, (uint32_t) ((p_event->aging_time - cl_get_time_stamp()) / 1000)); /* If the list is empty - need to start the timer */ if (cl_is_qlist_empty(&p_event_wheel->events_wheel)) { /* Edward Bortnikov 03/29/2003 * ++TBD Consider moving the timer manipulation behind the list manipulation. */ /* calculate the new timeout */ timeout = (p_event->aging_time - cl_get_time_stamp() + 500) / 1000; /* stop the timer if it is running */ /* Edward Bortnikov 03/29/2003 * Don't call cl_timer_stop() because it spins forever. * cl_timer_start() will invoke cl_timer_stop() by itself. * * The problematic scenario is when __cl_event_wheel_callback() * is in race condition with this code. It sets timer.in_timer_cb * to TRUE and then blocks on p_event_wheel->lock. Following this, * the call to cl_timer_stop() hangs. Following this, the whole system * enters into a deadlock. * * cl_timer_stop(&p_event_wheel->timer); */ /* The timeout for the cl_timer_start should be given as uint32_t. if there is an overflow - warn about it. */ to = (uint32_t) timeout; if (timeout > (uint32_t) timeout) { to = 0xffffffff; /* max 32 bit timer */ CL_DBG("cl_event_wheel_reg: timeout requested is " "too large. Using timeout: %u\n", to); } /* start the timer to the timeout [msec] */ cl_status = cl_timer_start(&p_event_wheel->timer, to); if (cl_status != CL_SUCCESS) { CL_DBG("cl_event_wheel_reg : ERR 6203: " "Failed to start timer\n"); goto Exit; } } /* insert the object to the qlist and the qmap */ /* BUT WE MUST INSERT IT IN A SORTED MANNER */ prev_event_list_item = cl_qlist_find_from_tail(&p_event_wheel->events_wheel, __event_will_age_before, &p_event->aging_time); cl_qlist_insert_next(&p_event_wheel->events_wheel, prev_event_list_item, &p_event->list_item); cl_qmap_insert(&p_event_wheel->events_map, key, &(p_event->map_item)); Exit: cl_spinlock_release(&p_event_wheel->lock); return cl_status; }