blob: 812c23f9853cd218bf4f61955d5ca112b2a2e65e [file] [log] [blame]
Sudeep Dutte9089f42015-04-29 05:32:35 -07001/*
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#include "scif_main.h"
19
20static int scif_fdopen(struct inode *inode, struct file *f)
21{
22 struct scif_endpt *priv = scif_open();
23
24 if (!priv)
25 return -ENOMEM;
26 f->private_data = priv;
27 return 0;
28}
29
30static int scif_fdclose(struct inode *inode, struct file *f)
31{
32 struct scif_endpt *priv = f->private_data;
33
34 return scif_close(priv);
35}
36
37static int scif_fdflush(struct file *f, fl_owner_t id)
38{
39 struct scif_endpt *ep = f->private_data;
40
41 spin_lock(&ep->lock);
42 /*
43 * The listening endpoint stashes the open file information before
44 * waiting for incoming connections. The release callback would never be
45 * called if the application closed the endpoint, while waiting for
46 * incoming connections from a separate thread since the file descriptor
47 * reference count is bumped up in the accept IOCTL. Call the flush
48 * routine if the id matches the endpoint open file information so that
49 * the listening endpoint can be woken up and the fd released.
50 */
51 if (ep->files == id)
52 __scif_flush(ep);
53 spin_unlock(&ep->lock);
54 return 0;
55}
56
57static __always_inline void scif_err_debug(int err, const char *str)
58{
59 /*
60 * ENOTCONN is a common uninteresting error which is
61 * flooding debug messages to the console unnecessarily.
62 */
63 if (err < 0 && err != -ENOTCONN)
64 dev_dbg(scif_info.mdev.this_device, "%s err %d\n", str, err);
65}
66
67static long scif_fdioctl(struct file *f, unsigned int cmd, unsigned long arg)
68{
69 struct scif_endpt *priv = f->private_data;
70 void __user *argp = (void __user *)arg;
71 bool non_block = false;
72
73 non_block = !!(f->f_flags & O_NONBLOCK);
74
75 switch (cmd) {
76 case SCIF_BIND:
77 {
78 int pn;
79
80 if (copy_from_user(&pn, argp, sizeof(pn)))
81 return -EFAULT;
82
83 pn = scif_bind(priv, pn);
84 if (pn < 0)
85 return pn;
86
87 if (copy_to_user(argp, &pn, sizeof(pn)))
88 return -EFAULT;
89
90 return 0;
91 }
92 case SCIF_LISTEN:
93 return scif_listen(priv, arg);
94 }
95 return -EINVAL;
96}
97
98const struct file_operations scif_fops = {
99 .open = scif_fdopen,
100 .release = scif_fdclose,
101 .unlocked_ioctl = scif_fdioctl,
102 .flush = scif_fdflush,
103 .owner = THIS_MODULE,
104};