dbrec.c revision 256281
1/* 2 * Copyright (c) 2005 Topspin Communications. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33#if HAVE_CONFIG_H 34# include <config.h> 35#endif /* HAVE_CONFIG_H */ 36 37#include <stdlib.h> 38#include <netinet/in.h> 39#include <pthread.h> 40#include <string.h> 41 42#include "mlx4.h" 43 44struct mlx4_db_page { 45 struct mlx4_db_page *prev, *next; 46 struct mlx4_buf buf; 47 int num_db; 48 int use_cnt; 49 unsigned long free[0]; 50}; 51 52static const int db_size[] = { 53 [MLX4_DB_TYPE_CQ] = 8, 54 [MLX4_DB_TYPE_RQ] = 4, 55}; 56 57static struct mlx4_db_page *__add_page(struct mlx4_context *context, 58 enum mlx4_db_type type) 59{ 60 struct mlx4_db_page *page; 61 int ps = to_mdev(context->ibv_ctx.device)->page_size; 62 int pp; 63 int i; 64 65 pp = ps / db_size[type]; 66 67 page = malloc(sizeof *page + pp / 8); 68 if (!page) 69 return NULL; 70 71 if (mlx4_alloc_buf(&page->buf, ps, ps)) { 72 free(page); 73 return NULL; 74 } 75 76 page->num_db = pp; 77 page->use_cnt = 0; 78 for (i = 0; i < pp / (sizeof (long) * 8); ++i) 79 page->free[i] = ~0; 80 81 page->prev = NULL; 82 page->next = context->db_list[type]; 83 context->db_list[type] = page; 84 if (page->next) 85 page->next->prev = page; 86 87 return page; 88} 89 90uint32_t *mlx4_alloc_db(struct mlx4_context *context, enum mlx4_db_type type) 91{ 92 struct mlx4_db_page *page; 93 uint32_t *db = NULL; 94 int i, j; 95 96 pthread_mutex_lock(&context->db_list_mutex); 97 98 for (page = context->db_list[type]; page; page = page->next) 99 if (page->use_cnt < page->num_db) 100 goto found; 101 102 page = __add_page(context, type); 103 if (!page) 104 goto out; 105 106found: 107 ++page->use_cnt; 108 109 for (i = 0; !page->free[i]; ++i) 110 /* nothing */; 111 112 j = ffsl(page->free[i]); 113 page->free[i] &= ~(1UL << (j - 1)); 114 db = page->buf.buf + (i * 8 * sizeof (long) + (j - 1)) * db_size[type]; 115 116out: 117 pthread_mutex_unlock(&context->db_list_mutex); 118 119 return db; 120} 121 122void mlx4_free_db(struct mlx4_context *context, enum mlx4_db_type type, uint32_t *db) 123{ 124 struct mlx4_db_page *page; 125 uintptr_t ps = to_mdev(context->ibv_ctx.device)->page_size; 126 int i; 127 128 pthread_mutex_lock(&context->db_list_mutex); 129 130 for (page = context->db_list[type]; page; page = page->next) 131 if (((uintptr_t) db & ~(ps - 1)) == (uintptr_t) page->buf.buf) 132 break; 133 134 if (!page) 135 goto out; 136 137 i = ((void *) db - page->buf.buf) / db_size[type]; 138 page->free[i / (8 * sizeof (long))] |= 1UL << (i % (8 * sizeof (long))); 139 140 if (!--page->use_cnt) { 141 if (page->prev) 142 page->prev->next = page->next; 143 else 144 context->db_list[type] = page->next; 145 if (page->next) 146 page->next->prev = page->prev; 147 148 mlx4_free_buf(&page->buf); 149 free(page); 150 } 151 152out: 153 pthread_mutex_unlock(&context->db_list_mutex); 154} 155