1fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick/*
2fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *  IBM eServer eHCA Infiniband device driver for Linux on POWER
3fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *
4fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *  userspace support verbs
5fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *
6fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *  Authors: Christoph Raisch <raisch@de.ibm.com>
7fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *           Hoang-Nam Nguyen <hnguyen@de.ibm.com>
8fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *           Heiko J Schick <schickhj@de.ibm.com>
9fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *
10fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *  Copyright (c) 2005 IBM Corporation
11fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *
12fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *  All rights reserved.
13fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *
14fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *  This source code is distributed under a dual license of GPL v2.0 and OpenIB
15fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *  BSD.
16fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *
17fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * OpenIB BSD License
18fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *
19fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * Redistribution and use in source and binary forms, with or without
20fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * modification, are permitted provided that the following conditions are met:
21fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *
22fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * Redistributions of source code must retain the above copyright notice, this
23fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * list of conditions and the following disclaimer.
24fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *
25fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * Redistributions in binary form must reproduce the above copyright notice,
26fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * this list of conditions and the following disclaimer in the documentation
27fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * and/or other materials
28fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * provided with the distribution.
29fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick *
30fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
31fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
34fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
37fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
38fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick * POSSIBILITY OF SUCH DAMAGE.
41fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick */
42fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
435a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
445a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo
45fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick#include "ehca_classes.h"
46fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick#include "ehca_iverbs.h"
47fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick#include "ehca_mrmw.h"
48fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick#include "ehca_tools.h"
49fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick#include "hcp_if.h"
50fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
51fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schickstruct ib_ucontext *ehca_alloc_ucontext(struct ib_device *device,
52fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick					struct ib_udata *udata)
53fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick{
54fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	struct ehca_ucontext *my_context;
55fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
56fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	my_context = kzalloc(sizeof *my_context, GFP_KERNEL);
57fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	if (!my_context) {
58fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		ehca_err(device, "Out of memory device=%p", device);
59fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		return ERR_PTR(-ENOMEM);
60fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	}
61fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
62fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	return &my_context->ib_ucontext;
63fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick}
64fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
65fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schickint ehca_dealloc_ucontext(struct ib_ucontext *context)
66fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick{
67fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	kfree(container_of(context, struct ehca_ucontext, ib_ucontext));
68fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	return 0;
69fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick}
70fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
714c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyenstatic void ehca_mm_open(struct vm_area_struct *vma)
72fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick{
732b94397adc68c2f0f851539884cc426e03444a26Hoang-Nam Nguyen	u32 *count = (u32 *)vma->vm_private_data;
744c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	if (!count) {
754c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
764c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			     vma->vm_start, vma->vm_end);
774c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		return;
784c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	}
794c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	(*count)++;
804c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	if (!(*count))
814c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ehca_gen_err("Use count overflow vm_start=%lx vm_end=%lx",
824c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			     vma->vm_start, vma->vm_end);
834c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x",
844c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		     vma->vm_start, vma->vm_end, *count);
854c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen}
86fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
874c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyenstatic void ehca_mm_close(struct vm_area_struct *vma)
884c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen{
892b94397adc68c2f0f851539884cc426e03444a26Hoang-Nam Nguyen	u32 *count = (u32 *)vma->vm_private_data;
904c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	if (!count) {
914c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
924c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			     vma->vm_start, vma->vm_end);
934c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		return;
944c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	}
954c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	(*count)--;
964c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x",
974c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		     vma->vm_start, vma->vm_end, *count);
984c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen}
99fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
100f0f37e2f77731b3473fa6bd5ee53255d9a9cdb40Alexey Dobriyanstatic const struct vm_operations_struct vm_ops = {
1014c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	.open =	ehca_mm_open,
1024c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	.close = ehca_mm_close,
1034c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen};
1044c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen
1054c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyenstatic int ehca_mmap_fw(struct vm_area_struct *vma, struct h_galpas *galpas,
1064c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			u32 *mm_count)
1074c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen{
1084c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	int ret;
1094c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	u64 vsize, physical;
1104c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen
1114c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	vsize = vma->vm_end - vma->vm_start;
112e390d3b52f791fcea26312ba4982cda82052727bHoang-Nam Nguyen	if (vsize < EHCA_PAGESIZE) {
1134c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ehca_gen_err("invalid vsize=%lx", vma->vm_end - vma->vm_start);
1144c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		return -EINVAL;
1154c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	}
1164c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen
1174c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	physical = galpas->user.fw_handle;
1184c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
1193750f60557b68776eb749859ad68af70d1a01ad0Stephen Rothwell	ehca_gen_dbg("vsize=%llx physical=%llx", vsize, physical);
120314e51b9851b4f4e8ab302243ff5a6fc6147f379Konstantin Khlebnikov	/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
121e390d3b52f791fcea26312ba4982cda82052727bHoang-Nam Nguyen	ret = remap_4k_pfn(vma, vma->vm_start, physical >> EHCA_PAGESHIFT,
122e390d3b52f791fcea26312ba4982cda82052727bHoang-Nam Nguyen			   vma->vm_page_prot);
1234c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	if (unlikely(ret)) {
124e37221928bf685d63ba5319746eafe463d61e330Joachim Fenkes		ehca_gen_err("remap_pfn_range() failed ret=%i", ret);
1254c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		return -ENOMEM;
1264c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	}
1274c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen
1284c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	vma->vm_private_data = mm_count;
1294c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	(*mm_count)++;
1304c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	vma->vm_ops = &vm_ops;
1314c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen
1324c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	return 0;
1334c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen}
1344c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen
1354c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyenstatic int ehca_mmap_queue(struct vm_area_struct *vma, struct ipz_queue *queue,
1364c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			   u32 *mm_count)
1374c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen{
1384c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	int ret;
1394c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	u64 start, ofs;
1404c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	struct page *page;
1414c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen
142314e51b9851b4f4e8ab302243ff5a6fc6147f379Konstantin Khlebnikov	vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
1434c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	start = vma->vm_start;
1444c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	for (ofs = 0; ofs < queue->queue_length; ofs += PAGE_SIZE) {
1454c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		u64 virt_addr = (u64)ipz_qeit_calc(queue, ofs);
1464c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		page = virt_to_page(virt_addr);
1474c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ret = vm_insert_page(vma, start, page);
1484c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		if (unlikely(ret)) {
149e37221928bf685d63ba5319746eafe463d61e330Joachim Fenkes			ehca_gen_err("vm_insert_page() failed rc=%i", ret);
1504c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			return ret;
151fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		}
152e2f81daf23efde23d8cac1fc253d41838f0347cfStefan Roscher <stefan.roscher at		start += PAGE_SIZE;
1534c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	}
1544c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	vma->vm_private_data = mm_count;
1554c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	(*mm_count)++;
1564c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	vma->vm_ops = &vm_ops;
157fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
1584c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	return 0;
1594c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen}
1604c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen
1614c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyenstatic int ehca_mmap_cq(struct vm_area_struct *vma, struct ehca_cq *cq,
1624c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			u32 rsrc_type)
1634c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen{
1644c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	int ret;
1654c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen
1664c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	switch (rsrc_type) {
1675281a4b8a0c6bac0c070913ec25868faa06a3115Stefan Roscher	case 0: /* galpa fw handle */
1684c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ehca_dbg(cq->ib_cq.device, "cq_num=%x fw", cq->cq_number);
1694c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ret = ehca_mmap_fw(vma, &cq->galpas, &cq->mm_count_galpa);
1704c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		if (unlikely(ret)) {
171fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick			ehca_err(cq->ib_cq.device,
172e37221928bf685d63ba5319746eafe463d61e330Joachim Fenkes				 "ehca_mmap_fw() failed rc=%i cq_num=%x",
1734c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen				 ret, cq->cq_number);
1744c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			return ret;
175fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		}
1764c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		break;
177fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
1785281a4b8a0c6bac0c070913ec25868faa06a3115Stefan Roscher	case 1: /* cq queue_addr */
1794c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ehca_dbg(cq->ib_cq.device, "cq_num=%x queue", cq->cq_number);
1804c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ret = ehca_mmap_queue(vma, &cq->ipz_queue, &cq->mm_count_queue);
1814c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		if (unlikely(ret)) {
1824c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			ehca_err(cq->ib_cq.device,
183e37221928bf685d63ba5319746eafe463d61e330Joachim Fenkes				 "ehca_mmap_queue() failed rc=%i cq_num=%x",
1844c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen				 ret, cq->cq_number);
1854c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			return ret;
186fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		}
187fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		break;
188fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
1894c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	default:
1904c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ehca_err(cq->ib_cq.device, "bad resource type=%x cq_num=%x",
1914c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			 rsrc_type, cq->cq_number);
1924c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		return -EINVAL;
1934c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	}
194fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
1954c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	return 0;
1964c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen}
1974c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen
1984c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyenstatic int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
1994c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			u32 rsrc_type)
2004c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen{
2014c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	int ret;
2024c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen
2034c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	switch (rsrc_type) {
2045281a4b8a0c6bac0c070913ec25868faa06a3115Stefan Roscher	case 0: /* galpa fw handle */
2054c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ehca_dbg(qp->ib_qp.device, "qp_num=%x fw", qp->ib_qp.qp_num);
2064c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ret = ehca_mmap_fw(vma, &qp->galpas, &qp->mm_count_galpa);
2074c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		if (unlikely(ret)) {
2084c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			ehca_err(qp->ib_qp.device,
209e37221928bf685d63ba5319746eafe463d61e330Joachim Fenkes				 "remap_pfn_range() failed ret=%i qp_num=%x",
2104c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen				 ret, qp->ib_qp.qp_num);
2114c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			return -ENOMEM;
212fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		}
2134c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		break;
214fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
2155281a4b8a0c6bac0c070913ec25868faa06a3115Stefan Roscher	case 1: /* qp rqueue_addr */
2164da27d6d5b92c8fe4b3a3e5bcf42606d9e4a6fc8Joachim Fenkes		ehca_dbg(qp->ib_qp.device, "qp_num=%x rq", qp->ib_qp.qp_num);
2172b94397adc68c2f0f851539884cc426e03444a26Hoang-Nam Nguyen		ret = ehca_mmap_queue(vma, &qp->ipz_rqueue,
2182b94397adc68c2f0f851539884cc426e03444a26Hoang-Nam Nguyen				      &qp->mm_count_rqueue);
2194c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		if (unlikely(ret)) {
220fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick			ehca_err(qp->ib_qp.device,
221e37221928bf685d63ba5319746eafe463d61e330Joachim Fenkes				 "ehca_mmap_queue(rq) failed rc=%i qp_num=%x",
2224c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen				 ret, qp->ib_qp.qp_num);
2234c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			return ret;
224fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		}
2254c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		break;
226fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
2275281a4b8a0c6bac0c070913ec25868faa06a3115Stefan Roscher	case 2: /* qp squeue_addr */
2284da27d6d5b92c8fe4b3a3e5bcf42606d9e4a6fc8Joachim Fenkes		ehca_dbg(qp->ib_qp.device, "qp_num=%x sq", qp->ib_qp.qp_num);
2292b94397adc68c2f0f851539884cc426e03444a26Hoang-Nam Nguyen		ret = ehca_mmap_queue(vma, &qp->ipz_squeue,
2302b94397adc68c2f0f851539884cc426e03444a26Hoang-Nam Nguyen				      &qp->mm_count_squeue);
2314c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		if (unlikely(ret)) {
2324c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			ehca_err(qp->ib_qp.device,
233e37221928bf685d63ba5319746eafe463d61e330Joachim Fenkes				 "ehca_mmap_queue(sq) failed rc=%i qp_num=%x",
2344c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen				 ret, qp->ib_qp.qp_num);
2354c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			return ret;
236fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		}
237fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		break;
238fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
239fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	default:
2404c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ehca_err(qp->ib_qp.device, "bad resource type=%x qp=num=%x",
2414c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			 rsrc_type, qp->ib_qp.qp_num);
2424c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		return -EINVAL;
243fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	}
244fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
2454c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen	return 0;
246fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick}
247fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
248fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schickint ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
249fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick{
2505281a4b8a0c6bac0c070913ec25868faa06a3115Stefan Roscher	u64 fileoffset = vma->vm_pgoff;
2515281a4b8a0c6bac0c070913ec25868faa06a3115Stefan Roscher	u32 idr_handle = fileoffset & 0x1FFFFFF;
2525281a4b8a0c6bac0c070913ec25868faa06a3115Stefan Roscher	u32 q_type = (fileoffset >> 27) & 0x1;	  /* CQ, QP,...        */
2535281a4b8a0c6bac0c070913ec25868faa06a3115Stefan Roscher	u32 rsrc_type = (fileoffset >> 25) & 0x3; /* sq,rq,cmnd_window */
254fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	u32 ret;
255fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	struct ehca_cq *cq;
256fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	struct ehca_qp *qp;
257a6a12947fbf4a1782535468d756b0d44babf9760Joachim Fenkes	struct ib_uobject *uobject;
258fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
259fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	switch (q_type) {
2605281a4b8a0c6bac0c070913ec25868faa06a3115Stefan Roscher	case  0: /* CQ */
26126ed687fdd541c2542b79dcd75fb2c82eb36f189Joachim Fenkes		read_lock(&ehca_cq_idr_lock);
262fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		cq = idr_find(&ehca_cq_idr, idr_handle);
26326ed687fdd541c2542b79dcd75fb2c82eb36f189Joachim Fenkes		read_unlock(&ehca_cq_idr_lock);
264fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
265fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		/* make sure this mmap really belongs to the authorized user */
266fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		if (!cq)
267fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick			return -EINVAL;
268fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
269fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context)
270fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick			return -EINVAL;
271fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
2724c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ret = ehca_mmap_cq(vma, cq, rsrc_type);
2734c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		if (unlikely(ret)) {
2744c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			ehca_err(cq->ib_cq.device,
275e37221928bf685d63ba5319746eafe463d61e330Joachim Fenkes				 "ehca_mmap_cq() failed rc=%i cq_num=%x",
2764c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen				 ret, cq->cq_number);
2774c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			return ret;
278fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		}
279fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		break;
280fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
2815281a4b8a0c6bac0c070913ec25868faa06a3115Stefan Roscher	case 1: /* QP */
28226ed687fdd541c2542b79dcd75fb2c82eb36f189Joachim Fenkes		read_lock(&ehca_qp_idr_lock);
283fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		qp = idr_find(&ehca_qp_idr, idr_handle);
28426ed687fdd541c2542b79dcd75fb2c82eb36f189Joachim Fenkes		read_unlock(&ehca_qp_idr_lock);
285fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
286fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		/* make sure this mmap really belongs to the authorized user */
287fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		if (!qp)
288fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick			return -EINVAL;
289fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
290a6a12947fbf4a1782535468d756b0d44babf9760Joachim Fenkes		uobject = IS_SRQ(qp) ? qp->ib_srq.uobject : qp->ib_qp.uobject;
291a6a12947fbf4a1782535468d756b0d44babf9760Joachim Fenkes		if (!uobject || uobject->context != context)
292fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick			return -EINVAL;
293fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
2944c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		ret = ehca_mmap_qp(vma, qp, rsrc_type);
2954c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen		if (unlikely(ret)) {
2964c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			ehca_err(qp->ib_qp.device,
297e37221928bf685d63ba5319746eafe463d61e330Joachim Fenkes				 "ehca_mmap_qp() failed rc=%i qp_num=%x",
2984c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen				 ret, qp->ib_qp.qp_num);
2994c34bdf58c0a3b305ebd9b5e74011ca1fd6d964dHoang-Nam Nguyen			return ret;
300fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		}
301fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		break;
302fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
303fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	default:
304fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		ehca_gen_err("bad queue type %x", q_type);
305fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick		return -EINVAL;
306fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	}
307fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick
308fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick	return 0;
309fab97220c9e409a98b1956ba677ddd2dd43b0b95Heiko J Schick}
310