treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / drivers / misc / mic / scif / scif_fd.c
blob3f08646cd78abdeda3c4e1920d605064ddec869d
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Intel MIC Platform Software Stack (MPSS)
5 * Copyright(c) 2014 Intel Corporation.
7 * Intel SCIF driver.
8 */
9 #include "scif_main.h"
11 static int scif_fdopen(struct inode *inode, struct file *f)
13 struct scif_endpt *priv = scif_open();
15 if (!priv)
16 return -ENOMEM;
17 f->private_data = priv;
18 return 0;
21 static int scif_fdclose(struct inode *inode, struct file *f)
23 struct scif_endpt *priv = f->private_data;
25 return scif_close(priv);
28 static int scif_fdmmap(struct file *f, struct vm_area_struct *vma)
30 struct scif_endpt *priv = f->private_data;
32 return scif_mmap(vma, priv);
35 static __poll_t scif_fdpoll(struct file *f, poll_table *wait)
37 struct scif_endpt *priv = f->private_data;
39 return __scif_pollfd(f, wait, priv);
42 static int scif_fdflush(struct file *f, fl_owner_t id)
44 struct scif_endpt *ep = f->private_data;
46 spin_lock(&ep->lock);
48 * The listening endpoint stashes the open file information before
49 * waiting for incoming connections. The release callback would never be
50 * called if the application closed the endpoint, while waiting for
51 * incoming connections from a separate thread since the file descriptor
52 * reference count is bumped up in the accept IOCTL. Call the flush
53 * routine if the id matches the endpoint open file information so that
54 * the listening endpoint can be woken up and the fd released.
56 if (ep->files == id)
57 __scif_flush(ep);
58 spin_unlock(&ep->lock);
59 return 0;
62 static __always_inline void scif_err_debug(int err, const char *str)
65 * ENOTCONN is a common uninteresting error which is
66 * flooding debug messages to the console unnecessarily.
68 if (err < 0 && err != -ENOTCONN)
69 dev_dbg(scif_info.mdev.this_device, "%s err %d\n", str, err);
72 static long scif_fdioctl(struct file *f, unsigned int cmd, unsigned long arg)
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;
80 non_block = !!(f->f_flags & O_NONBLOCK);
82 switch (cmd) {
83 case SCIF_BIND:
85 int pn;
87 if (copy_from_user(&pn, argp, sizeof(pn)))
88 return -EFAULT;
90 pn = scif_bind(priv, pn);
91 if (pn < 0)
92 return pn;
94 if (copy_to_user(argp, &pn, sizeof(pn)))
95 return -EFAULT;
97 return 0;
99 case SCIF_LISTEN:
100 return scif_listen(priv, arg);
101 case SCIF_CONNECT:
103 struct scifioctl_connect req;
104 struct scif_endpt *ep = (struct scif_endpt *)priv;
106 if (copy_from_user(&req, argp, sizeof(req)))
107 return -EFAULT;
109 err = __scif_connect(priv, &req.peer, non_block);
110 if (err < 0)
111 return err;
113 req.self.node = ep->port.node;
114 req.self.port = ep->port.port;
116 if (copy_to_user(argp, &req, sizeof(req)))
117 return -EFAULT;
119 return 0;
122 * Accept is done in two halves. The request ioctl does the basic
123 * functionality of accepting the request and returning the information
124 * about it including the internal ID of the end point. The register
125 * is done with the internal ID on a new file descriptor opened by the
126 * requesting process.
128 case SCIF_ACCEPTREQ:
130 struct scifioctl_accept request;
131 scif_epd_t *ep = (scif_epd_t *)&request.endpt;
133 if (copy_from_user(&request, argp, sizeof(request)))
134 return -EFAULT;
136 err = scif_accept(priv, &request.peer, ep, request.flags);
137 if (err < 0)
138 return err;
140 if (copy_to_user(argp, &request, sizeof(request))) {
141 scif_close(*ep);
142 return -EFAULT;
145 * Add to the list of user mode eps where the second half
146 * of the accept is not yet completed.
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);
155 return 0;
157 case SCIF_ACCEPTREG:
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;
166 /* Finally replace the pointer to the accepted endpoint */
167 if (copy_from_user(&newep, argp, sizeof(void *)))
168 return -EFAULT;
170 /* Remove form the user accept queue */
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;
182 if (!fep) {
183 mutex_unlock(&scif_info.eplock);
184 return -ENOENT;
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;
198 mutex_unlock(&scif_info.eplock);
200 /* Free the resources automatically created from the open. */
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;
207 case SCIF_SEND:
209 struct scif_endpt *priv = f->private_data;
211 if (copy_from_user(&request, argp,
212 sizeof(struct scifioctl_msg))) {
213 err = -EFAULT;
214 goto send_err;
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;
226 err = 0;
227 send_err:
228 scif_err_debug(err, "scif_send");
229 return err;
231 case SCIF_RECV:
233 struct scif_endpt *priv = f->private_data;
235 if (copy_from_user(&request, argp,
236 sizeof(struct scifioctl_msg))) {
237 err = -EFAULT;
238 goto recv_err;
241 err = scif_user_recv(priv, (void __user *)request.msg,
242 request.len, request.flags);
243 if (err < 0)
244 goto recv_err;
246 if (copy_to_user(&
247 ((struct scifioctl_msg __user *)argp)->out_len,
248 &err, sizeof(err))) {
249 err = -EFAULT;
250 goto recv_err;
252 err = 0;
253 recv_err:
254 scif_err_debug(err, "scif_recv");
255 return err;
257 case SCIF_GET_NODEIDS:
259 struct scifioctl_node_ids node_ids;
260 int entries;
261 u16 *nodes;
262 void __user *unodes, *uself;
263 u16 self;
265 if (copy_from_user(&node_ids, argp, sizeof(node_ids))) {
266 err = -EFAULT;
267 goto getnodes_err2;
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;
276 node_ids.len = scif_get_node_ids(nodes, entries, &self);
278 unodes = (void __user *)node_ids.nodes;
279 if (copy_to_user(unodes, nodes, sizeof(u16) * entries)) {
280 err = -EFAULT;
281 goto getnodes_err1;
284 uself = (void __user *)node_ids.self;
285 if (copy_to_user(uself, &self, sizeof(u16))) {
286 err = -EFAULT;
287 goto getnodes_err1;
290 if (copy_to_user(argp, &node_ids, sizeof(node_ids))) {
291 err = -EFAULT;
292 goto getnodes_err1;
294 getnodes_err1:
295 kfree(nodes);
296 getnodes_err2:
297 return err;
299 case SCIF_REG:
301 struct scif_endpt *priv = f->private_data;
302 struct scifioctl_reg reg;
303 off_t ret;
305 if (copy_from_user(&reg, argp, sizeof(reg))) {
306 err = -EFAULT;
307 goto reg_err;
309 if (reg.flags & SCIF_MAP_KERNEL) {
310 err = -EINVAL;
311 goto reg_err;
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;
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;
325 err = 0;
326 reg_err:
327 scif_err_debug(err, "scif_register");
328 return err;
330 case SCIF_UNREG:
332 struct scif_endpt *priv = f->private_data;
333 struct scifioctl_unreg unreg;
335 if (copy_from_user(&unreg, argp, sizeof(unreg))) {
336 err = -EFAULT;
337 goto unreg_err;
339 err = scif_unregister(priv, unreg.offset, unreg.len);
340 unreg_err:
341 scif_err_debug(err, "scif_unregister");
342 return err;
344 case SCIF_READFROM:
346 struct scif_endpt *priv = f->private_data;
347 struct scifioctl_copy copy;
349 if (copy_from_user(&copy, argp, sizeof(copy))) {
350 err = -EFAULT;
351 goto readfrom_err;
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;
359 case SCIF_WRITETO:
361 struct scif_endpt *priv = f->private_data;
362 struct scifioctl_copy copy;
364 if (copy_from_user(&copy, argp, sizeof(copy))) {
365 err = -EFAULT;
366 goto writeto_err;
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;
374 case SCIF_VREADFROM:
376 struct scif_endpt *priv = f->private_data;
377 struct scifioctl_copy copy;
379 if (copy_from_user(&copy, argp, sizeof(copy))) {
380 err = -EFAULT;
381 goto vreadfrom_err;
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;
389 case SCIF_VWRITETO:
391 struct scif_endpt *priv = f->private_data;
392 struct scifioctl_copy copy;
394 if (copy_from_user(&copy, argp, sizeof(copy))) {
395 err = -EFAULT;
396 goto vwriteto_err;
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;
404 case SCIF_FENCE_MARK:
406 struct scif_endpt *priv = f->private_data;
407 struct scifioctl_fence_mark mark;
408 int tmp_mark = 0;
410 if (copy_from_user(&mark, argp, sizeof(mark))) {
411 err = -EFAULT;
412 goto fence_mark_err;
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;
422 fence_mark_err:
423 scif_err_debug(err, "scif_fence_mark");
424 return err;
426 case SCIF_FENCE_WAIT:
428 struct scif_endpt *priv = f->private_data;
430 err = scif_fence_wait(priv, arg);
431 scif_err_debug(err, "scif_fence_wait");
432 return err;
434 case SCIF_FENCE_SIGNAL:
436 struct scif_endpt *priv = f->private_data;
437 struct scifioctl_fence_signal signal;
439 if (copy_from_user(&signal, argp, sizeof(signal))) {
440 err = -EFAULT;
441 goto fence_signal_err;
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;
451 return -EINVAL;
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,