/**
 * If the buddy block is on the free list then coalesce and insert into the next
 * list until we reach an allocated or split buddy block, or the max list size.
 */
static inline uint32_t __gnix_buddy_coalesce(gnix_buddy_alloc_handle_t *alloc_handle
					 , void **ptr, uint32_t block_size)
{
	void *buddy;

	for (buddy = __gnix_buddy_address(*ptr, block_size, alloc_handle->base);
	     block_size < alloc_handle->max &&
		     !_gnix_test_bit(&alloc_handle->bitmap,
				     __gnix_buddy_bitmap_index(buddy,
							       block_size,
							       alloc_handle->base,
							       alloc_handle->len,
							       MIN_BLOCK_SIZE));
	     buddy = __gnix_buddy_address(*ptr, block_size, alloc_handle->base)) {

		dlist_remove(buddy);

		/* Ensure ptr is the beginning of the new block */
		if (*ptr > buddy)
			*ptr = buddy;

		block_size *= 2;

		_gnix_clear_bit(&alloc_handle->bitmap,
				__gnix_buddy_bitmap_index(*ptr, block_size,
							  alloc_handle->base,
							  alloc_handle->len,
							  MIN_BLOCK_SIZE));
	}
	return block_size;
}
Ejemplo n.º 2
0
static int __nic_rx_overrun(struct gnix_nic *nic)
{
	int i, max_id, ret;
	struct gnix_vc *vc;
	gni_return_t status;
	gni_cq_entry_t cqe;

	GNIX_WARN(FI_LOG_EP_DATA, "\n");

	/* clear out the CQ */
	/*
	 * TODO:  really need to process CQEs better for error reporting,
	 * etc.
	 */
	while ((status = GNI_CqGetEvent(nic->rx_cq, &cqe)) == GNI_RC_SUCCESS);
	assert(status == GNI_RC_NOT_DONE);

	COND_ACQUIRE(nic->requires_lock, &nic->vc_id_lock);
	max_id = nic->vc_id_table_count;
	COND_RELEASE(nic->requires_lock, &nic->vc_id_lock);
	/*
	 * TODO: optimization would
	 * be to keep track of last time
	 * this happened and where smsg msgs.
	 * were found.
	 */
	for (i = 0; i < max_id; i++) {
		ret = _gnix_test_bit(&nic->vc_id_bitmap, i);
		if (ret) {
			vc = __gnix_nic_elem_by_rem_id(nic, i);
			ret = _gnix_vc_dequeue_smsg(vc);
			if (ret != FI_SUCCESS) {
				GNIX_WARN(FI_LOG_EP_DATA,
					  "_gnix_vc_dqueue_smsg returned %d\n",
					  ret);
			}
		}
	}

	return FI_SUCCESS;
}