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