Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixl/iwarp/iw_ixl_linux_genalloc.c
- This file was added.
/******************************************************************************* | |||||
* | |||||
* Copyright (c) 2015-2017 Intel Corporation. All rights reserved. | |||||
* | |||||
* This software is available to you under a choice of one of two | |||||
* licenses. You may choose to be licensed under the terms of the GNU | |||||
* General Public License (GPL) Version 2, available from the file | |||||
* COPYING in the main directory of this source tree, or the | |||||
* OpenFabrics.org BSD license below: | |||||
* | |||||
* Redistribution and use in source and binary forms, with or | |||||
* without modification, are permitted provided that the following | |||||
* conditions are met: | |||||
* | |||||
* - Redistributions of source code must retain the above | |||||
* copyright notice, this list of conditions and the following | |||||
* disclaimer. | |||||
* | |||||
* - Redistributions in binary form must reproduce the above | |||||
* copyright notice, this list of conditions and the following | |||||
* disclaimer in the documentation and/or other materials | |||||
* provided with the distribution. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
* SOFTWARE. | |||||
* | |||||
*******************************************************************************/ | |||||
/*$FreeBSD$*/ | |||||
#include <linux/types.h> | |||||
#include <sys/blist.h> | |||||
#include <sys/malloc.h> | |||||
#include <sys/queue.h> | |||||
#include <sys/lock.h> | |||||
#include <sys/mutex.h> | |||||
#include "iw_ixl_linux_genalloc.h" | |||||
#include "iw_ixl_dbg.h" | |||||
struct i40iw_pool_blist { | |||||
LIST_ENTRY(i40iw_pool_blist) node; | |||||
blist_t blist; | |||||
phys_addr_t phys; | |||||
unsigned long virt; | |||||
size_t size; | |||||
}; | |||||
LIST_HEAD(i40iw_pool_blists_head, i40iw_pool_blist); | |||||
struct gen_pool { | |||||
struct i40iw_pool_blists_head blists; | |||||
int size_shift; | |||||
struct mtx mtx; | |||||
}; | |||||
struct gen_pool * | |||||
i40iw_gen_pool_create(int size_shift) | |||||
{ | |||||
struct gen_pool *pool; | |||||
pool = malloc(sizeof(struct gen_pool), M_DEVBUF, M_NOWAIT | M_ZERO); | |||||
if (pool == NULL) | |||||
return NULL; | |||||
mtx_init(&pool->mtx, "iw_ixl_gen_pool", NULL, MTX_DEF); | |||||
LIST_INIT(&pool->blists); | |||||
pool->size_shift = size_shift; | |||||
return (pool); | |||||
} | |||||
void | |||||
i40iw_gen_pool_destroy(struct gen_pool *pool) | |||||
{ | |||||
struct i40iw_pool_blist *bl, *t_bl; | |||||
if (pool != NULL) { | |||||
mtx_lock(&pool->mtx); | |||||
LIST_FOREACH_SAFE(bl, &pool->blists, node, t_bl) { | |||||
blist_destroy(bl->blist); | |||||
LIST_REMOVE(bl, node); | |||||
free(bl, M_DEVBUF); | |||||
} | |||||
mtx_unlock(&pool->mtx); | |||||
mtx_destroy(&pool->mtx); | |||||
free(pool, M_DEVBUF); | |||||
} | |||||
} | |||||
int | |||||
i40iw_gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, | |||||
phys_addr_t phys, size_t size) | |||||
{ | |||||
struct i40iw_pool_blist *bl; | |||||
bl = malloc(sizeof(struct i40iw_pool_blist), M_DEVBUF, | |||||
M_NOWAIT | M_ZERO); | |||||
if (bl == NULL) | |||||
return (ENOMEM); | |||||
bl->blist = blist_create(size >> pool->size_shift, M_NOWAIT); | |||||
if (bl->blist == NULL) { | |||||
free(bl, M_DEVBUF); | |||||
return (ENOMEM); | |||||
} | |||||
blist_free(bl->blist, 0, size >> pool->size_shift); | |||||
bl->virt = virt; | |||||
bl->phys = phys; | |||||
bl->size = size; | |||||
mtx_lock(&pool->mtx); | |||||
LIST_INSERT_HEAD(&pool->blists, bl, node); | |||||
mtx_unlock(&pool->mtx); | |||||
return (0); | |||||
} | |||||
unsigned long | |||||
i40iw_gen_pool_alloc(struct gen_pool *pool, size_t size) | |||||
{ | |||||
struct i40iw_pool_blist *bl; | |||||
daddr_t blk_no = SWAPBLK_NONE; | |||||
int blk_cnt; | |||||
blk_cnt = I40IW_GEN_POOL_BLK_CNT(size, pool->size_shift); | |||||
mtx_lock(&pool->mtx); | |||||
LIST_FOREACH(bl, &pool->blists, node) { | |||||
blk_no = blist_alloc(bl->blist, blk_cnt); | |||||
if (blk_no != SWAPBLK_NONE) | |||||
break; | |||||
} | |||||
mtx_unlock(&pool->mtx); | |||||
if (blk_no == SWAPBLK_NONE) | |||||
return (0); | |||||
return (bl->virt + ((unsigned long)blk_no << pool->size_shift)); | |||||
} | |||||
void | |||||
i40iw_gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size) | |||||
{ | |||||
struct i40iw_pool_blist *bl; | |||||
daddr_t blk_no; | |||||
int blk_cnt; | |||||
mtx_lock(&pool->mtx); | |||||
LIST_FOREACH(bl, &pool->blists, node) { | |||||
if ((bl->virt <= addr) && | |||||
(bl->virt + bl->size >= addr + size)) { | |||||
blk_no = (addr - bl->virt) >> pool->size_shift; | |||||
blk_cnt = I40IW_GEN_POOL_BLK_CNT(size, pool->size_shift); | |||||
blist_free(bl->blist, blk_no, blk_cnt); | |||||
break; | |||||
} | |||||
} | |||||
mtx_unlock(&pool->mtx); | |||||
IW_IXL_ASSERT(bl != NULL); | |||||
} | |||||
phys_addr_t | |||||
i40iw_gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long addr) | |||||
{ | |||||
struct i40iw_pool_blist *bl; | |||||
phys_addr_t phys = -1; | |||||
mtx_lock(&pool->mtx); | |||||
LIST_FOREACH(bl, &pool->blists, node) { | |||||
if ((bl->virt <= addr) && | |||||
(bl->virt + bl->size > addr)) { | |||||
phys = bl->phys + (addr - bl->virt); | |||||
break; | |||||
} | |||||
} | |||||
mtx_unlock(&pool->mtx); | |||||
IW_IXL_ASSERT(bl != NULL); | |||||
return phys; | |||||
} |