mthca_memfree.c revision e8edc6e03a5c8562dc70a6d969f732bdb355a7e7
1/*
2 * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
3 * Copyright (c) 2005 Cisco Systems.  All rights reserved.
4 * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
5 *
6 * This software is available to you under a choice of one of two
7 * licenses.  You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 *     Redistribution and use in source and binary forms, with or
13 *     without modification, are permitted provided that the following
14 *     conditions are met:
15 *
16 *      - Redistributions of source code must retain the above
17 *        copyright notice, this list of conditions and the following
18 *        disclaimer.
19 *
20 *      - Redistributions in binary form must reproduce the above
21 *        copyright notice, this list of conditions and the following
22 *        disclaimer in the documentation and/or other materials
23 *        provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 *
34 * $Id$
35 */
36
37#include <linux/mm.h>
38#include <linux/scatterlist.h>
39#include <linux/sched.h>
40
41#include <asm/page.h>
42
43#include "mthca_memfree.h"
44#include "mthca_dev.h"
45#include "mthca_cmd.h"
46
47/*
48 * We allocate in as big chunks as we can, up to a maximum of 256 KB
49 * per chunk.
50 */
51enum {
52	MTHCA_ICM_ALLOC_SIZE   = 1 << 18,
53	MTHCA_TABLE_CHUNK_SIZE = 1 << 18
54};
55
56struct mthca_user_db_table {
57	struct mutex mutex;
58	struct {
59		u64                uvirt;
60		struct scatterlist mem;
61		int                refcount;
62	}                page[0];
63};
64
65static void mthca_free_icm_pages(struct mthca_dev *dev, struct mthca_icm_chunk *chunk)
66{
67	int i;
68
69	if (chunk->nsg > 0)
70		pci_unmap_sg(dev->pdev, chunk->mem, chunk->npages,
71			     PCI_DMA_BIDIRECTIONAL);
72
73	for (i = 0; i < chunk->npages; ++i)
74		__free_pages(chunk->mem[i].page,
75			     get_order(chunk->mem[i].length));
76}
77
78static void mthca_free_icm_coherent(struct mthca_dev *dev, struct mthca_icm_chunk *chunk)
79{
80	int i;
81
82	for (i = 0; i < chunk->npages; ++i) {
83		dma_free_coherent(&dev->pdev->dev, chunk->mem[i].length,
84				  lowmem_page_address(chunk->mem[i].page),
85				  sg_dma_address(&chunk->mem[i]));
86	}
87}
88
89void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm, int coherent)
90{
91	struct mthca_icm_chunk *chunk, *tmp;
92
93	if (!icm)
94		return;
95
96	list_for_each_entry_safe(chunk, tmp, &icm->chunk_list, list) {
97		if (coherent)
98			mthca_free_icm_coherent(dev, chunk);
99		else
100			mthca_free_icm_pages(dev, chunk);
101
102		kfree(chunk);
103	}
104
105	kfree(icm);
106}
107
108static int mthca_alloc_icm_pages(struct scatterlist *mem, int order, gfp_t gfp_mask)
109{
110	mem->page = alloc_pages(gfp_mask, order);
111	if (!mem->page)
112		return -ENOMEM;
113
114	mem->length = PAGE_SIZE << order;
115	mem->offset = 0;
116	return 0;
117}
118
119static int mthca_alloc_icm_coherent(struct device *dev, struct scatterlist *mem,
120				    int order, gfp_t gfp_mask)
121{
122	void *buf = dma_alloc_coherent(dev, PAGE_SIZE << order, &sg_dma_address(mem),
123				       gfp_mask);
124	if (!buf)
125		return -ENOMEM;
126
127	sg_set_buf(mem, buf, PAGE_SIZE << order);
128	BUG_ON(mem->offset);
129	sg_dma_len(mem) = PAGE_SIZE << order;
130	return 0;
131}
132
133struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages,
134				  gfp_t gfp_mask, int coherent)
135{
136	struct mthca_icm *icm;
137	struct mthca_icm_chunk *chunk = NULL;
138	int cur_order;
139	int ret;
140
141	/* We use sg_set_buf for coherent allocs, which assumes low memory */
142	BUG_ON(coherent && (gfp_mask & __GFP_HIGHMEM));
143
144	icm = kmalloc(sizeof *icm, gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
145	if (!icm)
146		return icm;
147
148	icm->refcount = 0;
149	INIT_LIST_HEAD(&icm->chunk_list);
150
151	cur_order = get_order(MTHCA_ICM_ALLOC_SIZE);
152
153	while (npages > 0) {
154		if (!chunk) {
155			chunk = kmalloc(sizeof *chunk,
156					gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
157			if (!chunk)
158				goto fail;
159
160			chunk->npages = 0;
161			chunk->nsg    = 0;
162			list_add_tail(&chunk->list, &icm->chunk_list);
163		}
164
165		while (1 << cur_order > npages)
166			--cur_order;
167
168		if (coherent)
169			ret = mthca_alloc_icm_coherent(&dev->pdev->dev,
170						       &chunk->mem[chunk->npages],
171						       cur_order, gfp_mask);
172		else
173			ret = mthca_alloc_icm_pages(&chunk->mem[chunk->npages],
174						    cur_order, gfp_mask);
175
176		if (!ret) {
177			++chunk->npages;
178
179			if (coherent)
180				++chunk->nsg;
181			else if (chunk->npages == MTHCA_ICM_CHUNK_LEN) {
182				chunk->nsg = pci_map_sg(dev->pdev, chunk->mem,
183							chunk->npages,
184							PCI_DMA_BIDIRECTIONAL);
185
186				if (chunk->nsg <= 0)
187					goto fail;
188			}
189
190			if (chunk->npages == MTHCA_ICM_CHUNK_LEN)
191				chunk = NULL;
192
193			npages -= 1 << cur_order;
194		} else {
195			--cur_order;
196			if (cur_order < 0)
197				goto fail;
198		}
199	}
200
201	if (!coherent && chunk) {
202		chunk->nsg = pci_map_sg(dev->pdev, chunk->mem,
203					chunk->npages,
204					PCI_DMA_BIDIRECTIONAL);
205
206		if (chunk->nsg <= 0)
207			goto fail;
208	}
209
210	return icm;
211
212fail:
213	mthca_free_icm(dev, icm, coherent);
214	return NULL;
215}
216
217int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int obj)
218{
219	int i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE;
220	int ret = 0;
221	u8 status;
222
223	mutex_lock(&table->mutex);
224
225	if (table->icm[i]) {
226		++table->icm[i]->refcount;
227		goto out;
228	}
229
230	table->icm[i] = mthca_alloc_icm(dev, MTHCA_TABLE_CHUNK_SIZE >> PAGE_SHIFT,
231					(table->lowmem ? GFP_KERNEL : GFP_HIGHUSER) |
232					__GFP_NOWARN, table->coherent);
233	if (!table->icm[i]) {
234		ret = -ENOMEM;
235		goto out;
236	}
237
238	if (mthca_MAP_ICM(dev, table->icm[i], table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
239			  &status) || status) {
240		mthca_free_icm(dev, table->icm[i], table->coherent);
241		table->icm[i] = NULL;
242		ret = -ENOMEM;
243		goto out;
244	}
245
246	++table->icm[i]->refcount;
247
248out:
249	mutex_unlock(&table->mutex);
250	return ret;
251}
252
253void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj)
254{
255	int i;
256	u8 status;
257
258	if (!mthca_is_memfree(dev))
259		return;
260
261	i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE;
262
263	mutex_lock(&table->mutex);
264
265	if (--table->icm[i]->refcount == 0) {
266		mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
267				MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
268				&status);
269		mthca_free_icm(dev, table->icm[i], table->coherent);
270		table->icm[i] = NULL;
271	}
272
273	mutex_unlock(&table->mutex);
274}
275
276void *mthca_table_find(struct mthca_icm_table *table, int obj, dma_addr_t *dma_handle)
277{
278	int idx, offset, dma_offset, i;
279	struct mthca_icm_chunk *chunk;
280	struct mthca_icm *icm;
281	struct page *page = NULL;
282
283	if (!table->lowmem)
284		return NULL;
285
286	mutex_lock(&table->mutex);
287
288	idx = (obj & (table->num_obj - 1)) * table->obj_size;
289	icm = table->icm[idx / MTHCA_TABLE_CHUNK_SIZE];
290	dma_offset = offset = idx % MTHCA_TABLE_CHUNK_SIZE;
291
292	if (!icm)
293		goto out;
294
295	list_for_each_entry(chunk, &icm->chunk_list, list) {
296		for (i = 0; i < chunk->npages; ++i) {
297			if (dma_handle && dma_offset >= 0) {
298				if (sg_dma_len(&chunk->mem[i]) > dma_offset)
299					*dma_handle = sg_dma_address(&chunk->mem[i]) +
300						dma_offset;
301				dma_offset -= sg_dma_len(&chunk->mem[i]);
302			}
303			/* DMA mapping can merge pages but not split them,
304			 * so if we found the page, dma_handle has already
305			 * been assigned to. */
306			if (chunk->mem[i].length > offset) {
307				page = chunk->mem[i].page;
308				goto out;
309			}
310			offset -= chunk->mem[i].length;
311		}
312	}
313
314out:
315	mutex_unlock(&table->mutex);
316	return page ? lowmem_page_address(page) + offset : NULL;
317}
318
319int mthca_table_get_range(struct mthca_dev *dev, struct mthca_icm_table *table,
320			  int start, int end)
321{
322	int inc = MTHCA_TABLE_CHUNK_SIZE / table->obj_size;
323	int i, err;
324
325	for (i = start; i <= end; i += inc) {
326		err = mthca_table_get(dev, table, i);
327		if (err)
328			goto fail;
329	}
330
331	return 0;
332
333fail:
334	while (i > start) {
335		i -= inc;
336		mthca_table_put(dev, table, i);
337	}
338
339	return err;
340}
341
342void mthca_table_put_range(struct mthca_dev *dev, struct mthca_icm_table *table,
343			   int start, int end)
344{
345	int i;
346
347	if (!mthca_is_memfree(dev))
348		return;
349
350	for (i = start; i <= end; i += MTHCA_TABLE_CHUNK_SIZE / table->obj_size)
351		mthca_table_put(dev, table, i);
352}
353
354struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
355					      u64 virt, int obj_size,
356					      int nobj, int reserved,
357					      int use_lowmem, int use_coherent)
358{
359	struct mthca_icm_table *table;
360	int num_icm;
361	unsigned chunk_size;
362	int i;
363	u8 status;
364
365	num_icm = (obj_size * nobj + MTHCA_TABLE_CHUNK_SIZE - 1) / MTHCA_TABLE_CHUNK_SIZE;
366
367	table = kmalloc(sizeof *table + num_icm * sizeof *table->icm, GFP_KERNEL);
368	if (!table)
369		return NULL;
370
371	table->virt     = virt;
372	table->num_icm  = num_icm;
373	table->num_obj  = nobj;
374	table->obj_size = obj_size;
375	table->lowmem   = use_lowmem;
376	table->coherent = use_coherent;
377	mutex_init(&table->mutex);
378
379	for (i = 0; i < num_icm; ++i)
380		table->icm[i] = NULL;
381
382	for (i = 0; i * MTHCA_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) {
383		chunk_size = MTHCA_TABLE_CHUNK_SIZE;
384		if ((i + 1) * MTHCA_TABLE_CHUNK_SIZE > nobj * obj_size)
385			chunk_size = nobj * obj_size - i * MTHCA_TABLE_CHUNK_SIZE;
386
387		table->icm[i] = mthca_alloc_icm(dev, chunk_size >> PAGE_SHIFT,
388						(use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) |
389						__GFP_NOWARN, use_coherent);
390		if (!table->icm[i])
391			goto err;
392		if (mthca_MAP_ICM(dev, table->icm[i], virt + i * MTHCA_TABLE_CHUNK_SIZE,
393				  &status) || status) {
394			mthca_free_icm(dev, table->icm[i], table->coherent);
395			table->icm[i] = NULL;
396			goto err;
397		}
398
399		/*
400		 * Add a reference to this ICM chunk so that it never
401		 * gets freed (since it contains reserved firmware objects).
402		 */
403		++table->icm[i]->refcount;
404	}
405
406	return table;
407
408err:
409	for (i = 0; i < num_icm; ++i)
410		if (table->icm[i]) {
411			mthca_UNMAP_ICM(dev, virt + i * MTHCA_TABLE_CHUNK_SIZE,
412					MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
413				        &status);
414			mthca_free_icm(dev, table->icm[i], table->coherent);
415		}
416
417	kfree(table);
418
419	return NULL;
420}
421
422void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table)
423{
424	int i;
425	u8 status;
426
427	for (i = 0; i < table->num_icm; ++i)
428		if (table->icm[i]) {
429			mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
430					MTHCA_TABLE_CHUNK_SIZE / MTHCA_ICM_PAGE_SIZE,
431					&status);
432			mthca_free_icm(dev, table->icm[i], table->coherent);
433		}
434
435	kfree(table);
436}
437
438static u64 mthca_uarc_virt(struct mthca_dev *dev, struct mthca_uar *uar, int page)
439{
440	return dev->uar_table.uarc_base +
441		uar->index * dev->uar_table.uarc_size +
442		page * MTHCA_ICM_PAGE_SIZE;
443}
444
445int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
446		      struct mthca_user_db_table *db_tab, int index, u64 uaddr)
447{
448	int ret = 0;
449	u8 status;
450	int i;
451
452	if (!mthca_is_memfree(dev))
453		return 0;
454
455	if (index < 0 || index > dev->uar_table.uarc_size / 8)
456		return -EINVAL;
457
458	mutex_lock(&db_tab->mutex);
459
460	i = index / MTHCA_DB_REC_PER_PAGE;
461
462	if ((db_tab->page[i].refcount >= MTHCA_DB_REC_PER_PAGE)       ||
463	    (db_tab->page[i].uvirt && db_tab->page[i].uvirt != uaddr) ||
464	    (uaddr & 4095)) {
465		ret = -EINVAL;
466		goto out;
467	}
468
469	if (db_tab->page[i].refcount) {
470		++db_tab->page[i].refcount;
471		goto out;
472	}
473
474	ret = get_user_pages(current, current->mm, uaddr & PAGE_MASK, 1, 1, 0,
475			     &db_tab->page[i].mem.page, NULL);
476	if (ret < 0)
477		goto out;
478
479	db_tab->page[i].mem.length = MTHCA_ICM_PAGE_SIZE;
480	db_tab->page[i].mem.offset = uaddr & ~PAGE_MASK;
481
482	ret = pci_map_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
483	if (ret < 0) {
484		put_page(db_tab->page[i].mem.page);
485		goto out;
486	}
487
488	ret = mthca_MAP_ICM_page(dev, sg_dma_address(&db_tab->page[i].mem),
489				 mthca_uarc_virt(dev, uar, i), &status);
490	if (!ret && status)
491		ret = -EINVAL;
492	if (ret) {
493		pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
494		put_page(db_tab->page[i].mem.page);
495		goto out;
496	}
497
498	db_tab->page[i].uvirt    = uaddr;
499	db_tab->page[i].refcount = 1;
500
501out:
502	mutex_unlock(&db_tab->mutex);
503	return ret;
504}
505
506void mthca_unmap_user_db(struct mthca_dev *dev, struct mthca_uar *uar,
507			 struct mthca_user_db_table *db_tab, int index)
508{
509	if (!mthca_is_memfree(dev))
510		return;
511
512	/*
513	 * To make our bookkeeping simpler, we don't unmap DB
514	 * pages until we clean up the whole db table.
515	 */
516
517	mutex_lock(&db_tab->mutex);
518
519	--db_tab->page[index / MTHCA_DB_REC_PER_PAGE].refcount;
520
521	mutex_unlock(&db_tab->mutex);
522}
523
524struct mthca_user_db_table *mthca_init_user_db_tab(struct mthca_dev *dev)
525{
526	struct mthca_user_db_table *db_tab;
527	int npages;
528	int i;
529
530	if (!mthca_is_memfree(dev))
531		return NULL;
532
533	npages = dev->uar_table.uarc_size / MTHCA_ICM_PAGE_SIZE;
534	db_tab = kmalloc(sizeof *db_tab + npages * sizeof *db_tab->page, GFP_KERNEL);
535	if (!db_tab)
536		return ERR_PTR(-ENOMEM);
537
538	mutex_init(&db_tab->mutex);
539	for (i = 0; i < npages; ++i) {
540		db_tab->page[i].refcount = 0;
541		db_tab->page[i].uvirt    = 0;
542	}
543
544	return db_tab;
545}
546
547void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar,
548			       struct mthca_user_db_table *db_tab)
549{
550	int i;
551	u8 status;
552
553	if (!mthca_is_memfree(dev))
554		return;
555
556	for (i = 0; i < dev->uar_table.uarc_size / MTHCA_ICM_PAGE_SIZE; ++i) {
557		if (db_tab->page[i].uvirt) {
558			mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1, &status);
559			pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE);
560			put_page(db_tab->page[i].mem.page);
561		}
562	}
563
564	kfree(db_tab);
565}
566
567int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
568		   u32 qn, __be32 **db)
569{
570	int group;
571	int start, end, dir;
572	int i, j;
573	struct mthca_db_page *page;
574	int ret = 0;
575	u8 status;
576
577	mutex_lock(&dev->db_tab->mutex);
578
579	switch (type) {
580	case MTHCA_DB_TYPE_CQ_ARM:
581	case MTHCA_DB_TYPE_SQ:
582		group = 0;
583		start = 0;
584		end   = dev->db_tab->max_group1;
585		dir   = 1;
586		break;
587
588	case MTHCA_DB_TYPE_CQ_SET_CI:
589	case MTHCA_DB_TYPE_RQ:
590	case MTHCA_DB_TYPE_SRQ:
591		group = 1;
592		start = dev->db_tab->npages - 1;
593		end   = dev->db_tab->min_group2;
594		dir   = -1;
595		break;
596
597	default:
598		ret = -EINVAL;
599		goto out;
600	}
601
602	for (i = start; i != end; i += dir)
603		if (dev->db_tab->page[i].db_rec &&
604		    !bitmap_full(dev->db_tab->page[i].used,
605				 MTHCA_DB_REC_PER_PAGE)) {
606			page = dev->db_tab->page + i;
607			goto found;
608		}
609
610	for (i = start; i != end; i += dir)
611		if (!dev->db_tab->page[i].db_rec) {
612			page = dev->db_tab->page + i;
613			goto alloc;
614		}
615
616	if (dev->db_tab->max_group1 >= dev->db_tab->min_group2 - 1) {
617		ret = -ENOMEM;
618		goto out;
619	}
620
621	if (group == 0)
622		++dev->db_tab->max_group1;
623	else
624		--dev->db_tab->min_group2;
625
626	page = dev->db_tab->page + end;
627
628alloc:
629	page->db_rec = dma_alloc_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
630					  &page->mapping, GFP_KERNEL);
631	if (!page->db_rec) {
632		ret = -ENOMEM;
633		goto out;
634	}
635	memset(page->db_rec, 0, MTHCA_ICM_PAGE_SIZE);
636
637	ret = mthca_MAP_ICM_page(dev, page->mapping,
638				 mthca_uarc_virt(dev, &dev->driver_uar, i), &status);
639	if (!ret && status)
640		ret = -EINVAL;
641	if (ret) {
642		dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
643				  page->db_rec, page->mapping);
644		goto out;
645	}
646
647	bitmap_zero(page->used, MTHCA_DB_REC_PER_PAGE);
648
649found:
650	j = find_first_zero_bit(page->used, MTHCA_DB_REC_PER_PAGE);
651	set_bit(j, page->used);
652
653	if (group == 1)
654		j = MTHCA_DB_REC_PER_PAGE - 1 - j;
655
656	ret = i * MTHCA_DB_REC_PER_PAGE + j;
657
658	page->db_rec[j] = cpu_to_be64((qn << 8) | (type << 5));
659
660	*db = (__be32 *) &page->db_rec[j];
661
662out:
663	mutex_unlock(&dev->db_tab->mutex);
664
665	return ret;
666}
667
668void mthca_free_db(struct mthca_dev *dev, int type, int db_index)
669{
670	int i, j;
671	struct mthca_db_page *page;
672	u8 status;
673
674	i = db_index / MTHCA_DB_REC_PER_PAGE;
675	j = db_index % MTHCA_DB_REC_PER_PAGE;
676
677	page = dev->db_tab->page + i;
678
679	mutex_lock(&dev->db_tab->mutex);
680
681	page->db_rec[j] = 0;
682	if (i >= dev->db_tab->min_group2)
683		j = MTHCA_DB_REC_PER_PAGE - 1 - j;
684	clear_bit(j, page->used);
685
686	if (bitmap_empty(page->used, MTHCA_DB_REC_PER_PAGE) &&
687	    i >= dev->db_tab->max_group1 - 1) {
688		mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1, &status);
689
690		dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
691				  page->db_rec, page->mapping);
692		page->db_rec = NULL;
693
694		if (i == dev->db_tab->max_group1) {
695			--dev->db_tab->max_group1;
696			/* XXX may be able to unmap more pages now */
697		}
698		if (i == dev->db_tab->min_group2)
699			++dev->db_tab->min_group2;
700	}
701
702	mutex_unlock(&dev->db_tab->mutex);
703}
704
705int mthca_init_db_tab(struct mthca_dev *dev)
706{
707	int i;
708
709	if (!mthca_is_memfree(dev))
710		return 0;
711
712	dev->db_tab = kmalloc(sizeof *dev->db_tab, GFP_KERNEL);
713	if (!dev->db_tab)
714		return -ENOMEM;
715
716	mutex_init(&dev->db_tab->mutex);
717
718	dev->db_tab->npages     = dev->uar_table.uarc_size / MTHCA_ICM_PAGE_SIZE;
719	dev->db_tab->max_group1 = 0;
720	dev->db_tab->min_group2 = dev->db_tab->npages - 1;
721
722	dev->db_tab->page = kmalloc(dev->db_tab->npages *
723				    sizeof *dev->db_tab->page,
724				    GFP_KERNEL);
725	if (!dev->db_tab->page) {
726		kfree(dev->db_tab);
727		return -ENOMEM;
728	}
729
730	for (i = 0; i < dev->db_tab->npages; ++i)
731		dev->db_tab->page[i].db_rec = NULL;
732
733	return 0;
734}
735
736void mthca_cleanup_db_tab(struct mthca_dev *dev)
737{
738	int i;
739	u8 status;
740
741	if (!mthca_is_memfree(dev))
742		return;
743
744	/*
745	 * Because we don't always free our UARC pages when they
746	 * become empty to make mthca_free_db() simpler we need to
747	 * make a sweep through the doorbell pages and free any
748	 * leftover pages now.
749	 */
750	for (i = 0; i < dev->db_tab->npages; ++i) {
751		if (!dev->db_tab->page[i].db_rec)
752			continue;
753
754		if (!bitmap_empty(dev->db_tab->page[i].used, MTHCA_DB_REC_PER_PAGE))
755			mthca_warn(dev, "Kernel UARC page %d not empty\n", i);
756
757		mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, &dev->driver_uar, i), 1, &status);
758
759		dma_free_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
760				  dev->db_tab->page[i].db_rec,
761				  dev->db_tab->page[i].mapping);
762	}
763
764	kfree(dev->db_tab->page);
765	kfree(dev->db_tab);
766}
767