/** * 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; }
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; }