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);
}
Exemple #2
0
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);
}
Exemple #5
0
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);
}
Exemple #6
0
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);
}
Exemple #7
0
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);
}
Exemple #8
0
/*
 * 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);

}
Exemple #11
0
/* 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);

}
Exemple #12
0
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;
}