1/*
2 * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
3 * Copyright (c) 2006, 2007 Cisco Systems, Inc.  All rights reserved.
4 *
5 * This software is available to you under a choice of one of two
6 * licenses.  You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
10 *
11 *     Redistribution and use in source and binary forms, with or
12 *     without modification, are permitted provided that the following
13 *     conditions are met:
14 *
15 *      - Redistributions of source code must retain the above
16 *        copyright notice, this list of conditions and the following
17 *        disclaimer.
18 *
19 *      - Redistributions in binary form must reproduce the above
20 *        copyright notice, this list of conditions and the following
21 *        disclaimer in the documentation and/or other materials
22 *        provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34#ifndef MLX4_ICM_H
35#define MLX4_ICM_H
36
37#include <linux/list.h>
38/*#include <linux/pci.h>
39 #include <linux/mutex.h>
40 */
41#include <linux/scatterlist.h>
42
43#include "mlx4.h"
44
45#define MLX4_ICM_CHUNK_LEN						\
46	((256 - sizeof (struct list_head) - 2 * sizeof (int)) /		\
47	 (sizeof (struct scatterlist)))
48
49enum {
50	MLX4_ICM_PAGE_SHIFT = 12, MLX4_ICM_PAGE_SIZE = 1 << MLX4_ICM_PAGE_SHIFT,
51};
52struct mlx4_icm_chunk {
53	struct list_head list;
54	int npages;
55	int nsg;
56	struct scatterlist mem[MLX4_ICM_CHUNK_LEN];
57};
58struct mlx4_icm {
59	struct list_head chunk_list;
60	int refcount;
61};
62struct mlx4_icm_iter {
63	struct mlx4_icm *icm;
64	struct mlx4_icm_chunk *chunk;
65	int page_idx;
66};
67/*
68 struct mlx4_dev;
69 */
70
71struct mlx4_icm *mlx4_alloc_icm(struct mlx4_priv *priv, int npages,
72		int coherent);
73/*
74 void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent);
75 */
76int mlx4_table_get(struct mlx4_priv *priv, struct mlx4_icm_table *table,
77		u32 obj);
78void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj);
79int mlx4_table_get_range(struct mlx4_priv *priv, struct mlx4_icm_table *table,
80		u32 start, u32 end);
81/*
82 void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
83 u32 start, u32 end);
84 */
85
86int mlx4_init_icm_table(struct mlx4_priv *priv, struct mlx4_icm_table *table,
87		u64 virt, int obj_size, u64 nobj, int reserved, int use_lowmem,
88		int use_coherent);
89/*
90 void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table);
91 */
92void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj,
93		genpaddr_t *dma_handle);
94static inline void mlx4_icm_first(struct mlx4_icm *icm,
95		struct mlx4_icm_iter *iter) {
96	iter->icm = icm;
97	iter->chunk =
98			list_empty(&icm->chunk_list) ?
99					NULL :
100					list_entry(icm->chunk_list.next, struct mlx4_icm_chunk,
101							list);
102	iter->page_idx = 0;
103}
104
105static inline int mlx4_icm_last(struct mlx4_icm_iter *iter) {
106	return !iter->chunk;
107}
108
109static inline void mlx4_icm_next(struct mlx4_icm_iter *iter) {
110	if (++iter->page_idx >= iter->chunk->nsg) {
111		if (iter->chunk->list.next == &iter->icm->chunk_list) {
112			iter->chunk = NULL;
113			return;
114		}
115
116		iter->chunk = list_entry(iter->chunk->list.next, struct mlx4_icm_chunk,
117				list);
118		iter->page_idx = 0;
119	}
120}
121
122static inline genpaddr_t mlx4_icm_addr(struct mlx4_icm_iter *iter) {
123	return sg_dma_address(&iter->chunk->mem[iter->page_idx]);
124}
125
126static inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter) {
127	return iter->chunk->mem[iter->page_idx].length;
128}
129
130int mlx4_MAP_ICM_AUX(struct mlx4_priv *priv, struct mlx4_icm *icm);
131/*int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev);*/
132
133#endif /* MLX4_ICM_H */
134