162306a36Sopenharmony_ci/* Copyright 2008 - 2016 Freescale Semiconductor, Inc.
262306a36Sopenharmony_ci *
362306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
462306a36Sopenharmony_ci * modification, are permitted provided that the following conditions are met:
562306a36Sopenharmony_ci *     * Redistributions of source code must retain the above copyright
662306a36Sopenharmony_ci *	 notice, this list of conditions and the following disclaimer.
762306a36Sopenharmony_ci *     * Redistributions in binary form must reproduce the above copyright
862306a36Sopenharmony_ci *	 notice, this list of conditions and the following disclaimer in the
962306a36Sopenharmony_ci *	 documentation and/or other materials provided with the distribution.
1062306a36Sopenharmony_ci *     * Neither the name of Freescale Semiconductor nor the
1162306a36Sopenharmony_ci *	 names of its contributors may be used to endorse or promote products
1262306a36Sopenharmony_ci *	 derived from this software without specific prior written permission.
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * ALTERNATIVELY, this software may be distributed under the terms of the
1562306a36Sopenharmony_ci * GNU General Public License ("GPL") as published by the Free Software
1662306a36Sopenharmony_ci * Foundation, either version 2 of that License or (at your option) any
1762306a36Sopenharmony_ci * later version.
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
2062306a36Sopenharmony_ci * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2162306a36Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2262306a36Sopenharmony_ci * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
2362306a36Sopenharmony_ci * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2462306a36Sopenharmony_ci * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2562306a36Sopenharmony_ci * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2662306a36Sopenharmony_ci * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2762306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2862306a36Sopenharmony_ci * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2962306a36Sopenharmony_ci */
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#include "bman_test.h"
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define NUM_BUFS	93
3462306a36Sopenharmony_ci#define LOOPS		3
3562306a36Sopenharmony_ci#define BMAN_TOKEN_MASK 0x00FFFFFFFFFFLLU
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic struct bman_pool *pool;
3862306a36Sopenharmony_cistatic struct bm_buffer bufs_in[NUM_BUFS] ____cacheline_aligned;
3962306a36Sopenharmony_cistatic struct bm_buffer bufs_out[NUM_BUFS] ____cacheline_aligned;
4062306a36Sopenharmony_cistatic int bufs_received;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic void bufs_init(void)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	int i;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	for (i = 0; i < NUM_BUFS; i++)
4762306a36Sopenharmony_ci		bm_buffer_set64(&bufs_in[i], 0xfedc01234567LLU * i);
4862306a36Sopenharmony_ci	bufs_received = 0;
4962306a36Sopenharmony_ci}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic inline int bufs_cmp(const struct bm_buffer *a, const struct bm_buffer *b)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	if (bman_ip_rev == BMAN_REV20 || bman_ip_rev == BMAN_REV21) {
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci		/*
5662306a36Sopenharmony_ci		 * On SoCs with BMan revison 2.0, BMan only respects the 40
5762306a36Sopenharmony_ci		 * LS-bits of buffer addresses, masking off the upper 8-bits on
5862306a36Sopenharmony_ci		 * release commands. The API provides for 48-bit addresses
5962306a36Sopenharmony_ci		 * because some SoCs support all 48-bits. When generating
6062306a36Sopenharmony_ci		 * garbage addresses for testing, we either need to zero the
6162306a36Sopenharmony_ci		 * upper 8-bits when releasing to BMan (otherwise we'll be
6262306a36Sopenharmony_ci		 * disappointed when the buffers we acquire back from BMan
6362306a36Sopenharmony_ci		 * don't match), or we need to mask the upper 8-bits off when
6462306a36Sopenharmony_ci		 * comparing. We do the latter.
6562306a36Sopenharmony_ci		 */
6662306a36Sopenharmony_ci		if ((bm_buffer_get64(a) & BMAN_TOKEN_MASK) <
6762306a36Sopenharmony_ci		    (bm_buffer_get64(b) & BMAN_TOKEN_MASK))
6862306a36Sopenharmony_ci			return -1;
6962306a36Sopenharmony_ci		if ((bm_buffer_get64(a) & BMAN_TOKEN_MASK) >
7062306a36Sopenharmony_ci		    (bm_buffer_get64(b) & BMAN_TOKEN_MASK))
7162306a36Sopenharmony_ci			return 1;
7262306a36Sopenharmony_ci	} else {
7362306a36Sopenharmony_ci		if (bm_buffer_get64(a) < bm_buffer_get64(b))
7462306a36Sopenharmony_ci			return -1;
7562306a36Sopenharmony_ci		if (bm_buffer_get64(a) > bm_buffer_get64(b))
7662306a36Sopenharmony_ci			return 1;
7762306a36Sopenharmony_ci	}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	return 0;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic void bufs_confirm(void)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	int i, j;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	for (i = 0; i < NUM_BUFS; i++) {
8762306a36Sopenharmony_ci		int matches = 0;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci		for (j = 0; j < NUM_BUFS; j++)
9062306a36Sopenharmony_ci			if (!bufs_cmp(&bufs_in[i], &bufs_out[j]))
9162306a36Sopenharmony_ci				matches++;
9262306a36Sopenharmony_ci		WARN_ON(matches != 1);
9362306a36Sopenharmony_ci	}
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/* test */
9762306a36Sopenharmony_civoid bman_test_api(void)
9862306a36Sopenharmony_ci{
9962306a36Sopenharmony_ci	int i, loops = LOOPS;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	bufs_init();
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	pr_info("%s(): Starting\n", __func__);
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	pool = bman_new_pool();
10662306a36Sopenharmony_ci	if (!pool) {
10762306a36Sopenharmony_ci		pr_crit("bman_new_pool() failed\n");
10862306a36Sopenharmony_ci		goto failed;
10962306a36Sopenharmony_ci	}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	/* Release buffers */
11262306a36Sopenharmony_cido_loop:
11362306a36Sopenharmony_ci	i = 0;
11462306a36Sopenharmony_ci	while (i < NUM_BUFS) {
11562306a36Sopenharmony_ci		int num = 8;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci		if (i + num > NUM_BUFS)
11862306a36Sopenharmony_ci			num = NUM_BUFS - i;
11962306a36Sopenharmony_ci		if (bman_release(pool, bufs_in + i, num)) {
12062306a36Sopenharmony_ci			pr_crit("bman_release() failed\n");
12162306a36Sopenharmony_ci			goto failed;
12262306a36Sopenharmony_ci		}
12362306a36Sopenharmony_ci		i += num;
12462306a36Sopenharmony_ci	}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	/* Acquire buffers */
12762306a36Sopenharmony_ci	while (i > 0) {
12862306a36Sopenharmony_ci		int tmp, num = 8;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci		if (num > i)
13162306a36Sopenharmony_ci			num = i;
13262306a36Sopenharmony_ci		tmp = bman_acquire(pool, bufs_out + i - num, num);
13362306a36Sopenharmony_ci		WARN_ON(tmp != num);
13462306a36Sopenharmony_ci		i -= num;
13562306a36Sopenharmony_ci	}
13662306a36Sopenharmony_ci	i = bman_acquire(pool, NULL, 1);
13762306a36Sopenharmony_ci	WARN_ON(i > 0);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	bufs_confirm();
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	if (--loops)
14262306a36Sopenharmony_ci		goto do_loop;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	/* Clean up */
14562306a36Sopenharmony_ci	bman_free_pool(pool);
14662306a36Sopenharmony_ci	pr_info("%s(): Finished\n", __func__);
14762306a36Sopenharmony_ci	return;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cifailed:
15062306a36Sopenharmony_ci	WARN_ON(1);
15162306a36Sopenharmony_ci}
152