1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
4*4882a593Smuzhiyun * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <rdma/rdma_netlink.h>
8*4882a593Smuzhiyun #include <net/addrconf.h>
9*4882a593Smuzhiyun #include "rxe.h"
10*4882a593Smuzhiyun #include "rxe_loc.h"
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun MODULE_AUTHOR("Bob Pearson, Frank Zago, John Groves, Kamal Heib");
13*4882a593Smuzhiyun MODULE_DESCRIPTION("Soft RDMA transport");
14*4882a593Smuzhiyun MODULE_LICENSE("Dual BSD/GPL");
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun bool rxe_initialized;
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun /* free resources for a rxe device all objects created for this device must
19*4882a593Smuzhiyun * have been destroyed
20*4882a593Smuzhiyun */
rxe_dealloc(struct ib_device * ib_dev)21*4882a593Smuzhiyun void rxe_dealloc(struct ib_device *ib_dev)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun struct rxe_dev *rxe = container_of(ib_dev, struct rxe_dev, ib_dev);
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->uc_pool);
26*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->pd_pool);
27*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->ah_pool);
28*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->srq_pool);
29*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->qp_pool);
30*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->cq_pool);
31*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->mr_pool);
32*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->mw_pool);
33*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->mc_grp_pool);
34*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->mc_elem_pool);
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun if (rxe->tfm)
37*4882a593Smuzhiyun crypto_free_shash(rxe->tfm);
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun /* initialize rxe device parameters */
rxe_init_device_param(struct rxe_dev * rxe)41*4882a593Smuzhiyun static void rxe_init_device_param(struct rxe_dev *rxe)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun rxe->max_inline_data = RXE_MAX_INLINE_DATA;
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun rxe->attr.vendor_id = RXE_VENDOR_ID;
46*4882a593Smuzhiyun rxe->attr.max_mr_size = RXE_MAX_MR_SIZE;
47*4882a593Smuzhiyun rxe->attr.page_size_cap = RXE_PAGE_SIZE_CAP;
48*4882a593Smuzhiyun rxe->attr.max_qp = RXE_MAX_QP;
49*4882a593Smuzhiyun rxe->attr.max_qp_wr = RXE_MAX_QP_WR;
50*4882a593Smuzhiyun rxe->attr.device_cap_flags = RXE_DEVICE_CAP_FLAGS;
51*4882a593Smuzhiyun rxe->attr.max_send_sge = RXE_MAX_SGE;
52*4882a593Smuzhiyun rxe->attr.max_recv_sge = RXE_MAX_SGE;
53*4882a593Smuzhiyun rxe->attr.max_sge_rd = RXE_MAX_SGE_RD;
54*4882a593Smuzhiyun rxe->attr.max_cq = RXE_MAX_CQ;
55*4882a593Smuzhiyun rxe->attr.max_cqe = (1 << RXE_MAX_LOG_CQE) - 1;
56*4882a593Smuzhiyun rxe->attr.max_mr = RXE_MAX_MR;
57*4882a593Smuzhiyun rxe->attr.max_pd = RXE_MAX_PD;
58*4882a593Smuzhiyun rxe->attr.max_qp_rd_atom = RXE_MAX_QP_RD_ATOM;
59*4882a593Smuzhiyun rxe->attr.max_res_rd_atom = RXE_MAX_RES_RD_ATOM;
60*4882a593Smuzhiyun rxe->attr.max_qp_init_rd_atom = RXE_MAX_QP_INIT_RD_ATOM;
61*4882a593Smuzhiyun rxe->attr.atomic_cap = IB_ATOMIC_HCA;
62*4882a593Smuzhiyun rxe->attr.max_mcast_grp = RXE_MAX_MCAST_GRP;
63*4882a593Smuzhiyun rxe->attr.max_mcast_qp_attach = RXE_MAX_MCAST_QP_ATTACH;
64*4882a593Smuzhiyun rxe->attr.max_total_mcast_qp_attach = RXE_MAX_TOT_MCAST_QP_ATTACH;
65*4882a593Smuzhiyun rxe->attr.max_ah = RXE_MAX_AH;
66*4882a593Smuzhiyun rxe->attr.max_srq = RXE_MAX_SRQ;
67*4882a593Smuzhiyun rxe->attr.max_srq_wr = RXE_MAX_SRQ_WR;
68*4882a593Smuzhiyun rxe->attr.max_srq_sge = RXE_MAX_SRQ_SGE;
69*4882a593Smuzhiyun rxe->attr.max_fast_reg_page_list_len = RXE_MAX_FMR_PAGE_LIST_LEN;
70*4882a593Smuzhiyun rxe->attr.max_pkeys = RXE_MAX_PKEYS;
71*4882a593Smuzhiyun rxe->attr.local_ca_ack_delay = RXE_LOCAL_CA_ACK_DELAY;
72*4882a593Smuzhiyun addrconf_addr_eui48((unsigned char *)&rxe->attr.sys_image_guid,
73*4882a593Smuzhiyun rxe->ndev->dev_addr);
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun rxe->max_ucontext = RXE_MAX_UCONTEXT;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /* initialize port attributes */
rxe_init_port_param(struct rxe_port * port)79*4882a593Smuzhiyun static void rxe_init_port_param(struct rxe_port *port)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun port->attr.state = IB_PORT_DOWN;
82*4882a593Smuzhiyun port->attr.max_mtu = IB_MTU_4096;
83*4882a593Smuzhiyun port->attr.active_mtu = IB_MTU_256;
84*4882a593Smuzhiyun port->attr.gid_tbl_len = RXE_PORT_GID_TBL_LEN;
85*4882a593Smuzhiyun port->attr.port_cap_flags = RXE_PORT_PORT_CAP_FLAGS;
86*4882a593Smuzhiyun port->attr.max_msg_sz = RXE_PORT_MAX_MSG_SZ;
87*4882a593Smuzhiyun port->attr.bad_pkey_cntr = RXE_PORT_BAD_PKEY_CNTR;
88*4882a593Smuzhiyun port->attr.qkey_viol_cntr = RXE_PORT_QKEY_VIOL_CNTR;
89*4882a593Smuzhiyun port->attr.pkey_tbl_len = RXE_PORT_PKEY_TBL_LEN;
90*4882a593Smuzhiyun port->attr.lid = RXE_PORT_LID;
91*4882a593Smuzhiyun port->attr.sm_lid = RXE_PORT_SM_LID;
92*4882a593Smuzhiyun port->attr.lmc = RXE_PORT_LMC;
93*4882a593Smuzhiyun port->attr.max_vl_num = RXE_PORT_MAX_VL_NUM;
94*4882a593Smuzhiyun port->attr.sm_sl = RXE_PORT_SM_SL;
95*4882a593Smuzhiyun port->attr.subnet_timeout = RXE_PORT_SUBNET_TIMEOUT;
96*4882a593Smuzhiyun port->attr.init_type_reply = RXE_PORT_INIT_TYPE_REPLY;
97*4882a593Smuzhiyun port->attr.active_width = RXE_PORT_ACTIVE_WIDTH;
98*4882a593Smuzhiyun port->attr.active_speed = RXE_PORT_ACTIVE_SPEED;
99*4882a593Smuzhiyun port->attr.phys_state = RXE_PORT_PHYS_STATE;
100*4882a593Smuzhiyun port->mtu_cap = ib_mtu_enum_to_int(IB_MTU_256);
101*4882a593Smuzhiyun port->subnet_prefix = cpu_to_be64(RXE_PORT_SUBNET_PREFIX);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun /* initialize port state, note IB convention that HCA ports are always
105*4882a593Smuzhiyun * numbered from 1
106*4882a593Smuzhiyun */
rxe_init_ports(struct rxe_dev * rxe)107*4882a593Smuzhiyun static void rxe_init_ports(struct rxe_dev *rxe)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun struct rxe_port *port = &rxe->port;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun rxe_init_port_param(port);
112*4882a593Smuzhiyun addrconf_addr_eui48((unsigned char *)&port->port_guid,
113*4882a593Smuzhiyun rxe->ndev->dev_addr);
114*4882a593Smuzhiyun spin_lock_init(&port->port_lock);
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun /* init pools of managed objects */
rxe_init_pools(struct rxe_dev * rxe)118*4882a593Smuzhiyun static int rxe_init_pools(struct rxe_dev *rxe)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun int err;
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun err = rxe_pool_init(rxe, &rxe->uc_pool, RXE_TYPE_UC,
123*4882a593Smuzhiyun rxe->max_ucontext);
124*4882a593Smuzhiyun if (err)
125*4882a593Smuzhiyun goto err1;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun err = rxe_pool_init(rxe, &rxe->pd_pool, RXE_TYPE_PD,
128*4882a593Smuzhiyun rxe->attr.max_pd);
129*4882a593Smuzhiyun if (err)
130*4882a593Smuzhiyun goto err2;
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun err = rxe_pool_init(rxe, &rxe->ah_pool, RXE_TYPE_AH,
133*4882a593Smuzhiyun rxe->attr.max_ah);
134*4882a593Smuzhiyun if (err)
135*4882a593Smuzhiyun goto err3;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun err = rxe_pool_init(rxe, &rxe->srq_pool, RXE_TYPE_SRQ,
138*4882a593Smuzhiyun rxe->attr.max_srq);
139*4882a593Smuzhiyun if (err)
140*4882a593Smuzhiyun goto err4;
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun err = rxe_pool_init(rxe, &rxe->qp_pool, RXE_TYPE_QP,
143*4882a593Smuzhiyun rxe->attr.max_qp);
144*4882a593Smuzhiyun if (err)
145*4882a593Smuzhiyun goto err5;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun err = rxe_pool_init(rxe, &rxe->cq_pool, RXE_TYPE_CQ,
148*4882a593Smuzhiyun rxe->attr.max_cq);
149*4882a593Smuzhiyun if (err)
150*4882a593Smuzhiyun goto err6;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun err = rxe_pool_init(rxe, &rxe->mr_pool, RXE_TYPE_MR,
153*4882a593Smuzhiyun rxe->attr.max_mr);
154*4882a593Smuzhiyun if (err)
155*4882a593Smuzhiyun goto err7;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun err = rxe_pool_init(rxe, &rxe->mw_pool, RXE_TYPE_MW,
158*4882a593Smuzhiyun rxe->attr.max_mw);
159*4882a593Smuzhiyun if (err)
160*4882a593Smuzhiyun goto err8;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun err = rxe_pool_init(rxe, &rxe->mc_grp_pool, RXE_TYPE_MC_GRP,
163*4882a593Smuzhiyun rxe->attr.max_mcast_grp);
164*4882a593Smuzhiyun if (err)
165*4882a593Smuzhiyun goto err9;
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun err = rxe_pool_init(rxe, &rxe->mc_elem_pool, RXE_TYPE_MC_ELEM,
168*4882a593Smuzhiyun rxe->attr.max_total_mcast_qp_attach);
169*4882a593Smuzhiyun if (err)
170*4882a593Smuzhiyun goto err10;
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun return 0;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun err10:
175*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->mc_grp_pool);
176*4882a593Smuzhiyun err9:
177*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->mw_pool);
178*4882a593Smuzhiyun err8:
179*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->mr_pool);
180*4882a593Smuzhiyun err7:
181*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->cq_pool);
182*4882a593Smuzhiyun err6:
183*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->qp_pool);
184*4882a593Smuzhiyun err5:
185*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->srq_pool);
186*4882a593Smuzhiyun err4:
187*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->ah_pool);
188*4882a593Smuzhiyun err3:
189*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->pd_pool);
190*4882a593Smuzhiyun err2:
191*4882a593Smuzhiyun rxe_pool_cleanup(&rxe->uc_pool);
192*4882a593Smuzhiyun err1:
193*4882a593Smuzhiyun return err;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun /* initialize rxe device state */
rxe_init(struct rxe_dev * rxe)197*4882a593Smuzhiyun static int rxe_init(struct rxe_dev *rxe)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun int err;
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /* init default device parameters */
202*4882a593Smuzhiyun rxe_init_device_param(rxe);
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun rxe_init_ports(rxe);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun err = rxe_init_pools(rxe);
207*4882a593Smuzhiyun if (err)
208*4882a593Smuzhiyun return err;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* init pending mmap list */
211*4882a593Smuzhiyun spin_lock_init(&rxe->mmap_offset_lock);
212*4882a593Smuzhiyun spin_lock_init(&rxe->pending_lock);
213*4882a593Smuzhiyun INIT_LIST_HEAD(&rxe->pending_mmaps);
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun mutex_init(&rxe->usdev_lock);
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun return 0;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
rxe_set_mtu(struct rxe_dev * rxe,unsigned int ndev_mtu)220*4882a593Smuzhiyun void rxe_set_mtu(struct rxe_dev *rxe, unsigned int ndev_mtu)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun struct rxe_port *port = &rxe->port;
223*4882a593Smuzhiyun enum ib_mtu mtu;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun mtu = eth_mtu_int_to_enum(ndev_mtu);
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun /* Make sure that new MTU in range */
228*4882a593Smuzhiyun mtu = mtu ? min_t(enum ib_mtu, mtu, IB_MTU_4096) : IB_MTU_256;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun port->attr.active_mtu = mtu;
231*4882a593Smuzhiyun port->mtu_cap = ib_mtu_enum_to_int(mtu);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun /* called by ifc layer to create new rxe device.
235*4882a593Smuzhiyun * The caller should allocate memory for rxe by calling ib_alloc_device.
236*4882a593Smuzhiyun */
rxe_add(struct rxe_dev * rxe,unsigned int mtu,const char * ibdev_name)237*4882a593Smuzhiyun int rxe_add(struct rxe_dev *rxe, unsigned int mtu, const char *ibdev_name)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun int err;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun err = rxe_init(rxe);
242*4882a593Smuzhiyun if (err)
243*4882a593Smuzhiyun return err;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun rxe_set_mtu(rxe, mtu);
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun return rxe_register_device(rxe, ibdev_name);
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
rxe_newlink(const char * ibdev_name,struct net_device * ndev)250*4882a593Smuzhiyun static int rxe_newlink(const char *ibdev_name, struct net_device *ndev)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun struct rxe_dev *exists;
253*4882a593Smuzhiyun int err = 0;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun if (is_vlan_dev(ndev)) {
256*4882a593Smuzhiyun pr_err("rxe creation allowed on top of a real device only\n");
257*4882a593Smuzhiyun err = -EPERM;
258*4882a593Smuzhiyun goto err;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun exists = rxe_get_dev_from_net(ndev);
262*4882a593Smuzhiyun if (exists) {
263*4882a593Smuzhiyun ib_device_put(&exists->ib_dev);
264*4882a593Smuzhiyun pr_err("already configured on %s\n", ndev->name);
265*4882a593Smuzhiyun err = -EEXIST;
266*4882a593Smuzhiyun goto err;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun err = rxe_net_add(ibdev_name, ndev);
270*4882a593Smuzhiyun if (err) {
271*4882a593Smuzhiyun pr_err("failed to add %s\n", ndev->name);
272*4882a593Smuzhiyun goto err;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun err:
275*4882a593Smuzhiyun return err;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun static struct rdma_link_ops rxe_link_ops = {
279*4882a593Smuzhiyun .type = "rxe",
280*4882a593Smuzhiyun .newlink = rxe_newlink,
281*4882a593Smuzhiyun };
282*4882a593Smuzhiyun
rxe_module_init(void)283*4882a593Smuzhiyun static int __init rxe_module_init(void)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun int err;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun err = rxe_net_init();
288*4882a593Smuzhiyun if (err)
289*4882a593Smuzhiyun return err;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun rdma_link_register(&rxe_link_ops);
292*4882a593Smuzhiyun rxe_initialized = true;
293*4882a593Smuzhiyun pr_info("loaded\n");
294*4882a593Smuzhiyun return 0;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun
rxe_module_exit(void)297*4882a593Smuzhiyun static void __exit rxe_module_exit(void)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun rdma_link_unregister(&rxe_link_ops);
300*4882a593Smuzhiyun ib_unregister_driver(RDMA_DRIVER_RXE);
301*4882a593Smuzhiyun rxe_net_exit();
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun rxe_initialized = false;
304*4882a593Smuzhiyun pr_info("unloaded\n");
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun late_initcall(rxe_module_init);
308*4882a593Smuzhiyun module_exit(rxe_module_exit);
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun MODULE_ALIAS_RDMA_LINK("rxe");
311