1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright(c) 2016 - 2018 Intel Corporation.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * This file is provided under a dual BSD/GPLv2 license. When using or
5*4882a593Smuzhiyun * redistributing this file, you may do so under either license.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * GPL LICENSE SUMMARY
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify
10*4882a593Smuzhiyun * it under the terms of version 2 of the GNU General Public License as
11*4882a593Smuzhiyun * published by the Free Software Foundation.
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful, but
14*4882a593Smuzhiyun * WITHOUT ANY WARRANTY; without even the implied warranty of
15*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16*4882a593Smuzhiyun * General Public License for more details.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * BSD LICENSE
19*4882a593Smuzhiyun *
20*4882a593Smuzhiyun * Redistribution and use in source and binary forms, with or without
21*4882a593Smuzhiyun * modification, are permitted provided that the following conditions
22*4882a593Smuzhiyun * are met:
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * - Redistributions of source code must retain the above copyright
25*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer.
26*4882a593Smuzhiyun * - Redistributions in binary form must reproduce the above copyright
27*4882a593Smuzhiyun * notice, this list of conditions and the following disclaimer in
28*4882a593Smuzhiyun * the documentation and/or other materials provided with the
29*4882a593Smuzhiyun * distribution.
30*4882a593Smuzhiyun * - Neither the name of Intel Corporation nor the names of its
31*4882a593Smuzhiyun * contributors may be used to endorse or promote products derived
32*4882a593Smuzhiyun * from this software without specific prior written permission.
33*4882a593Smuzhiyun *
34*4882a593Smuzhiyun * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
35*4882a593Smuzhiyun * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
36*4882a593Smuzhiyun * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
37*4882a593Smuzhiyun * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
38*4882a593Smuzhiyun * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39*4882a593Smuzhiyun * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40*4882a593Smuzhiyun * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
41*4882a593Smuzhiyun * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
42*4882a593Smuzhiyun * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43*4882a593Smuzhiyun * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
44*4882a593Smuzhiyun * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45*4882a593Smuzhiyun *
46*4882a593Smuzhiyun */
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #include <linux/module.h>
49*4882a593Smuzhiyun #include <linux/kernel.h>
50*4882a593Smuzhiyun #include <linux/dma-mapping.h>
51*4882a593Smuzhiyun #include "vt.h"
52*4882a593Smuzhiyun #include "cq.h"
53*4882a593Smuzhiyun #include "trace.h"
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun #define RVT_UVERBS_ABI_VERSION 2
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun MODULE_LICENSE("Dual BSD/GPL");
58*4882a593Smuzhiyun MODULE_DESCRIPTION("RDMA Verbs Transport Library");
59*4882a593Smuzhiyun
rvt_init(void)60*4882a593Smuzhiyun static int rvt_init(void)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun int ret = rvt_driver_cq_init();
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun if (ret)
65*4882a593Smuzhiyun pr_err("Error in driver CQ init.\n");
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun return ret;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun module_init(rvt_init);
70*4882a593Smuzhiyun
rvt_cleanup(void)71*4882a593Smuzhiyun static void rvt_cleanup(void)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun rvt_cq_exit();
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun module_exit(rvt_cleanup);
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun /**
78*4882a593Smuzhiyun * rvt_alloc_device - allocate rdi
79*4882a593Smuzhiyun * @size: how big of a structure to allocate
80*4882a593Smuzhiyun * @nports: number of ports to allocate array slots for
81*4882a593Smuzhiyun *
82*4882a593Smuzhiyun * Use IB core device alloc to allocate space for the rdi which is assumed to be
83*4882a593Smuzhiyun * inside of the ib_device. Any extra space that drivers require should be
84*4882a593Smuzhiyun * included in size.
85*4882a593Smuzhiyun *
86*4882a593Smuzhiyun * We also allocate a port array based on the number of ports.
87*4882a593Smuzhiyun *
88*4882a593Smuzhiyun * Return: pointer to allocated rdi
89*4882a593Smuzhiyun */
rvt_alloc_device(size_t size,int nports)90*4882a593Smuzhiyun struct rvt_dev_info *rvt_alloc_device(size_t size, int nports)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun struct rvt_dev_info *rdi;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun rdi = container_of(_ib_alloc_device(size), struct rvt_dev_info, ibdev);
95*4882a593Smuzhiyun if (!rdi)
96*4882a593Smuzhiyun return rdi;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun rdi->ports = kcalloc(nports, sizeof(*rdi->ports), GFP_KERNEL);
99*4882a593Smuzhiyun if (!rdi->ports)
100*4882a593Smuzhiyun ib_dealloc_device(&rdi->ibdev);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun return rdi;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun EXPORT_SYMBOL(rvt_alloc_device);
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /**
107*4882a593Smuzhiyun * rvt_dealloc_device - deallocate rdi
108*4882a593Smuzhiyun * @rdi: structure to free
109*4882a593Smuzhiyun *
110*4882a593Smuzhiyun * Free a structure allocated with rvt_alloc_device()
111*4882a593Smuzhiyun */
rvt_dealloc_device(struct rvt_dev_info * rdi)112*4882a593Smuzhiyun void rvt_dealloc_device(struct rvt_dev_info *rdi)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun kfree(rdi->ports);
115*4882a593Smuzhiyun ib_dealloc_device(&rdi->ibdev);
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun EXPORT_SYMBOL(rvt_dealloc_device);
118*4882a593Smuzhiyun
rvt_query_device(struct ib_device * ibdev,struct ib_device_attr * props,struct ib_udata * uhw)119*4882a593Smuzhiyun static int rvt_query_device(struct ib_device *ibdev,
120*4882a593Smuzhiyun struct ib_device_attr *props,
121*4882a593Smuzhiyun struct ib_udata *uhw)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun if (uhw->inlen || uhw->outlen)
126*4882a593Smuzhiyun return -EINVAL;
127*4882a593Smuzhiyun /*
128*4882a593Smuzhiyun * Return rvt_dev_info.dparms.props contents
129*4882a593Smuzhiyun */
130*4882a593Smuzhiyun *props = rdi->dparms.props;
131*4882a593Smuzhiyun return 0;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
rvt_modify_device(struct ib_device * device,int device_modify_mask,struct ib_device_modify * device_modify)134*4882a593Smuzhiyun static int rvt_modify_device(struct ib_device *device,
135*4882a593Smuzhiyun int device_modify_mask,
136*4882a593Smuzhiyun struct ib_device_modify *device_modify)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun /*
139*4882a593Smuzhiyun * There is currently no need to supply this based on qib and hfi1.
140*4882a593Smuzhiyun * Future drivers may need to implement this though.
141*4882a593Smuzhiyun */
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun return -EOPNOTSUPP;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /**
147*4882a593Smuzhiyun * rvt_query_port: Passes the query port call to the driver
148*4882a593Smuzhiyun * @ibdev: Verbs IB dev
149*4882a593Smuzhiyun * @port_num: port number, 1 based from ib core
150*4882a593Smuzhiyun * @props: structure to hold returned properties
151*4882a593Smuzhiyun *
152*4882a593Smuzhiyun * Return: 0 on success
153*4882a593Smuzhiyun */
rvt_query_port(struct ib_device * ibdev,u8 port_num,struct ib_port_attr * props)154*4882a593Smuzhiyun static int rvt_query_port(struct ib_device *ibdev, u8 port_num,
155*4882a593Smuzhiyun struct ib_port_attr *props)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
158*4882a593Smuzhiyun struct rvt_ibport *rvp;
159*4882a593Smuzhiyun int port_index = ibport_num_to_idx(ibdev, port_num);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun if (port_index < 0)
162*4882a593Smuzhiyun return -EINVAL;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun rvp = rdi->ports[port_index];
165*4882a593Smuzhiyun /* props being zeroed by the caller, avoid zeroing it here */
166*4882a593Smuzhiyun props->sm_lid = rvp->sm_lid;
167*4882a593Smuzhiyun props->sm_sl = rvp->sm_sl;
168*4882a593Smuzhiyun props->port_cap_flags = rvp->port_cap_flags;
169*4882a593Smuzhiyun props->max_msg_sz = 0x80000000;
170*4882a593Smuzhiyun props->pkey_tbl_len = rvt_get_npkeys(rdi);
171*4882a593Smuzhiyun props->bad_pkey_cntr = rvp->pkey_violations;
172*4882a593Smuzhiyun props->qkey_viol_cntr = rvp->qkey_violations;
173*4882a593Smuzhiyun props->subnet_timeout = rvp->subnet_timeout;
174*4882a593Smuzhiyun props->init_type_reply = 0;
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /* Populate the remaining ib_port_attr elements */
177*4882a593Smuzhiyun return rdi->driver_f.query_port_state(rdi, port_num, props);
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun /**
181*4882a593Smuzhiyun * rvt_modify_port
182*4882a593Smuzhiyun * @ibdev: Verbs IB dev
183*4882a593Smuzhiyun * @port_num: Port number, 1 based from ib core
184*4882a593Smuzhiyun * @port_modify_mask: How to change the port
185*4882a593Smuzhiyun * @props: Structure to fill in
186*4882a593Smuzhiyun *
187*4882a593Smuzhiyun * Return: 0 on success
188*4882a593Smuzhiyun */
rvt_modify_port(struct ib_device * ibdev,u8 port_num,int port_modify_mask,struct ib_port_modify * props)189*4882a593Smuzhiyun static int rvt_modify_port(struct ib_device *ibdev, u8 port_num,
190*4882a593Smuzhiyun int port_modify_mask, struct ib_port_modify *props)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
193*4882a593Smuzhiyun struct rvt_ibport *rvp;
194*4882a593Smuzhiyun int ret = 0;
195*4882a593Smuzhiyun int port_index = ibport_num_to_idx(ibdev, port_num);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun if (port_index < 0)
198*4882a593Smuzhiyun return -EINVAL;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun rvp = rdi->ports[port_index];
201*4882a593Smuzhiyun if (port_modify_mask & IB_PORT_OPA_MASK_CHG) {
202*4882a593Smuzhiyun rvp->port_cap3_flags |= props->set_port_cap_mask;
203*4882a593Smuzhiyun rvp->port_cap3_flags &= ~props->clr_port_cap_mask;
204*4882a593Smuzhiyun } else {
205*4882a593Smuzhiyun rvp->port_cap_flags |= props->set_port_cap_mask;
206*4882a593Smuzhiyun rvp->port_cap_flags &= ~props->clr_port_cap_mask;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun if (props->set_port_cap_mask || props->clr_port_cap_mask)
210*4882a593Smuzhiyun rdi->driver_f.cap_mask_chg(rdi, port_num);
211*4882a593Smuzhiyun if (port_modify_mask & IB_PORT_SHUTDOWN)
212*4882a593Smuzhiyun ret = rdi->driver_f.shut_down_port(rdi, port_num);
213*4882a593Smuzhiyun if (port_modify_mask & IB_PORT_RESET_QKEY_CNTR)
214*4882a593Smuzhiyun rvp->qkey_violations = 0;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun return ret;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /**
220*4882a593Smuzhiyun * rvt_query_pkey - Return a pkey from the table at a given index
221*4882a593Smuzhiyun * @ibdev: Verbs IB dev
222*4882a593Smuzhiyun * @port_num: Port number, 1 based from ib core
223*4882a593Smuzhiyun * @index: Index into pkey table
224*4882a593Smuzhiyun * @pkey: returned pkey from the port pkey table
225*4882a593Smuzhiyun *
226*4882a593Smuzhiyun * Return: 0 on failure pkey otherwise
227*4882a593Smuzhiyun */
rvt_query_pkey(struct ib_device * ibdev,u8 port_num,u16 index,u16 * pkey)228*4882a593Smuzhiyun static int rvt_query_pkey(struct ib_device *ibdev, u8 port_num, u16 index,
229*4882a593Smuzhiyun u16 *pkey)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun /*
232*4882a593Smuzhiyun * Driver will be responsible for keeping rvt_dev_info.pkey_table up to
233*4882a593Smuzhiyun * date. This function will just return that value. There is no need to
234*4882a593Smuzhiyun * lock, if a stale value is read and sent to the user so be it there is
235*4882a593Smuzhiyun * no way to protect against that anyway.
236*4882a593Smuzhiyun */
237*4882a593Smuzhiyun struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
238*4882a593Smuzhiyun int port_index;
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun port_index = ibport_num_to_idx(ibdev, port_num);
241*4882a593Smuzhiyun if (port_index < 0)
242*4882a593Smuzhiyun return -EINVAL;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun if (index >= rvt_get_npkeys(rdi))
245*4882a593Smuzhiyun return -EINVAL;
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun *pkey = rvt_get_pkey(rdi, port_index, index);
248*4882a593Smuzhiyun return 0;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun /**
252*4882a593Smuzhiyun * rvt_query_gid - Return a gid from the table
253*4882a593Smuzhiyun * @ibdev: Verbs IB dev
254*4882a593Smuzhiyun * @port_num: Port number, 1 based from ib core
255*4882a593Smuzhiyun * @guid_index: Index in table
256*4882a593Smuzhiyun * @gid: Gid to return
257*4882a593Smuzhiyun *
258*4882a593Smuzhiyun * Return: 0 on success
259*4882a593Smuzhiyun */
rvt_query_gid(struct ib_device * ibdev,u8 port_num,int guid_index,union ib_gid * gid)260*4882a593Smuzhiyun static int rvt_query_gid(struct ib_device *ibdev, u8 port_num,
261*4882a593Smuzhiyun int guid_index, union ib_gid *gid)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun struct rvt_dev_info *rdi;
264*4882a593Smuzhiyun struct rvt_ibport *rvp;
265*4882a593Smuzhiyun int port_index;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /*
268*4882a593Smuzhiyun * Driver is responsible for updating the guid table. Which will be used
269*4882a593Smuzhiyun * to craft the return value. This will work similar to how query_pkey()
270*4882a593Smuzhiyun * is being done.
271*4882a593Smuzhiyun */
272*4882a593Smuzhiyun port_index = ibport_num_to_idx(ibdev, port_num);
273*4882a593Smuzhiyun if (port_index < 0)
274*4882a593Smuzhiyun return -EINVAL;
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun rdi = ib_to_rvt(ibdev);
277*4882a593Smuzhiyun rvp = rdi->ports[port_index];
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun gid->global.subnet_prefix = rvp->gid_prefix;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun return rdi->driver_f.get_guid_be(rdi, rvp, guid_index,
282*4882a593Smuzhiyun &gid->global.interface_id);
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun /**
286*4882a593Smuzhiyun * rvt_alloc_ucontext - Allocate a user context
287*4882a593Smuzhiyun * @uctx: Verbs context
288*4882a593Smuzhiyun * @udata: User data allocated
289*4882a593Smuzhiyun */
rvt_alloc_ucontext(struct ib_ucontext * uctx,struct ib_udata * udata)290*4882a593Smuzhiyun static int rvt_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun return 0;
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun /**
296*4882a593Smuzhiyun * rvt_dealloc_ucontext - Free a user context
297*4882a593Smuzhiyun * @context - Free this
298*4882a593Smuzhiyun */
rvt_dealloc_ucontext(struct ib_ucontext * context)299*4882a593Smuzhiyun static void rvt_dealloc_ucontext(struct ib_ucontext *context)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun return;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun
rvt_get_port_immutable(struct ib_device * ibdev,u8 port_num,struct ib_port_immutable * immutable)304*4882a593Smuzhiyun static int rvt_get_port_immutable(struct ib_device *ibdev, u8 port_num,
305*4882a593Smuzhiyun struct ib_port_immutable *immutable)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun struct rvt_dev_info *rdi = ib_to_rvt(ibdev);
308*4882a593Smuzhiyun struct ib_port_attr attr;
309*4882a593Smuzhiyun int err, port_index;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun port_index = ibport_num_to_idx(ibdev, port_num);
312*4882a593Smuzhiyun if (port_index < 0)
313*4882a593Smuzhiyun return -EINVAL;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun immutable->core_cap_flags = rdi->dparms.core_cap_flags;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun err = ib_query_port(ibdev, port_num, &attr);
318*4882a593Smuzhiyun if (err)
319*4882a593Smuzhiyun return err;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun immutable->pkey_tbl_len = attr.pkey_tbl_len;
322*4882a593Smuzhiyun immutable->gid_tbl_len = attr.gid_tbl_len;
323*4882a593Smuzhiyun immutable->max_mad_size = rdi->dparms.max_mad_size;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun return 0;
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun enum {
329*4882a593Smuzhiyun MISC,
330*4882a593Smuzhiyun QUERY_DEVICE,
331*4882a593Smuzhiyun MODIFY_DEVICE,
332*4882a593Smuzhiyun QUERY_PORT,
333*4882a593Smuzhiyun MODIFY_PORT,
334*4882a593Smuzhiyun QUERY_PKEY,
335*4882a593Smuzhiyun QUERY_GID,
336*4882a593Smuzhiyun ALLOC_UCONTEXT,
337*4882a593Smuzhiyun DEALLOC_UCONTEXT,
338*4882a593Smuzhiyun GET_PORT_IMMUTABLE,
339*4882a593Smuzhiyun CREATE_QP,
340*4882a593Smuzhiyun MODIFY_QP,
341*4882a593Smuzhiyun DESTROY_QP,
342*4882a593Smuzhiyun QUERY_QP,
343*4882a593Smuzhiyun POST_SEND,
344*4882a593Smuzhiyun POST_RECV,
345*4882a593Smuzhiyun POST_SRQ_RECV,
346*4882a593Smuzhiyun CREATE_AH,
347*4882a593Smuzhiyun DESTROY_AH,
348*4882a593Smuzhiyun MODIFY_AH,
349*4882a593Smuzhiyun QUERY_AH,
350*4882a593Smuzhiyun CREATE_SRQ,
351*4882a593Smuzhiyun MODIFY_SRQ,
352*4882a593Smuzhiyun DESTROY_SRQ,
353*4882a593Smuzhiyun QUERY_SRQ,
354*4882a593Smuzhiyun ATTACH_MCAST,
355*4882a593Smuzhiyun DETACH_MCAST,
356*4882a593Smuzhiyun GET_DMA_MR,
357*4882a593Smuzhiyun REG_USER_MR,
358*4882a593Smuzhiyun DEREG_MR,
359*4882a593Smuzhiyun ALLOC_MR,
360*4882a593Smuzhiyun MAP_MR_SG,
361*4882a593Smuzhiyun ALLOC_FMR,
362*4882a593Smuzhiyun MAP_PHYS_FMR,
363*4882a593Smuzhiyun UNMAP_FMR,
364*4882a593Smuzhiyun DEALLOC_FMR,
365*4882a593Smuzhiyun MMAP,
366*4882a593Smuzhiyun CREATE_CQ,
367*4882a593Smuzhiyun DESTROY_CQ,
368*4882a593Smuzhiyun POLL_CQ,
369*4882a593Smuzhiyun REQ_NOTFIY_CQ,
370*4882a593Smuzhiyun RESIZE_CQ,
371*4882a593Smuzhiyun ALLOC_PD,
372*4882a593Smuzhiyun DEALLOC_PD,
373*4882a593Smuzhiyun _VERB_IDX_MAX /* Must always be last! */
374*4882a593Smuzhiyun };
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun static const struct ib_device_ops rvt_dev_ops = {
377*4882a593Smuzhiyun .uverbs_abi_ver = RVT_UVERBS_ABI_VERSION,
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun .alloc_mr = rvt_alloc_mr,
380*4882a593Smuzhiyun .alloc_pd = rvt_alloc_pd,
381*4882a593Smuzhiyun .alloc_ucontext = rvt_alloc_ucontext,
382*4882a593Smuzhiyun .attach_mcast = rvt_attach_mcast,
383*4882a593Smuzhiyun .create_ah = rvt_create_ah,
384*4882a593Smuzhiyun .create_cq = rvt_create_cq,
385*4882a593Smuzhiyun .create_qp = rvt_create_qp,
386*4882a593Smuzhiyun .create_srq = rvt_create_srq,
387*4882a593Smuzhiyun .dealloc_pd = rvt_dealloc_pd,
388*4882a593Smuzhiyun .dealloc_ucontext = rvt_dealloc_ucontext,
389*4882a593Smuzhiyun .dereg_mr = rvt_dereg_mr,
390*4882a593Smuzhiyun .destroy_ah = rvt_destroy_ah,
391*4882a593Smuzhiyun .destroy_cq = rvt_destroy_cq,
392*4882a593Smuzhiyun .destroy_qp = rvt_destroy_qp,
393*4882a593Smuzhiyun .destroy_srq = rvt_destroy_srq,
394*4882a593Smuzhiyun .detach_mcast = rvt_detach_mcast,
395*4882a593Smuzhiyun .get_dma_mr = rvt_get_dma_mr,
396*4882a593Smuzhiyun .get_port_immutable = rvt_get_port_immutable,
397*4882a593Smuzhiyun .map_mr_sg = rvt_map_mr_sg,
398*4882a593Smuzhiyun .mmap = rvt_mmap,
399*4882a593Smuzhiyun .modify_ah = rvt_modify_ah,
400*4882a593Smuzhiyun .modify_device = rvt_modify_device,
401*4882a593Smuzhiyun .modify_port = rvt_modify_port,
402*4882a593Smuzhiyun .modify_qp = rvt_modify_qp,
403*4882a593Smuzhiyun .modify_srq = rvt_modify_srq,
404*4882a593Smuzhiyun .poll_cq = rvt_poll_cq,
405*4882a593Smuzhiyun .post_recv = rvt_post_recv,
406*4882a593Smuzhiyun .post_send = rvt_post_send,
407*4882a593Smuzhiyun .post_srq_recv = rvt_post_srq_recv,
408*4882a593Smuzhiyun .query_ah = rvt_query_ah,
409*4882a593Smuzhiyun .query_device = rvt_query_device,
410*4882a593Smuzhiyun .query_gid = rvt_query_gid,
411*4882a593Smuzhiyun .query_pkey = rvt_query_pkey,
412*4882a593Smuzhiyun .query_port = rvt_query_port,
413*4882a593Smuzhiyun .query_qp = rvt_query_qp,
414*4882a593Smuzhiyun .query_srq = rvt_query_srq,
415*4882a593Smuzhiyun .reg_user_mr = rvt_reg_user_mr,
416*4882a593Smuzhiyun .req_notify_cq = rvt_req_notify_cq,
417*4882a593Smuzhiyun .resize_cq = rvt_resize_cq,
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun INIT_RDMA_OBJ_SIZE(ib_ah, rvt_ah, ibah),
420*4882a593Smuzhiyun INIT_RDMA_OBJ_SIZE(ib_cq, rvt_cq, ibcq),
421*4882a593Smuzhiyun INIT_RDMA_OBJ_SIZE(ib_pd, rvt_pd, ibpd),
422*4882a593Smuzhiyun INIT_RDMA_OBJ_SIZE(ib_srq, rvt_srq, ibsrq),
423*4882a593Smuzhiyun INIT_RDMA_OBJ_SIZE(ib_ucontext, rvt_ucontext, ibucontext),
424*4882a593Smuzhiyun };
425*4882a593Smuzhiyun
check_support(struct rvt_dev_info * rdi,int verb)426*4882a593Smuzhiyun static noinline int check_support(struct rvt_dev_info *rdi, int verb)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun switch (verb) {
429*4882a593Smuzhiyun case MISC:
430*4882a593Smuzhiyun /*
431*4882a593Smuzhiyun * These functions are not part of verbs specifically but are
432*4882a593Smuzhiyun * required for rdmavt to function.
433*4882a593Smuzhiyun */
434*4882a593Smuzhiyun if ((!rdi->ibdev.ops.init_port) ||
435*4882a593Smuzhiyun (!rdi->driver_f.get_pci_dev))
436*4882a593Smuzhiyun return -EINVAL;
437*4882a593Smuzhiyun break;
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun case MODIFY_DEVICE:
440*4882a593Smuzhiyun /*
441*4882a593Smuzhiyun * rdmavt does not support modify device currently drivers must
442*4882a593Smuzhiyun * provide.
443*4882a593Smuzhiyun */
444*4882a593Smuzhiyun if (!rdi->ibdev.ops.modify_device)
445*4882a593Smuzhiyun return -EOPNOTSUPP;
446*4882a593Smuzhiyun break;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun case QUERY_PORT:
449*4882a593Smuzhiyun if (!rdi->ibdev.ops.query_port)
450*4882a593Smuzhiyun if (!rdi->driver_f.query_port_state)
451*4882a593Smuzhiyun return -EINVAL;
452*4882a593Smuzhiyun break;
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun case MODIFY_PORT:
455*4882a593Smuzhiyun if (!rdi->ibdev.ops.modify_port)
456*4882a593Smuzhiyun if (!rdi->driver_f.cap_mask_chg ||
457*4882a593Smuzhiyun !rdi->driver_f.shut_down_port)
458*4882a593Smuzhiyun return -EINVAL;
459*4882a593Smuzhiyun break;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun case QUERY_GID:
462*4882a593Smuzhiyun if (!rdi->ibdev.ops.query_gid)
463*4882a593Smuzhiyun if (!rdi->driver_f.get_guid_be)
464*4882a593Smuzhiyun return -EINVAL;
465*4882a593Smuzhiyun break;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun case CREATE_QP:
468*4882a593Smuzhiyun if (!rdi->ibdev.ops.create_qp)
469*4882a593Smuzhiyun if (!rdi->driver_f.qp_priv_alloc ||
470*4882a593Smuzhiyun !rdi->driver_f.qp_priv_free ||
471*4882a593Smuzhiyun !rdi->driver_f.notify_qp_reset ||
472*4882a593Smuzhiyun !rdi->driver_f.flush_qp_waiters ||
473*4882a593Smuzhiyun !rdi->driver_f.stop_send_queue ||
474*4882a593Smuzhiyun !rdi->driver_f.quiesce_qp)
475*4882a593Smuzhiyun return -EINVAL;
476*4882a593Smuzhiyun break;
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun case MODIFY_QP:
479*4882a593Smuzhiyun if (!rdi->ibdev.ops.modify_qp)
480*4882a593Smuzhiyun if (!rdi->driver_f.notify_qp_reset ||
481*4882a593Smuzhiyun !rdi->driver_f.schedule_send ||
482*4882a593Smuzhiyun !rdi->driver_f.get_pmtu_from_attr ||
483*4882a593Smuzhiyun !rdi->driver_f.flush_qp_waiters ||
484*4882a593Smuzhiyun !rdi->driver_f.stop_send_queue ||
485*4882a593Smuzhiyun !rdi->driver_f.quiesce_qp ||
486*4882a593Smuzhiyun !rdi->driver_f.notify_error_qp ||
487*4882a593Smuzhiyun !rdi->driver_f.mtu_from_qp ||
488*4882a593Smuzhiyun !rdi->driver_f.mtu_to_path_mtu)
489*4882a593Smuzhiyun return -EINVAL;
490*4882a593Smuzhiyun break;
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun case DESTROY_QP:
493*4882a593Smuzhiyun if (!rdi->ibdev.ops.destroy_qp)
494*4882a593Smuzhiyun if (!rdi->driver_f.qp_priv_free ||
495*4882a593Smuzhiyun !rdi->driver_f.notify_qp_reset ||
496*4882a593Smuzhiyun !rdi->driver_f.flush_qp_waiters ||
497*4882a593Smuzhiyun !rdi->driver_f.stop_send_queue ||
498*4882a593Smuzhiyun !rdi->driver_f.quiesce_qp)
499*4882a593Smuzhiyun return -EINVAL;
500*4882a593Smuzhiyun break;
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun case POST_SEND:
503*4882a593Smuzhiyun if (!rdi->ibdev.ops.post_send)
504*4882a593Smuzhiyun if (!rdi->driver_f.schedule_send ||
505*4882a593Smuzhiyun !rdi->driver_f.do_send ||
506*4882a593Smuzhiyun !rdi->post_parms)
507*4882a593Smuzhiyun return -EINVAL;
508*4882a593Smuzhiyun break;
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun return 0;
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun /**
516*4882a593Smuzhiyun * rvt_register_device - register a driver
517*4882a593Smuzhiyun * @rdi: main dev structure for all of rdmavt operations
518*4882a593Smuzhiyun *
519*4882a593Smuzhiyun * It is up to drivers to allocate the rdi and fill in the appropriate
520*4882a593Smuzhiyun * information.
521*4882a593Smuzhiyun *
522*4882a593Smuzhiyun * Return: 0 on success otherwise an errno.
523*4882a593Smuzhiyun */
rvt_register_device(struct rvt_dev_info * rdi)524*4882a593Smuzhiyun int rvt_register_device(struct rvt_dev_info *rdi)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun int ret = 0, i;
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun if (!rdi)
529*4882a593Smuzhiyun return -EINVAL;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun /*
532*4882a593Smuzhiyun * Check to ensure drivers have setup the required helpers for the verbs
533*4882a593Smuzhiyun * they want rdmavt to handle
534*4882a593Smuzhiyun */
535*4882a593Smuzhiyun for (i = 0; i < _VERB_IDX_MAX; i++)
536*4882a593Smuzhiyun if (check_support(rdi, i)) {
537*4882a593Smuzhiyun pr_err("Driver support req not met at %d\n", i);
538*4882a593Smuzhiyun return -EINVAL;
539*4882a593Smuzhiyun }
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun ib_set_device_ops(&rdi->ibdev, &rvt_dev_ops);
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun /* Once we get past here we can use rvt_pr macros and tracepoints */
544*4882a593Smuzhiyun trace_rvt_dbg(rdi, "Driver attempting registration");
545*4882a593Smuzhiyun rvt_mmap_init(rdi);
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun /* Queue Pairs */
548*4882a593Smuzhiyun ret = rvt_driver_qp_init(rdi);
549*4882a593Smuzhiyun if (ret) {
550*4882a593Smuzhiyun pr_err("Error in driver QP init.\n");
551*4882a593Smuzhiyun return -EINVAL;
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun /* Address Handle */
555*4882a593Smuzhiyun spin_lock_init(&rdi->n_ahs_lock);
556*4882a593Smuzhiyun rdi->n_ahs_allocated = 0;
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun /* Shared Receive Queue */
559*4882a593Smuzhiyun rvt_driver_srq_init(rdi);
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun /* Multicast */
562*4882a593Smuzhiyun rvt_driver_mcast_init(rdi);
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun /* Mem Region */
565*4882a593Smuzhiyun ret = rvt_driver_mr_init(rdi);
566*4882a593Smuzhiyun if (ret) {
567*4882a593Smuzhiyun pr_err("Error in driver MR init.\n");
568*4882a593Smuzhiyun goto bail_no_mr;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun /* Memory Working Set Size */
572*4882a593Smuzhiyun ret = rvt_wss_init(rdi);
573*4882a593Smuzhiyun if (ret) {
574*4882a593Smuzhiyun rvt_pr_err(rdi, "Error in WSS init.\n");
575*4882a593Smuzhiyun goto bail_mr;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun /* Completion queues */
579*4882a593Smuzhiyun spin_lock_init(&rdi->n_cqs_lock);
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun /* Protection Domain */
582*4882a593Smuzhiyun spin_lock_init(&rdi->n_pds_lock);
583*4882a593Smuzhiyun rdi->n_pds_allocated = 0;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun /*
586*4882a593Smuzhiyun * There are some things which could be set by underlying drivers but
587*4882a593Smuzhiyun * really should be up to rdmavt to set. For instance drivers can't know
588*4882a593Smuzhiyun * exactly which functions rdmavt supports, nor do they know the ABI
589*4882a593Smuzhiyun * version, so we do all of this sort of stuff here.
590*4882a593Smuzhiyun */
591*4882a593Smuzhiyun rdi->ibdev.uverbs_cmd_mask =
592*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
593*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) |
594*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_QUERY_PORT) |
595*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_ALLOC_PD) |
596*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) |
597*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_CREATE_AH) |
598*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_MODIFY_AH) |
599*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_QUERY_AH) |
600*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_DESTROY_AH) |
601*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_REG_MR) |
602*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_DEREG_MR) |
603*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
604*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
605*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) |
606*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |
607*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_POLL_CQ) |
608*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) |
609*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_CREATE_QP) |
610*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_QUERY_QP) |
611*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
612*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
613*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_POST_SEND) |
614*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_POST_RECV) |
615*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) |
616*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) |
617*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
618*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
619*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
620*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ) |
621*4882a593Smuzhiyun (1ull << IB_USER_VERBS_CMD_POST_SRQ_RECV);
622*4882a593Smuzhiyun rdi->ibdev.node_type = RDMA_NODE_IB_CA;
623*4882a593Smuzhiyun if (!rdi->ibdev.num_comp_vectors)
624*4882a593Smuzhiyun rdi->ibdev.num_comp_vectors = 1;
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun /* We are now good to announce we exist */
627*4882a593Smuzhiyun ret = ib_register_device(&rdi->ibdev, dev_name(&rdi->ibdev.dev), NULL);
628*4882a593Smuzhiyun if (ret) {
629*4882a593Smuzhiyun rvt_pr_err(rdi, "Failed to register driver with ib core.\n");
630*4882a593Smuzhiyun goto bail_wss;
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun rvt_create_mad_agents(rdi);
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun rvt_pr_info(rdi, "Registration with rdmavt done.\n");
636*4882a593Smuzhiyun return ret;
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun bail_wss:
639*4882a593Smuzhiyun rvt_wss_exit(rdi);
640*4882a593Smuzhiyun bail_mr:
641*4882a593Smuzhiyun rvt_mr_exit(rdi);
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun bail_no_mr:
644*4882a593Smuzhiyun rvt_qp_exit(rdi);
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun return ret;
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun EXPORT_SYMBOL(rvt_register_device);
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun /**
651*4882a593Smuzhiyun * rvt_unregister_device - remove a driver
652*4882a593Smuzhiyun * @rdi: rvt dev struct
653*4882a593Smuzhiyun */
rvt_unregister_device(struct rvt_dev_info * rdi)654*4882a593Smuzhiyun void rvt_unregister_device(struct rvt_dev_info *rdi)
655*4882a593Smuzhiyun {
656*4882a593Smuzhiyun trace_rvt_dbg(rdi, "Driver is unregistering.");
657*4882a593Smuzhiyun if (!rdi)
658*4882a593Smuzhiyun return;
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun rvt_free_mad_agents(rdi);
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun ib_unregister_device(&rdi->ibdev);
663*4882a593Smuzhiyun rvt_wss_exit(rdi);
664*4882a593Smuzhiyun rvt_mr_exit(rdi);
665*4882a593Smuzhiyun rvt_qp_exit(rdi);
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun EXPORT_SYMBOL(rvt_unregister_device);
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun /**
670*4882a593Smuzhiyun * rvt_init_port - init internal data for driver port
671*4882a593Smuzhiyun * @rdi: rvt_dev_info struct
672*4882a593Smuzhiyun * @port: rvt port
673*4882a593Smuzhiyun * @port_index: 0 based index of ports, different from IB core port num
674*4882a593Smuzhiyun * @pkey_table: pkey_table for @port
675*4882a593Smuzhiyun *
676*4882a593Smuzhiyun * Keep track of a list of ports. No need to have a detach port.
677*4882a593Smuzhiyun * They persist until the driver goes away.
678*4882a593Smuzhiyun *
679*4882a593Smuzhiyun * Return: always 0
680*4882a593Smuzhiyun */
rvt_init_port(struct rvt_dev_info * rdi,struct rvt_ibport * port,int port_index,u16 * pkey_table)681*4882a593Smuzhiyun int rvt_init_port(struct rvt_dev_info *rdi, struct rvt_ibport *port,
682*4882a593Smuzhiyun int port_index, u16 *pkey_table)
683*4882a593Smuzhiyun {
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun rdi->ports[port_index] = port;
686*4882a593Smuzhiyun rdi->ports[port_index]->pkey_table = pkey_table;
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun return 0;
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun EXPORT_SYMBOL(rvt_init_port);
691