1 /*
2  * Copyright (c) 2014, Cisco Systems, Inc. All rights reserved.
3  *
4  * LICENSE_BEGIN
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  * 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  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  * LICENSE_END
39  *
40  *
41  */
42 
43 #ifndef _USD_H_
44 #define _USD_H_
45 
46 #include <sys/queue.h>
47 
48 #include "kcompat.h"
49 #include "vnic_rq.h"
50 #include "vnic_wq.h"
51 #include "vnic_cq.h"
52 #include "wq_enet_desc.h"
53 #include "rq_enet_desc.h"
54 #include "vnic_intr.h"
55 
56 #include "usnic_abi.h"
57 #include "usnic_direct.h"
58 #include "usd_ib_sysfs.h"
59 
60 #define USD_INVALID_HANDLE (~0)
61 #define USD_SF_ISSET(flags, flagname) \
62     ((flags >> USD_SFS_##flagname) & 1)
63 
64 #define USD_SEND_MAX_COPY 992
65 #define USD_MAX_PRESEND 4
66 
67 #define USD_CTXF_CLOSE_CMD_FD (1u << 0)
68 #define USD_DEVF_CLOSE_CTX (1u << 0)
69 
70 #ifndef USD_DEBUG
71 #define USD_DEBUG 0
72 #endif
73 
74 /*
75  * Group interrupt vector userspace map info
76  */
77 struct usd_grp_vect_map {
78     void            *va;
79     size_t          len;
80     uint32_t        vfid;
81 };
82 
83 /*
84  * structure storing interrupt resource and its mapping to FD
85  */
86 struct usd_cq_comp_intr {
87     struct vnic_intr                uci_vintr;
88     int                             uci_offset;
89     int                             uci_refcnt;
90     LIST_ENTRY(usd_cq_comp_intr)    uci_ctx_link;
91 };
92 
93 /*
94  * Instance of a usd context, corresponding to an
95  * opened libibverbs context
96  */
97 struct usd_context {
98     struct usd_ib_dev *ucx_ib_dev;  /* parent IB dev */
99     int ucx_ib_dev_fd;              /* file desc for IB dev */
100     int ucmd_ib_dev_fd;             /* Another open file descriptor for IB dev
101                                      * used for encapusulating user commands
102                                      * through GET_CONTEXT IB command */
103 
104     uint32_t ucx_flags;
105     int ucx_caps[USD_CAP_MAX];          /* device capablities */
106 
107     pthread_mutex_t ucx_mutex;          /* protect intr_list */
108     LIST_HEAD(intr_head, usd_cq_comp_intr) ucx_intr_list;
109 
110     /* Remove these after moving ud_attrs here */
111     int event_fd;
112     unsigned num_comp_vectors;
113 };
114 
115 /*
116  * Instance of a device opened by user
117  */
118 struct usd_device {
119     struct usd_context *ud_ctx;
120 
121     uint32_t ud_flags;
122     struct usd_device_attrs ud_attrs;   /* TODO move this to usd_ctx */
123 
124     /* VFs we have associated with this device */
125     struct usd_vf *ud_vf_list;
126 
127     /* PD for this device */
128     uint32_t ud_pd_handle;
129 
130     /* destination related */
131     int ud_arp_sockfd;              /* for ARP */
132     TAILQ_HEAD(, usd_dest_req) ud_pending_reqs;
133     TAILQ_HEAD(, usd_dest_req) ud_completed_reqs;
134 
135     TAILQ_ENTRY(usd_device) ud_link;
136 
137     struct usd_grp_vect_map grp_vect_map;
138 };
139 
140 /*
141  * Registered memory region
142  */
143 struct usd_mr {
144     struct usd_device *umr_dev;
145     void *umr_vaddr;
146     uint32_t umr_handle;
147     uint32_t umr_lkey;
148     uint32_t umr_rkey;
149     size_t umr_length;
150 };
151 
152 /*
153  * Information about the PCI virtual function
154  */
155 struct usd_vf {
156     uint32_t vf_id;
157     int vf_refcnt;
158     struct vnic_dev_bar vf_bar0;
159     size_t vf_bar_map_len;
160     struct vnic_dev *vf_vdev;
161     struct vnic_dev_iomap_info iomaps[RES_TYPE_MAX];
162 
163     /* Will also protect the devcmd region */
164     pthread_mutex_t vf_lock;
165     struct usd_vf *vf_next;
166     struct usd_vf *vf_prev;
167 };
168 
169 /*
170  * Holding place for information about a VF
171  */
172 struct usd_vf_info {
173     uint32_t vi_vfid;
174     dma_addr_t vi_bar_bus_addr;
175     uint32_t vi_bar_len;
176     size_t vi_barhead_len;
177     struct usnic_vnic_barres_info barres[RES_TYPE_MAX];
178 };
179 
180 /*
181  * Internal representation of a filter
182  */
183 struct usd_qp_filter {
184     enum usd_filter_type qf_type;
185     union {
186         struct {
187             int u_sockfd;
188         } qf_udp;
189     } qf_filter;
190 };
191 
192 /*
193  * Definitions and structures about queues
194  */
195 
196 /*
197  * this is used to keep track of what has been allocated and/or
198  * initialized to assist with teardown of partially completed queues
199  */
200 enum usd_qstate {
201     USD_QS_FILTER_ALLOC = (1 << 0),
202     USD_QS_VERBS_CREATED = (1 << 1),
203     USD_QS_VF_MAPPED = (1 << 2),
204     USD_QS_VNIC_ALLOCATED = (1 << 3),
205     USD_QS_VNIC_INITIALIZED = (1 << 4),
206     USD_QS_READY = (1 << 5)
207 };
208 
209 struct usd_cq_impl {
210     struct usd_cq ucq_cq;
211     struct usd_device *ucq_dev;
212     struct usd_vf *ucq_vf;
213 
214     uint32_t ucq_state;
215 
216     struct vnic_cq ucq_vnic_cq;
217 
218     void *ucq_desc_ring;
219     uint32_t ucq_next_desc;
220     uint32_t ucq_last_color;
221 
222     uint32_t ucq_index;
223     uint32_t ucq_num_entries;
224     uint32_t ucq_cqe_mask;
225     uint32_t ucq_color_shift;
226     uint32_t ucq_handle;
227 
228     int comp_fd;
229     int comp_vec;
230     int comp_req_notify;
231     int intr_offset;
232     struct usd_cq_comp_intr *ucq_intr;
233 
234     struct usd_rq **ucq_rq_map;
235     struct usd_wq **ucq_wq_map;
236 };
237 #define to_cqi(CQ) ((struct usd_cq_impl *)(CQ))
238 #define to_usdcq(CQ) (&(CQ)->ucq_cq)
239 
240 struct usd_rq {
241     struct usd_cq_impl *urq_cq;
242     uint32_t urq_state;
243 
244     uint32_t urq_index;
245     uint32_t urq_num_entries;
246     struct vnic_rq urq_vnic_rq;
247 
248     void **urq_context;
249 
250     char *urq_rxbuf;
251     char **urq_post_addr;
252     uint32_t urq_recv_credits;  /* number of available descriptors */
253     struct rq_enet_desc *urq_desc_ring;
254     struct rq_enet_desc *urq_next_desc;
255     uint32_t urq_post_index;    /* next rxbuf to post */
256     uint32_t urq_post_index_mask;
257     uint32_t urq_last_comp;
258     uint32_t urq_accum_bytes;
259 
260     uint32_t urq_num_rxbuf;
261     uint32_t urq_rxbuf_size;
262 };
263 
264 struct usd_wq_post_info {
265     void *wp_context;
266     uint32_t wp_len;
267 };
268 
269 struct usd_wq {
270     struct usd_cq_impl *uwq_cq;
271     uint32_t uwq_state;
272     struct vnic_wq uwq_vnic_wq;
273 
274     uint32_t uwq_index;
275     uint32_t uwq_num_entries;
276     uint32_t uwq_send_credits;
277     struct wq_enet_desc *uwq_desc_ring;
278     struct wq_enet_desc *uwq_next_desc;
279     uint32_t uwq_post_index;
280     uint32_t uwq_post_index_mask;
281     uint32_t uwq_last_comp;
282 
283     uint8_t *uwq_copybuf;
284     struct usd_wq_post_info *uwq_post_info;
285 
286     /* used only for PIO QPs */
287     void *pio_v_wq_addr;
288     uint64_t pio_p_wq_addr;
289     char *pio_v_pkt_buf;
290     uint64_t pio_p_pkt_buf;
291 };
292 
293 struct usd_qp_impl {
294     struct usd_qp uq_qp;        /* user's view of QP */
295 
296     struct usd_device *uq_dev;
297     struct usd_vf *uq_vf;
298 
299     struct usd_qp_attrs uq_attrs;
300 
301     uint32_t uq_qp_handle;      /* IB QP handle */
302     uint32_t uq_qp_num;
303 
304     /* primary filter for this QP */
305     struct usd_qp_filter uq_filter;
306 
307     struct usd_wq uq_wq;
308     struct usd_rq uq_rq;
309 };
310 #define to_qpi(Q) ((struct usd_qp_impl *)(Q))
311 #define to_usdqp(Q) (&(Q)->uq_qp)
312 
313 struct usd_dest {
314     union {
315         struct {
316             struct usd_udp_hdr u_hdr;
317         } ds_udp;
318     } ds_dest;
319 };
320 
321 extern struct usd_qp_ops usd_qp_ops_ud_udp;
322 extern struct usd_qp_ops usd_qp_ops_ud_pio_udp;
323 extern struct usd_qp_ops usd_qp_ops_ud_raw;
324 #endif /* _USD_H_ */
325