⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cxio_resource.c

📁 linux内核源码
💻 C
字号:
/* * Copyright (c) 2006 Chelsio, Inc. 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 * OpenIB.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. *//* Crude resource management */#include <linux/kernel.h>#include <linux/random.h>#include <linux/slab.h>#include <linux/kfifo.h>#include <linux/spinlock.h>#include <linux/errno.h>#include "cxio_resource.h"#include "cxio_hal.h"static struct kfifo *rhdl_fifo;static spinlock_t rhdl_fifo_lock;#define RANDOM_SIZE 16static int __cxio_init_resource_fifo(struct kfifo **fifo,				   spinlock_t *fifo_lock,				   u32 nr, u32 skip_low,				   u32 skip_high,				   int random){	u32 i, j, entry = 0, idx;	u32 random_bytes;	u32 rarray[16];	spin_lock_init(fifo_lock);	*fifo = kfifo_alloc(nr * sizeof(u32), GFP_KERNEL, fifo_lock);	if (IS_ERR(*fifo))		return -ENOMEM;	for (i = 0; i < skip_low + skip_high; i++)		__kfifo_put(*fifo, (unsigned char *) &entry, sizeof(u32));	if (random) {		j = 0;		random_bytes = random32();		for (i = 0; i < RANDOM_SIZE; i++)			rarray[i] = i + skip_low;		for (i = skip_low + RANDOM_SIZE; i < nr - skip_high; i++) {			if (j >= RANDOM_SIZE) {				j = 0;				random_bytes = random32();			}			idx = (random_bytes >> (j * 2)) & 0xF;			__kfifo_put(*fifo,				(unsigned char *) &rarray[idx],				sizeof(u32));			rarray[idx] = i;			j++;		}		for (i = 0; i < RANDOM_SIZE; i++)			__kfifo_put(*fifo,				(unsigned char *) &rarray[i],				sizeof(u32));	} else		for (i = skip_low; i < nr - skip_high; i++)			__kfifo_put(*fifo, (unsigned char *) &i, sizeof(u32));	for (i = 0; i < skip_low + skip_high; i++)		kfifo_get(*fifo, (unsigned char *) &entry, sizeof(u32));	return 0;}static int cxio_init_resource_fifo(struct kfifo **fifo, spinlock_t * fifo_lock,				   u32 nr, u32 skip_low, u32 skip_high){	return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low,					  skip_high, 0));}static int cxio_init_resource_fifo_random(struct kfifo **fifo,				   spinlock_t * fifo_lock,				   u32 nr, u32 skip_low, u32 skip_high){	return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low,					  skip_high, 1));}static int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p){	u32 i;	spin_lock_init(&rdev_p->rscp->qpid_fifo_lock);	rdev_p->rscp->qpid_fifo = kfifo_alloc(T3_MAX_NUM_QP * sizeof(u32),					      GFP_KERNEL,					      &rdev_p->rscp->qpid_fifo_lock);	if (IS_ERR(rdev_p->rscp->qpid_fifo))		return -ENOMEM;	for (i = 16; i < T3_MAX_NUM_QP; i++)		if (!(i & rdev_p->qpmask))			__kfifo_put(rdev_p->rscp->qpid_fifo,				    (unsigned char *) &i, sizeof(u32));	return 0;}int cxio_hal_init_rhdl_resource(u32 nr_rhdl){	return cxio_init_resource_fifo(&rhdl_fifo, &rhdl_fifo_lock, nr_rhdl, 1,				       0);}void cxio_hal_destroy_rhdl_resource(void){	kfifo_free(rhdl_fifo);}/* nr_* must be power of 2 */int cxio_hal_init_resource(struct cxio_rdev *rdev_p,			   u32 nr_tpt, u32 nr_pbl,			   u32 nr_rqt, u32 nr_qpid, u32 nr_cqid, u32 nr_pdid){	int err = 0;	struct cxio_hal_resource *rscp;	rscp = kmalloc(sizeof(*rscp), GFP_KERNEL);	if (!rscp)		return -ENOMEM;	rdev_p->rscp = rscp;	err = cxio_init_resource_fifo_random(&rscp->tpt_fifo,				      &rscp->tpt_fifo_lock,				      nr_tpt, 1, 0);	if (err)		goto tpt_err;	err = cxio_init_qpid_fifo(rdev_p);	if (err)		goto qpid_err;	err = cxio_init_resource_fifo(&rscp->cqid_fifo, &rscp->cqid_fifo_lock,				      nr_cqid, 1, 0);	if (err)		goto cqid_err;	err = cxio_init_resource_fifo(&rscp->pdid_fifo, &rscp->pdid_fifo_lock,				      nr_pdid, 1, 0);	if (err)		goto pdid_err;	return 0;pdid_err:	kfifo_free(rscp->cqid_fifo);cqid_err:	kfifo_free(rscp->qpid_fifo);qpid_err:	kfifo_free(rscp->tpt_fifo);tpt_err:	return -ENOMEM;}/* * returns 0 if no resource available */static u32 cxio_hal_get_resource(struct kfifo *fifo){	u32 entry;	if (kfifo_get(fifo, (unsigned char *) &entry, sizeof(u32)))		return entry;	else		return 0;	/* fifo emptry */}static void cxio_hal_put_resource(struct kfifo *fifo, u32 entry){	BUG_ON(kfifo_put(fifo, (unsigned char *) &entry, sizeof(u32)) == 0);}u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp){	return cxio_hal_get_resource(rscp->tpt_fifo);}void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag){	cxio_hal_put_resource(rscp->tpt_fifo, stag);}u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp){	u32 qpid = cxio_hal_get_resource(rscp->qpid_fifo);	PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);	return qpid;}void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid){	PDBG("%s qpid 0x%x\n", __FUNCTION__, qpid);	cxio_hal_put_resource(rscp->qpid_fifo, qpid);}u32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp){	return cxio_hal_get_resource(rscp->cqid_fifo);}void cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid){	cxio_hal_put_resource(rscp->cqid_fifo, cqid);}u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp){	return cxio_hal_get_resource(rscp->pdid_fifo);}void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid){	cxio_hal_put_resource(rscp->pdid_fifo, pdid);}void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp){	kfifo_free(rscp->tpt_fifo);	kfifo_free(rscp->cqid_fifo);	kfifo_free(rscp->qpid_fifo);	kfifo_free(rscp->pdid_fifo);	kfree(rscp);}/* * PBL Memory Manager.  Uses Linux generic allocator. */#define MIN_PBL_SHIFT 8			/* 256B == min PBL size (32 entries) */#define PBL_CHUNK 2*1024*1024u32 cxio_hal_pblpool_alloc(struct cxio_rdev *rdev_p, int size){	unsigned long addr = gen_pool_alloc(rdev_p->pbl_pool, size);	PDBG("%s addr 0x%x size %d\n", __FUNCTION__, (u32)addr, size);	return (u32)addr;}void cxio_hal_pblpool_free(struct cxio_rdev *rdev_p, u32 addr, int size){	PDBG("%s addr 0x%x size %d\n", __FUNCTION__, addr, size);	gen_pool_free(rdev_p->pbl_pool, (unsigned long)addr, size);}int cxio_hal_pblpool_create(struct cxio_rdev *rdev_p){	unsigned long i;	rdev_p->pbl_pool = gen_pool_create(MIN_PBL_SHIFT, -1);	if (rdev_p->pbl_pool)		for (i = rdev_p->rnic_info.pbl_base;		     i <= rdev_p->rnic_info.pbl_top - PBL_CHUNK + 1;		     i += PBL_CHUNK)			gen_pool_add(rdev_p->pbl_pool, i, PBL_CHUNK, -1);	return rdev_p->pbl_pool ? 0 : -ENOMEM;}void cxio_hal_pblpool_destroy(struct cxio_rdev *rdev_p){	gen_pool_destroy(rdev_p->pbl_pool);}/* * RQT Memory Manager.  Uses Linux generic allocator. */#define MIN_RQT_SHIFT 10	/* 1KB == mini RQT size (16 entries) */#define RQT_CHUNK 2*1024*1024u32 cxio_hal_rqtpool_alloc(struct cxio_rdev *rdev_p, int size){	unsigned long addr = gen_pool_alloc(rdev_p->rqt_pool, size << 6);	PDBG("%s addr 0x%x size %d\n", __FUNCTION__, (u32)addr, size << 6);	return (u32)addr;}void cxio_hal_rqtpool_free(struct cxio_rdev *rdev_p, u32 addr, int size){	PDBG("%s addr 0x%x size %d\n", __FUNCTION__, addr, size << 6);	gen_pool_free(rdev_p->rqt_pool, (unsigned long)addr, size << 6);}int cxio_hal_rqtpool_create(struct cxio_rdev *rdev_p){	unsigned long i;	rdev_p->rqt_pool = gen_pool_create(MIN_RQT_SHIFT, -1);	if (rdev_p->rqt_pool)		for (i = rdev_p->rnic_info.rqt_base;		     i <= rdev_p->rnic_info.rqt_top - RQT_CHUNK + 1;		     i += RQT_CHUNK)			gen_pool_add(rdev_p->rqt_pool, i, RQT_CHUNK, -1);	return rdev_p->rqt_pool ? 0 : -ENOMEM;}void cxio_hal_rqtpool_destroy(struct cxio_rdev *rdev_p){	gen_pool_destroy(rdev_p->rqt_pool);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -