1b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise/* 2b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * Copyright (c) 2006 Chelsio, Inc. All rights reserved. 3b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * 4b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * This software is available to you under a choice of one of two 5b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * licenses. You may choose to be licensed under the terms of the GNU 6b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * General Public License (GPL) Version 2, available from the file 7b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * COPYING in the main directory of this source tree, or the 8b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * OpenIB.org BSD license below: 9b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * 10b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * Redistribution and use in source and binary forms, with or 11b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * without modification, are permitted provided that the following 12b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * conditions are met: 13b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * 14b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * - Redistributions of source code must retain the above 15b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * copyright notice, this list of conditions and the following 16b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * disclaimer. 17b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * 18b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * - Redistributions in binary form must reproduce the above 19b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * copyright notice, this list of conditions and the following 20b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * disclaimer in the documentation and/or other materials 21b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * provided with the distribution. 22b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * 23b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * SOFTWARE. 31b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise */ 32b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise/* Crude resource management */ 33b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise#include <linux/kernel.h> 34b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise#include <linux/random.h> 35b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise#include <linux/slab.h> 36b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise#include <linux/kfifo.h> 37b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise#include <linux/spinlock.h> 38b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise#include <linux/errno.h> 39b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise#include "cxio_resource.h" 40b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise#include "cxio_hal.h" 41b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 4245465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seiboldstatic struct kfifo rhdl_fifo; 43b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisestatic spinlock_t rhdl_fifo_lock; 44b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 45b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise#define RANDOM_SIZE 16 46b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 4745465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seiboldstatic int __cxio_init_resource_fifo(struct kfifo *fifo, 48b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise spinlock_t *fifo_lock, 49b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise u32 nr, u32 skip_low, 50b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise u32 skip_high, 51b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise int random) 52b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 53b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise u32 i, j, entry = 0, idx; 54b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise u32 random_bytes; 55b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise u32 rarray[16]; 56b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise spin_lock_init(fifo_lock); 57b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 58c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold if (kfifo_alloc(fifo, nr * sizeof(u32), GFP_KERNEL)) 59b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return -ENOMEM; 60b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 61b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise for (i = 0; i < skip_low + skip_high; i++) 627acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold kfifo_in(fifo, (unsigned char *) &entry, sizeof(u32)); 63b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise if (random) { 64b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise j = 0; 6550bea5c0d583e255e3d8a193f8b20e177bac8ec8Andrew Morton random_bytes = prandom_u32(); 66b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise for (i = 0; i < RANDOM_SIZE; i++) 67b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise rarray[i] = i + skip_low; 68b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise for (i = skip_low + RANDOM_SIZE; i < nr - skip_high; i++) { 69b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise if (j >= RANDOM_SIZE) { 70b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise j = 0; 7150bea5c0d583e255e3d8a193f8b20e177bac8ec8Andrew Morton random_bytes = prandom_u32(); 72b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise } 73b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise idx = (random_bytes >> (j * 2)) & 0xF; 747acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold kfifo_in(fifo, 75b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise (unsigned char *) &rarray[idx], 76b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise sizeof(u32)); 77b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise rarray[idx] = i; 78b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise j++; 79b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise } 80b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise for (i = 0; i < RANDOM_SIZE; i++) 817acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold kfifo_in(fifo, 82b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise (unsigned char *) &rarray[i], 83b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise sizeof(u32)); 84b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise } else 85b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise for (i = skip_low; i < nr - skip_high; i++) 867acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold kfifo_in(fifo, (unsigned char *) &i, sizeof(u32)); 87b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 88b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise for (i = 0; i < skip_low + skip_high; i++) 899842c38e917636fa7dc6b88aff17a8f1fd7f0cc0Stefani Seibold if (kfifo_out_locked(fifo, (unsigned char *) &entry, 909842c38e917636fa7dc6b88aff17a8f1fd7f0cc0Stefani Seibold sizeof(u32), fifo_lock) != sizeof(u32)) 919842c38e917636fa7dc6b88aff17a8f1fd7f0cc0Stefani Seibold break; 92b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return 0; 93b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 94b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 9545465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seiboldstatic int cxio_init_resource_fifo(struct kfifo *fifo, spinlock_t * fifo_lock, 96b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise u32 nr, u32 skip_low, u32 skip_high) 97b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 98b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low, 99b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise skip_high, 0)); 100b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 101b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 10245465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seiboldstatic int cxio_init_resource_fifo_random(struct kfifo *fifo, 103b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise spinlock_t * fifo_lock, 104b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise u32 nr, u32 skip_low, u32 skip_high) 105b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 106b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 107b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low, 108b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise skip_high, 1)); 109b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 110b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 111b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisestatic int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p) 112b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 113b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise u32 i; 114b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 115b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise spin_lock_init(&rdev_p->rscp->qpid_fifo_lock); 116b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 11745465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold if (kfifo_alloc(&rdev_p->rscp->qpid_fifo, T3_MAX_NUM_QP * sizeof(u32), 118c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold GFP_KERNEL)) 119b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return -ENOMEM; 120b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 121b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise for (i = 16; i < T3_MAX_NUM_QP; i++) 122b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise if (!(i & rdev_p->qpmask)) 1237acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold kfifo_in(&rdev_p->rscp->qpid_fifo, 124b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise (unsigned char *) &i, sizeof(u32)); 125b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return 0; 126b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 127b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 128b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wiseint cxio_hal_init_rhdl_resource(u32 nr_rhdl) 129b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 130b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return cxio_init_resource_fifo(&rhdl_fifo, &rhdl_fifo_lock, nr_rhdl, 1, 131b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 0); 132b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 133b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 134b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisevoid cxio_hal_destroy_rhdl_resource(void) 135b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 13645465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold kfifo_free(&rhdl_fifo); 137b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 138b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 139b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise/* nr_* must be power of 2 */ 140b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wiseint cxio_hal_init_resource(struct cxio_rdev *rdev_p, 141b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise u32 nr_tpt, u32 nr_pbl, 142b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise u32 nr_rqt, u32 nr_qpid, u32 nr_cqid, u32 nr_pdid) 143b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 144b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise int err = 0; 145b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise struct cxio_hal_resource *rscp; 146b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 147b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise rscp = kmalloc(sizeof(*rscp), GFP_KERNEL); 148b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise if (!rscp) 149b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return -ENOMEM; 150b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise rdev_p->rscp = rscp; 151b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise err = cxio_init_resource_fifo_random(&rscp->tpt_fifo, 152b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise &rscp->tpt_fifo_lock, 153b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise nr_tpt, 1, 0); 154b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise if (err) 155b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise goto tpt_err; 156b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise err = cxio_init_qpid_fifo(rdev_p); 157b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise if (err) 158b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise goto qpid_err; 159b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise err = cxio_init_resource_fifo(&rscp->cqid_fifo, &rscp->cqid_fifo_lock, 160b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise nr_cqid, 1, 0); 161b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise if (err) 162b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise goto cqid_err; 163b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise err = cxio_init_resource_fifo(&rscp->pdid_fifo, &rscp->pdid_fifo_lock, 164b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise nr_pdid, 1, 0); 165b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise if (err) 166b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise goto pdid_err; 167b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return 0; 168b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisepdid_err: 16945465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold kfifo_free(&rscp->cqid_fifo); 170b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisecqid_err: 17145465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold kfifo_free(&rscp->qpid_fifo); 172b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wiseqpid_err: 17345465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold kfifo_free(&rscp->tpt_fifo); 174b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisetpt_err: 175b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return -ENOMEM; 176b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 177b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 178b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise/* 179b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * returns 0 if no resource available 180b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise */ 181c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seiboldstatic u32 cxio_hal_get_resource(struct kfifo *fifo, spinlock_t * lock) 182b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 183b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise u32 entry; 1847acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold if (kfifo_out_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock)) 185b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return entry; 186b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise else 187b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return 0; /* fifo emptry */ 188b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 189b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 190c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seiboldstatic void cxio_hal_put_resource(struct kfifo *fifo, spinlock_t * lock, 191c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold u32 entry) 192b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 193c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold BUG_ON( 1947acd72eb85f1c7a15e8b5eb554994949241737f1Stefani Seibold kfifo_in_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock) 195c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold == 0); 196b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 197b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 198b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wiseu32 cxio_hal_get_stag(struct cxio_hal_resource *rscp) 199b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 200c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold return cxio_hal_get_resource(&rscp->tpt_fifo, &rscp->tpt_fifo_lock); 201b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 202b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 203b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisevoid cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag) 204b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 205c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold cxio_hal_put_resource(&rscp->tpt_fifo, &rscp->tpt_fifo_lock, stag); 206b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 207b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 208b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wiseu32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp) 209b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 210c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold u32 qpid = cxio_hal_get_resource(&rscp->qpid_fifo, 211c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold &rscp->qpid_fifo_lock); 2123371836383d63b627b228875f5ac63023cbf11d2Harvey Harrison PDBG("%s qpid 0x%x\n", __func__, qpid); 213b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return qpid; 214b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 215b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 216b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisevoid cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid) 217b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 2183371836383d63b627b228875f5ac63023cbf11d2Harvey Harrison PDBG("%s qpid 0x%x\n", __func__, qpid); 219c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold cxio_hal_put_resource(&rscp->qpid_fifo, &rscp->qpid_fifo_lock, qpid); 220b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 221b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 222b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wiseu32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp) 223b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 224c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold return cxio_hal_get_resource(&rscp->cqid_fifo, &rscp->cqid_fifo_lock); 225b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 226b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 227b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisevoid cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid) 228b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 229c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold cxio_hal_put_resource(&rscp->cqid_fifo, &rscp->cqid_fifo_lock, cqid); 230b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 231b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 232b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wiseu32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp) 233b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 234c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold return cxio_hal_get_resource(&rscp->pdid_fifo, &rscp->pdid_fifo_lock); 235b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 236b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 237b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisevoid cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid) 238b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 239c1e13f25674ed564948ecb7dfe5f83e578892896Stefani Seibold cxio_hal_put_resource(&rscp->pdid_fifo, &rscp->pdid_fifo_lock, pdid); 240b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 241b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 242b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisevoid cxio_hal_destroy_resource(struct cxio_hal_resource *rscp) 243b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 24445465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold kfifo_free(&rscp->tpt_fifo); 24545465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold kfifo_free(&rscp->cqid_fifo); 24645465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold kfifo_free(&rscp->qpid_fifo); 24745465487897a1c6d508b14b904dc5777f7ec7e04Stefani Seibold kfifo_free(&rscp->pdid_fifo); 248b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise kfree(rscp); 249b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 250b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 251b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise/* 252b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * PBL Memory Manager. Uses Linux generic allocator. 253b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise */ 254b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 255b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise#define MIN_PBL_SHIFT 8 /* 256B == min PBL size (32 entries) */ 256b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 257b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wiseu32 cxio_hal_pblpool_alloc(struct cxio_rdev *rdev_p, int size) 258b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 259b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise unsigned long addr = gen_pool_alloc(rdev_p->pbl_pool, size); 2603371836383d63b627b228875f5ac63023cbf11d2Harvey Harrison PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size); 261b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return (u32)addr; 262b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 263b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 264b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisevoid cxio_hal_pblpool_free(struct cxio_rdev *rdev_p, u32 addr, int size) 265b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 2663371836383d63b627b228875f5ac63023cbf11d2Harvey Harrison PDBG("%s addr 0x%x size %d\n", __func__, addr, size); 267b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise gen_pool_free(rdev_p->pbl_pool, (unsigned long)addr, size); 268b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 269b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 270b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wiseint cxio_hal_pblpool_create(struct cxio_rdev *rdev_p) 271b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 2720e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier unsigned pbl_start, pbl_chunk; 2730e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier 274b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise rdev_p->pbl_pool = gen_pool_create(MIN_PBL_SHIFT, -1); 2750e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier if (!rdev_p->pbl_pool) 2760e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier return -ENOMEM; 2770e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier 2780e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier pbl_start = rdev_p->rnic_info.pbl_base; 2790e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier pbl_chunk = rdev_p->rnic_info.pbl_top - pbl_start + 1; 2800e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier 2810e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier while (pbl_start < rdev_p->rnic_info.pbl_top) { 2820e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier pbl_chunk = min(rdev_p->rnic_info.pbl_top - pbl_start + 1, 2830e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier pbl_chunk); 2840e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier if (gen_pool_add(rdev_p->pbl_pool, pbl_start, pbl_chunk, -1)) { 2850e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier PDBG("%s failed to add PBL chunk (%x/%x)\n", 2860e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier __func__, pbl_start, pbl_chunk); 2870e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier if (pbl_chunk <= 1024 << MIN_PBL_SHIFT) { 2880e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier printk(KERN_WARNING MOD "%s: Failed to add all PBL chunks (%x/%x)\n", 2890e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier __func__, pbl_start, rdev_p->rnic_info.pbl_top - pbl_start); 2900e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier return 0; 2910e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier } 2920e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier pbl_chunk >>= 1; 2930e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier } else { 2940e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier PDBG("%s added PBL chunk (%x/%x)\n", 2950e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier __func__, pbl_start, pbl_chunk); 2960e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier pbl_start += pbl_chunk; 2970e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier } 2980e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier } 2990e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier 3000e9913362a967377eb886bbdf305ec58aa07a878Roland Dreier return 0; 301b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 302b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 303b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisevoid cxio_hal_pblpool_destroy(struct cxio_rdev *rdev_p) 304b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 305b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise gen_pool_destroy(rdev_p->pbl_pool); 306b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 307b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 308b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise/* 309b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise * RQT Memory Manager. Uses Linux generic allocator. 310b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise */ 311b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 312b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise#define MIN_RQT_SHIFT 10 /* 1KB == mini RQT size (16 entries) */ 313b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise#define RQT_CHUNK 2*1024*1024 314b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 315b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wiseu32 cxio_hal_rqtpool_alloc(struct cxio_rdev *rdev_p, int size) 316b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 317b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise unsigned long addr = gen_pool_alloc(rdev_p->rqt_pool, size << 6); 3183371836383d63b627b228875f5ac63023cbf11d2Harvey Harrison PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size << 6); 319b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return (u32)addr; 320b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 321b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 322b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisevoid cxio_hal_rqtpool_free(struct cxio_rdev *rdev_p, u32 addr, int size) 323b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 3243371836383d63b627b228875f5ac63023cbf11d2Harvey Harrison PDBG("%s addr 0x%x size %d\n", __func__, addr, size << 6); 325b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise gen_pool_free(rdev_p->rqt_pool, (unsigned long)addr, size << 6); 326b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 327b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 328b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wiseint cxio_hal_rqtpool_create(struct cxio_rdev *rdev_p) 329b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 330b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise unsigned long i; 331b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise rdev_p->rqt_pool = gen_pool_create(MIN_RQT_SHIFT, -1); 332b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise if (rdev_p->rqt_pool) 333b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise for (i = rdev_p->rnic_info.rqt_base; 334b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise i <= rdev_p->rnic_info.rqt_top - RQT_CHUNK + 1; 335b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise i += RQT_CHUNK) 336b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise gen_pool_add(rdev_p->rqt_pool, i, RQT_CHUNK, -1); 337b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise return rdev_p->rqt_pool ? 0 : -ENOMEM; 338b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 339b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise 340b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wisevoid cxio_hal_rqtpool_destroy(struct cxio_rdev *rdev_p) 341b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise{ 342b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise gen_pool_destroy(rdev_p->rqt_pool); 343b038ced7b3705bf0ac9b30e118af0f56ab48b847Steve Wise} 344