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