This source file includes following definitions.
- scif_fdopen
- scif_fdclose
- scif_fdmmap
- scif_fdpoll
- scif_fdflush
- scif_err_debug
- scif_fdioctl
1
2
3
4
5
6
7
8
9 #include "scif_main.h"
10
11 static int scif_fdopen(struct inode *inode, struct file *f)
12 {
13 struct scif_endpt *priv = scif_open();
14
15 if (!priv)
16 return -ENOMEM;
17 f->private_data = priv;
18 return 0;
19 }
20
21 static int scif_fdclose(struct inode *inode, struct file *f)
22 {
23 struct scif_endpt *priv = f->private_data;
24
25 return scif_close(priv);
26 }
27
28 static int scif_fdmmap(struct file *f, struct vm_area_struct *vma)
29 {
30 struct scif_endpt *priv = f->private_data;
31
32 return scif_mmap(vma, priv);
33 }
34
35 static __poll_t scif_fdpoll(struct file *f, poll_table *wait)
36 {
37 struct scif_endpt *priv = f->private_data;
38
39 return __scif_pollfd(f, wait, priv);
40 }
41
42 static int scif_fdflush(struct file *f, fl_owner_t id)
43 {
44 struct scif_endpt *ep = f->private_data;
45
46 spin_lock(&ep->lock);
47
48
49
50
51
52
53
54
55
56 if (ep->files == id)
57 __scif_flush(ep);
58 spin_unlock(&ep->lock);
59 return 0;
60 }
61
62 static __always_inline void scif_err_debug(int err, const char *str)
63 {
64
65
66
67
68 if (err < 0 && err != -ENOTCONN)
69 dev_dbg(scif_info.mdev.this_device, "%s err %d\n", str, err);
70 }
71
72 static long scif_fdioctl(struct file *f, unsigned int cmd, unsigned long arg)
73 {
74 struct scif_endpt *priv = f->private_data;
75 void __user *argp = (void __user *)arg;
76 int err = 0;
77 struct scifioctl_msg request;
78 bool non_block = false;
79
80 non_block = !!(f->f_flags & O_NONBLOCK);
81
82 switch (cmd) {
83 case SCIF_BIND:
84 {
85 int pn;
86
87 if (copy_from_user(&pn, argp, sizeof(pn)))
88 return -EFAULT;
89
90 pn = scif_bind(priv, pn);
91 if (pn < 0)
92 return pn;
93
94 if (copy_to_user(argp, &pn, sizeof(pn)))
95 return -EFAULT;
96
97 return 0;
98 }
99 case SCIF_LISTEN:
100 return scif_listen(priv, arg);
101 case SCIF_CONNECT:
102 {
103 struct scifioctl_connect req;
104 struct scif_endpt *ep = (struct scif_endpt *)priv;
105
106 if (copy_from_user(&req, argp, sizeof(req)))
107 return -EFAULT;
108
109 err = __scif_connect(priv, &req.peer, non_block);
110 if (err < 0)
111 return err;
112
113 req.self.node = ep->port.node;
114 req.self.port = ep->port.port;
115
116 if (copy_to_user(argp, &req, sizeof(req)))
117 return -EFAULT;
118
119 return 0;
120 }
121
122
123
124
125
126
127
128 case SCIF_ACCEPTREQ:
129 {
130 struct scifioctl_accept request;
131 scif_epd_t *ep = (scif_epd_t *)&request.endpt;
132
133 if (copy_from_user(&request, argp, sizeof(request)))
134 return -EFAULT;
135
136 err = scif_accept(priv, &request.peer, ep, request.flags);
137 if (err < 0)
138 return err;
139
140 if (copy_to_user(argp, &request, sizeof(request))) {
141 scif_close(*ep);
142 return -EFAULT;
143 }
144
145
146
147
148 mutex_lock(&scif_info.eplock);
149 list_add_tail(&((*ep)->miacceptlist), &scif_info.uaccept);
150 list_add_tail(&((*ep)->liacceptlist), &priv->li_accept);
151 (*ep)->listenep = priv;
152 priv->acceptcnt++;
153 mutex_unlock(&scif_info.eplock);
154
155 return 0;
156 }
157 case SCIF_ACCEPTREG:
158 {
159 struct scif_endpt *priv = f->private_data;
160 struct scif_endpt *newep;
161 struct scif_endpt *lisep;
162 struct scif_endpt *fep = NULL;
163 struct scif_endpt *tmpep;
164 struct list_head *pos, *tmpq;
165
166
167 if (copy_from_user(&newep, argp, sizeof(void *)))
168 return -EFAULT;
169
170
171 mutex_lock(&scif_info.eplock);
172 list_for_each_safe(pos, tmpq, &scif_info.uaccept) {
173 tmpep = list_entry(pos,
174 struct scif_endpt, miacceptlist);
175 if (tmpep == newep) {
176 list_del(pos);
177 fep = tmpep;
178 break;
179 }
180 }
181
182 if (!fep) {
183 mutex_unlock(&scif_info.eplock);
184 return -ENOENT;
185 }
186
187 lisep = newep->listenep;
188 list_for_each_safe(pos, tmpq, &lisep->li_accept) {
189 tmpep = list_entry(pos,
190 struct scif_endpt, liacceptlist);
191 if (tmpep == newep) {
192 list_del(pos);
193 lisep->acceptcnt--;
194 break;
195 }
196 }
197
198 mutex_unlock(&scif_info.eplock);
199
200
201 scif_anon_inode_fput(priv);
202 scif_teardown_ep(priv);
203 scif_add_epd_to_zombie_list(priv, !SCIF_EPLOCK_HELD);
204 f->private_data = newep;
205 return 0;
206 }
207 case SCIF_SEND:
208 {
209 struct scif_endpt *priv = f->private_data;
210
211 if (copy_from_user(&request, argp,
212 sizeof(struct scifioctl_msg))) {
213 err = -EFAULT;
214 goto send_err;
215 }
216 err = scif_user_send(priv, (void __user *)request.msg,
217 request.len, request.flags);
218 if (err < 0)
219 goto send_err;
220 if (copy_to_user(&
221 ((struct scifioctl_msg __user *)argp)->out_len,
222 &err, sizeof(err))) {
223 err = -EFAULT;
224 goto send_err;
225 }
226 err = 0;
227 send_err:
228 scif_err_debug(err, "scif_send");
229 return err;
230 }
231 case SCIF_RECV:
232 {
233 struct scif_endpt *priv = f->private_data;
234
235 if (copy_from_user(&request, argp,
236 sizeof(struct scifioctl_msg))) {
237 err = -EFAULT;
238 goto recv_err;
239 }
240
241 err = scif_user_recv(priv, (void __user *)request.msg,
242 request.len, request.flags);
243 if (err < 0)
244 goto recv_err;
245
246 if (copy_to_user(&
247 ((struct scifioctl_msg __user *)argp)->out_len,
248 &err, sizeof(err))) {
249 err = -EFAULT;
250 goto recv_err;
251 }
252 err = 0;
253 recv_err:
254 scif_err_debug(err, "scif_recv");
255 return err;
256 }
257 case SCIF_GET_NODEIDS:
258 {
259 struct scifioctl_node_ids node_ids;
260 int entries;
261 u16 *nodes;
262 void __user *unodes, *uself;
263 u16 self;
264
265 if (copy_from_user(&node_ids, argp, sizeof(node_ids))) {
266 err = -EFAULT;
267 goto getnodes_err2;
268 }
269
270 entries = min_t(int, scif_info.maxid, node_ids.len);
271 nodes = kmalloc_array(entries, sizeof(u16), GFP_KERNEL);
272 if (entries && !nodes) {
273 err = -ENOMEM;
274 goto getnodes_err2;
275 }
276 node_ids.len = scif_get_node_ids(nodes, entries, &self);
277
278 unodes = (void __user *)node_ids.nodes;
279 if (copy_to_user(unodes, nodes, sizeof(u16) * entries)) {
280 err = -EFAULT;
281 goto getnodes_err1;
282 }
283
284 uself = (void __user *)node_ids.self;
285 if (copy_to_user(uself, &self, sizeof(u16))) {
286 err = -EFAULT;
287 goto getnodes_err1;
288 }
289
290 if (copy_to_user(argp, &node_ids, sizeof(node_ids))) {
291 err = -EFAULT;
292 goto getnodes_err1;
293 }
294 getnodes_err1:
295 kfree(nodes);
296 getnodes_err2:
297 return err;
298 }
299 case SCIF_REG:
300 {
301 struct scif_endpt *priv = f->private_data;
302 struct scifioctl_reg reg;
303 off_t ret;
304
305 if (copy_from_user(®, argp, sizeof(reg))) {
306 err = -EFAULT;
307 goto reg_err;
308 }
309 if (reg.flags & SCIF_MAP_KERNEL) {
310 err = -EINVAL;
311 goto reg_err;
312 }
313 ret = scif_register(priv, (void *)reg.addr, reg.len,
314 reg.offset, reg.prot, reg.flags);
315 if (ret < 0) {
316 err = (int)ret;
317 goto reg_err;
318 }
319
320 if (copy_to_user(&((struct scifioctl_reg __user *)argp)
321 ->out_offset, &ret, sizeof(reg.out_offset))) {
322 err = -EFAULT;
323 goto reg_err;
324 }
325 err = 0;
326 reg_err:
327 scif_err_debug(err, "scif_register");
328 return err;
329 }
330 case SCIF_UNREG:
331 {
332 struct scif_endpt *priv = f->private_data;
333 struct scifioctl_unreg unreg;
334
335 if (copy_from_user(&unreg, argp, sizeof(unreg))) {
336 err = -EFAULT;
337 goto unreg_err;
338 }
339 err = scif_unregister(priv, unreg.offset, unreg.len);
340 unreg_err:
341 scif_err_debug(err, "scif_unregister");
342 return err;
343 }
344 case SCIF_READFROM:
345 {
346 struct scif_endpt *priv = f->private_data;
347 struct scifioctl_copy copy;
348
349 if (copy_from_user(©, argp, sizeof(copy))) {
350 err = -EFAULT;
351 goto readfrom_err;
352 }
353 err = scif_readfrom(priv, copy.loffset, copy.len, copy.roffset,
354 copy.flags);
355 readfrom_err:
356 scif_err_debug(err, "scif_readfrom");
357 return err;
358 }
359 case SCIF_WRITETO:
360 {
361 struct scif_endpt *priv = f->private_data;
362 struct scifioctl_copy copy;
363
364 if (copy_from_user(©, argp, sizeof(copy))) {
365 err = -EFAULT;
366 goto writeto_err;
367 }
368 err = scif_writeto(priv, copy.loffset, copy.len, copy.roffset,
369 copy.flags);
370 writeto_err:
371 scif_err_debug(err, "scif_writeto");
372 return err;
373 }
374 case SCIF_VREADFROM:
375 {
376 struct scif_endpt *priv = f->private_data;
377 struct scifioctl_copy copy;
378
379 if (copy_from_user(©, argp, sizeof(copy))) {
380 err = -EFAULT;
381 goto vreadfrom_err;
382 }
383 err = scif_vreadfrom(priv, (void __force *)copy.addr, copy.len,
384 copy.roffset, copy.flags);
385 vreadfrom_err:
386 scif_err_debug(err, "scif_vreadfrom");
387 return err;
388 }
389 case SCIF_VWRITETO:
390 {
391 struct scif_endpt *priv = f->private_data;
392 struct scifioctl_copy copy;
393
394 if (copy_from_user(©, argp, sizeof(copy))) {
395 err = -EFAULT;
396 goto vwriteto_err;
397 }
398 err = scif_vwriteto(priv, (void __force *)copy.addr, copy.len,
399 copy.roffset, copy.flags);
400 vwriteto_err:
401 scif_err_debug(err, "scif_vwriteto");
402 return err;
403 }
404 case SCIF_FENCE_MARK:
405 {
406 struct scif_endpt *priv = f->private_data;
407 struct scifioctl_fence_mark mark;
408 int tmp_mark = 0;
409
410 if (copy_from_user(&mark, argp, sizeof(mark))) {
411 err = -EFAULT;
412 goto fence_mark_err;
413 }
414 err = scif_fence_mark(priv, mark.flags, &tmp_mark);
415 if (err)
416 goto fence_mark_err;
417 if (copy_to_user((void __user *)mark.mark, &tmp_mark,
418 sizeof(tmp_mark))) {
419 err = -EFAULT;
420 goto fence_mark_err;
421 }
422 fence_mark_err:
423 scif_err_debug(err, "scif_fence_mark");
424 return err;
425 }
426 case SCIF_FENCE_WAIT:
427 {
428 struct scif_endpt *priv = f->private_data;
429
430 err = scif_fence_wait(priv, arg);
431 scif_err_debug(err, "scif_fence_wait");
432 return err;
433 }
434 case SCIF_FENCE_SIGNAL:
435 {
436 struct scif_endpt *priv = f->private_data;
437 struct scifioctl_fence_signal signal;
438
439 if (copy_from_user(&signal, argp, sizeof(signal))) {
440 err = -EFAULT;
441 goto fence_signal_err;
442 }
443
444 err = scif_fence_signal(priv, signal.loff, signal.lval,
445 signal.roff, signal.rval, signal.flags);
446 fence_signal_err:
447 scif_err_debug(err, "scif_fence_signal");
448 return err;
449 }
450 }
451 return -EINVAL;
452 }
453
454 const struct file_operations scif_fops = {
455 .open = scif_fdopen,
456 .release = scif_fdclose,
457 .unlocked_ioctl = scif_fdioctl,
458 .mmap = scif_fdmmap,
459 .poll = scif_fdpoll,
460 .flush = scif_fdflush,
461 .owner = THIS_MODULE,
462 };