1 /*
2  * Intel MIC Platform Software Stack (MPSS)
3  *
4  * Copyright(c) 2014 Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License, version 2, as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * Intel SCIF driver.
16  *
17  */
18 #ifndef SCIF_EPD_H
19 #define SCIF_EPD_H
20 
21 #include <linux/delay.h>
22 #include <linux/scif.h>
23 #include <linux/scif_ioctl.h>
24 
25 #define SCIF_EPLOCK_HELD true
26 
27 enum scif_epd_state {
28 	SCIFEP_UNBOUND,
29 	SCIFEP_BOUND,
30 	SCIFEP_LISTENING,
31 	SCIFEP_CONNECTED,
32 	SCIFEP_CONNECTING,
33 	SCIFEP_MAPPING,
34 	SCIFEP_CLOSING,
35 	SCIFEP_CLLISTEN,
36 	SCIFEP_DISCONNECTED,
37 	SCIFEP_ZOMBIE
38 };
39 
40 /*
41  * struct scif_conreq - Data structure added to the connection list.
42  *
43  * @msg: connection request message received
44  * @list: link to list of connection requests
45  */
46 struct scif_conreq {
47 	struct scifmsg msg;
48 	struct list_head list;
49 };
50 
51 /* Size of the RB for the Endpoint QP */
52 #define SCIF_ENDPT_QP_SIZE 0x1000
53 
54 /*
55  * scif_endpt_qp_info - SCIF endpoint queue pair
56  *
57  * @qp - Qpair for this endpoint
58  * @qp_offset - DMA address of the QP
59  * @gnt_pld - Payload in a SCIF_CNCT_GNT message containing the
60  * physical address of the remote_qp.
61  */
62 struct scif_endpt_qp_info {
63 	struct scif_qp *qp;
64 	dma_addr_t qp_offset;
65 	dma_addr_t gnt_pld;
66 };
67 
68 /*
69  * struct scif_endpt - The SCIF endpoint data structure
70  *
71  * @state: end point state
72  * @lock: lock synchronizing access to endpoint fields like state etc
73  * @port: self port information
74  * @peer: peer port information
75  * @backlog: maximum pending connection requests
76  * @qp_info: Endpoint QP information for SCIF messaging
77  * @remote_dev: scifdev used by this endpt to communicate with remote node.
78  * @remote_ep: remote endpoint
79  * @conreqcnt: Keep track of number of connection requests.
80  * @files: Open file information used to match the id passed in with
81  *         the flush routine.
82  * @conlist: list of connection requests
83  * @conwq: waitqueue for connection processing
84  * @discon: completion used during disconnection
85  * @sendwq: waitqueue used during sending messages
86  * @recvwq: waitqueue used during message receipt
87  * @sendlock: Synchronize ordering of messages sent
88  * @recvlock: Synchronize ordering of messages received
89  * @list: link to list of various endpoints like connected, listening etc
90  * @li_accept: pending ACCEPTREG
91  * @acceptcnt: pending ACCEPTREG cnt
92  * @liacceptlist: link to listen accept
93  * @miacceptlist: link to uaccept
94  * @listenep: associated listen ep
95  * @conn_work: Non blocking connect work
96  * @conn_port: Connection port
97  * @conn_err: Errors during connection
98  * @conn_async_state: Async connection
99  * @conn_pend_wq: Used by poll while waiting for incoming connections
100  * @conn_list: List of async connection requests
101  * @rma_info: Information for triggering SCIF RMA and DMA operations
102  * @mmu_list: link to list of MMU notifier cleanup work
103  * @anon: anonymous file for use in kernel mode scif poll
104  */
105 struct scif_endpt {
106 	enum scif_epd_state state;
107 	spinlock_t lock;
108 	struct scif_port_id port;
109 	struct scif_port_id peer;
110 	int backlog;
111 	struct scif_endpt_qp_info qp_info;
112 	struct scif_dev *remote_dev;
113 	u64 remote_ep;
114 	int conreqcnt;
115 	struct files_struct *files;
116 	struct list_head conlist;
117 	wait_queue_head_t conwq;
118 	struct completion discon;
119 	wait_queue_head_t sendwq;
120 	wait_queue_head_t recvwq;
121 	struct mutex sendlock;
122 	struct mutex recvlock;
123 	struct list_head list;
124 	struct list_head li_accept;
125 	int acceptcnt;
126 	struct list_head liacceptlist;
127 	struct list_head miacceptlist;
128 	struct scif_endpt *listenep;
129 	struct scif_port_id conn_port;
130 	int conn_err;
131 	int conn_async_state;
132 	wait_queue_head_t conn_pend_wq;
133 	struct list_head conn_list;
134 	struct scif_endpt_rma_info rma_info;
135 	struct list_head mmu_list;
136 	struct file *anon;
137 };
138 
scifdev_alive(struct scif_endpt * ep)139 static inline int scifdev_alive(struct scif_endpt *ep)
140 {
141 	return _scifdev_alive(ep->remote_dev);
142 }
143 
144 /*
145  * scif_verify_epd:
146  * ep: SCIF endpoint
147  *
148  * Checks several generic error conditions and returns the
149  * appropriate error.
150  */
scif_verify_epd(struct scif_endpt * ep)151 static inline int scif_verify_epd(struct scif_endpt *ep)
152 {
153 	if (ep->state == SCIFEP_DISCONNECTED)
154 		return -ECONNRESET;
155 
156 	if (ep->state != SCIFEP_CONNECTED)
157 		return -ENOTCONN;
158 
159 	if (!scifdev_alive(ep))
160 		return -ENODEV;
161 
162 	return 0;
163 }
164 
scif_anon_inode_getfile(scif_epd_t epd)165 static inline int scif_anon_inode_getfile(scif_epd_t epd)
166 {
167 	epd->anon = anon_inode_getfile("scif", &scif_anon_fops, NULL, 0);
168 	if (IS_ERR(epd->anon))
169 		return PTR_ERR(epd->anon);
170 	return 0;
171 }
172 
scif_anon_inode_fput(scif_epd_t epd)173 static inline void scif_anon_inode_fput(scif_epd_t epd)
174 {
175 	if (epd->anon) {
176 		fput(epd->anon);
177 		epd->anon = NULL;
178 	}
179 }
180 
181 void scif_cleanup_zombie_epd(void);
182 void scif_teardown_ep(void *endpt);
183 void scif_cleanup_ep_qp(struct scif_endpt *ep);
184 void scif_add_epd_to_zombie_list(struct scif_endpt *ep, bool eplock_held);
185 void scif_get_node_info(void);
186 void scif_send_acks(struct scif_dev *dev);
187 void scif_conn_handler(struct work_struct *work);
188 int scif_rsrv_port(u16 port);
189 void scif_get_port(u16 port);
190 int scif_get_new_port(void);
191 void scif_put_port(u16 port);
192 int scif_user_send(scif_epd_t epd, void __user *msg, int len, int flags);
193 int scif_user_recv(scif_epd_t epd, void __user *msg, int len, int flags);
194 void scif_cnctreq(struct scif_dev *scifdev, struct scifmsg *msg);
195 void scif_cnctgnt(struct scif_dev *scifdev, struct scifmsg *msg);
196 void scif_cnctgnt_ack(struct scif_dev *scifdev, struct scifmsg *msg);
197 void scif_cnctgnt_nack(struct scif_dev *scifdev, struct scifmsg *msg);
198 void scif_cnctrej(struct scif_dev *scifdev, struct scifmsg *msg);
199 void scif_discnct(struct scif_dev *scifdev, struct scifmsg *msg);
200 void scif_discnt_ack(struct scif_dev *scifdev, struct scifmsg *msg);
201 void scif_clientsend(struct scif_dev *scifdev, struct scifmsg *msg);
202 void scif_clientrcvd(struct scif_dev *scifdev, struct scifmsg *msg);
203 int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block);
204 int __scif_flush(scif_epd_t epd);
205 int scif_mmap(struct vm_area_struct *vma, scif_epd_t epd);
206 __poll_t __scif_pollfd(struct file *f, poll_table *wait,
207 			   struct scif_endpt *ep);
208 int __scif_pin_pages(void *addr, size_t len, int *out_prot,
209 		     int map_flags, scif_pinned_pages_t *pages);
210 #endif /* SCIF_EPD_H */
211