blob: b47d56d5d93c2e20c75876ed5f9f7666209e8a16 [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 <linux/scif.h>
19#include "scif_main.h"
20#include "scif_map.h"
21
22static const char * const scif_ep_states[] = {
23 "Unbound",
24 "Bound",
25 "Listening",
26 "Connected",
27 "Connecting",
28 "Mapping",
29 "Closing",
30 "Close Listening",
31 "Disconnected",
32 "Zombie"};
33
34enum conn_async_state {
35 ASYNC_CONN_IDLE = 1, /* ep setup for async connect */
36 ASYNC_CONN_INPROGRESS, /* async connect in progress */
37 ASYNC_CONN_FLUSH_WORK /* async work flush in progress */
38};
39
Ashutosh Dixitb7f94442015-09-29 18:10:44 -070040/*
41 * File operations for anonymous inode file associated with a SCIF endpoint,
42 * used in kernel mode SCIF poll. Kernel mode SCIF poll calls portions of the
43 * poll API in the kernel and these take in a struct file *. Since a struct
44 * file is not available to kernel mode SCIF, it uses an anonymous file for
45 * this purpose.
46 */
47const struct file_operations scif_anon_fops = {
48 .owner = THIS_MODULE,
49};
50
Sudeep Dutte9089f42015-04-29 05:32:35 -070051scif_epd_t scif_open(void)
52{
53 struct scif_endpt *ep;
Ashutosh Dixitb7f94442015-09-29 18:10:44 -070054 int err;
Sudeep Dutte9089f42015-04-29 05:32:35 -070055
56 might_sleep();
57 ep = kzalloc(sizeof(*ep), GFP_KERNEL);
58 if (!ep)
59 goto err_ep_alloc;
60
61 ep->qp_info.qp = kzalloc(sizeof(*ep->qp_info.qp), GFP_KERNEL);
62 if (!ep->qp_info.qp)
63 goto err_qp_alloc;
64
Ashutosh Dixitb7f94442015-09-29 18:10:44 -070065 err = scif_anon_inode_getfile(ep);
66 if (err)
67 goto err_anon_inode;
68
Sudeep Dutte9089f42015-04-29 05:32:35 -070069 spin_lock_init(&ep->lock);
70 mutex_init(&ep->sendlock);
71 mutex_init(&ep->recvlock);
72
73 ep->state = SCIFEP_UNBOUND;
74 dev_dbg(scif_info.mdev.this_device,
75 "SCIFAPI open: ep %p success\n", ep);
76 return ep;
77
Ashutosh Dixitb7f94442015-09-29 18:10:44 -070078err_anon_inode:
79 kfree(ep->qp_info.qp);
Sudeep Dutte9089f42015-04-29 05:32:35 -070080err_qp_alloc:
81 kfree(ep);
82err_ep_alloc:
83 return NULL;
84}
85EXPORT_SYMBOL_GPL(scif_open);
86
87/*
88 * scif_disconnect_ep - Disconnects the endpoint if found
89 * @epd: The end point returned from scif_open()
90 */
91static struct scif_endpt *scif_disconnect_ep(struct scif_endpt *ep)
92{
93 struct scifmsg msg;
94 struct scif_endpt *fep = NULL;
95 struct scif_endpt *tmpep;
96 struct list_head *pos, *tmpq;
97 int err;
98
99 /*
100 * Wake up any threads blocked in send()/recv() before closing
101 * out the connection. Grabbing and releasing the send/recv lock
102 * will ensure that any blocked senders/receivers have exited for
103 * Ring 0 endpoints. It is a Ring 0 bug to call send/recv after
104 * close. Ring 3 endpoints are not affected since close will not
105 * be called while there are IOCTLs executing.
106 */
107 wake_up_interruptible(&ep->sendwq);
108 wake_up_interruptible(&ep->recvwq);
109 mutex_lock(&ep->sendlock);
110 mutex_unlock(&ep->sendlock);
111 mutex_lock(&ep->recvlock);
112 mutex_unlock(&ep->recvlock);
113
114 /* Remove from the connected list */
115 mutex_lock(&scif_info.connlock);
116 list_for_each_safe(pos, tmpq, &scif_info.connected) {
117 tmpep = list_entry(pos, struct scif_endpt, list);
118 if (tmpep == ep) {
119 list_del(pos);
120 fep = tmpep;
121 spin_lock(&ep->lock);
122 break;
123 }
124 }
125
126 if (!fep) {
127 /*
128 * The other side has completed the disconnect before
129 * the end point can be removed from the list. Therefore
130 * the ep lock is not locked, traverse the disconnected
131 * list to find the endpoint and release the conn lock.
132 */
133 list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
134 tmpep = list_entry(pos, struct scif_endpt, list);
135 if (tmpep == ep) {
136 list_del(pos);
137 break;
138 }
139 }
140 mutex_unlock(&scif_info.connlock);
141 return NULL;
142 }
143
144 init_completion(&ep->discon);
145 msg.uop = SCIF_DISCNCT;
146 msg.src = ep->port;
147 msg.dst = ep->peer;
148 msg.payload[0] = (u64)ep;
149 msg.payload[1] = ep->remote_ep;
150
151 err = scif_nodeqp_send(ep->remote_dev, &msg);
152 spin_unlock(&ep->lock);
153 mutex_unlock(&scif_info.connlock);
154
155 if (!err)
156 /* Wait for the remote node to respond with SCIF_DISCNT_ACK */
157 wait_for_completion_timeout(&ep->discon,
158 SCIF_NODE_ALIVE_TIMEOUT);
159 return ep;
160}
161
162int scif_close(scif_epd_t epd)
163{
164 struct scif_endpt *ep = (struct scif_endpt *)epd;
165 struct scif_endpt *tmpep;
166 struct list_head *pos, *tmpq;
167 enum scif_epd_state oldstate;
168 bool flush_conn;
169
170 dev_dbg(scif_info.mdev.this_device, "SCIFAPI close: ep %p %s\n",
171 ep, scif_ep_states[ep->state]);
172 might_sleep();
173 spin_lock(&ep->lock);
174 flush_conn = (ep->conn_async_state == ASYNC_CONN_INPROGRESS);
175 spin_unlock(&ep->lock);
176
177 if (flush_conn)
178 flush_work(&scif_info.conn_work);
179
180 spin_lock(&ep->lock);
181 oldstate = ep->state;
182
183 ep->state = SCIFEP_CLOSING;
184
185 switch (oldstate) {
186 case SCIFEP_ZOMBIE:
187 case SCIFEP_DISCONNECTED:
188 spin_unlock(&ep->lock);
189 /* Remove from the disconnected list */
190 mutex_lock(&scif_info.connlock);
191 list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
192 tmpep = list_entry(pos, struct scif_endpt, list);
193 if (tmpep == ep) {
194 list_del(pos);
195 break;
196 }
197 }
198 mutex_unlock(&scif_info.connlock);
199 break;
200 case SCIFEP_UNBOUND:
201 case SCIFEP_BOUND:
202 case SCIFEP_CONNECTING:
203 spin_unlock(&ep->lock);
204 break;
205 case SCIFEP_MAPPING:
206 case SCIFEP_CONNECTED:
207 case SCIFEP_CLOSING:
208 {
209 spin_unlock(&ep->lock);
210 scif_disconnect_ep(ep);
211 break;
212 }
213 case SCIFEP_LISTENING:
214 case SCIFEP_CLLISTEN:
215 {
216 struct scif_conreq *conreq;
217 struct scifmsg msg;
218 struct scif_endpt *aep;
219
220 spin_unlock(&ep->lock);
221 spin_lock(&scif_info.eplock);
222
223 /* remove from listen list */
224 list_for_each_safe(pos, tmpq, &scif_info.listen) {
225 tmpep = list_entry(pos, struct scif_endpt, list);
226 if (tmpep == ep)
227 list_del(pos);
228 }
229 /* Remove any dangling accepts */
230 while (ep->acceptcnt) {
231 aep = list_first_entry(&ep->li_accept,
232 struct scif_endpt, liacceptlist);
233 list_del(&aep->liacceptlist);
234 scif_put_port(aep->port.port);
235 list_for_each_safe(pos, tmpq, &scif_info.uaccept) {
236 tmpep = list_entry(pos, struct scif_endpt,
237 miacceptlist);
238 if (tmpep == aep) {
239 list_del(pos);
240 break;
241 }
242 }
243 spin_unlock(&scif_info.eplock);
244 mutex_lock(&scif_info.connlock);
245 list_for_each_safe(pos, tmpq, &scif_info.connected) {
246 tmpep = list_entry(pos,
247 struct scif_endpt, list);
248 if (tmpep == aep) {
249 list_del(pos);
250 break;
251 }
252 }
253 list_for_each_safe(pos, tmpq, &scif_info.disconnected) {
254 tmpep = list_entry(pos,
255 struct scif_endpt, list);
256 if (tmpep == aep) {
257 list_del(pos);
258 break;
259 }
260 }
261 mutex_unlock(&scif_info.connlock);
262 scif_teardown_ep(aep);
263 spin_lock(&scif_info.eplock);
264 scif_add_epd_to_zombie_list(aep, SCIF_EPLOCK_HELD);
265 ep->acceptcnt--;
266 }
267
268 spin_lock(&ep->lock);
269 spin_unlock(&scif_info.eplock);
270
271 /* Remove and reject any pending connection requests. */
272 while (ep->conreqcnt) {
273 conreq = list_first_entry(&ep->conlist,
274 struct scif_conreq, list);
275 list_del(&conreq->list);
276
277 msg.uop = SCIF_CNCT_REJ;
278 msg.dst.node = conreq->msg.src.node;
279 msg.dst.port = conreq->msg.src.port;
280 msg.payload[0] = conreq->msg.payload[0];
281 msg.payload[1] = conreq->msg.payload[1];
282 /*
283 * No Error Handling on purpose for scif_nodeqp_send().
284 * If the remote node is lost we still want free the
285 * connection requests on the self node.
286 */
287 scif_nodeqp_send(&scif_dev[conreq->msg.src.node],
288 &msg);
289 ep->conreqcnt--;
290 kfree(conreq);
291 }
292
293 spin_unlock(&ep->lock);
294 /* If a kSCIF accept is waiting wake it up */
295 wake_up_interruptible(&ep->conwq);
296 break;
297 }
298 }
299 scif_put_port(ep->port.port);
Ashutosh Dixitb7f94442015-09-29 18:10:44 -0700300 scif_anon_inode_fput(ep);
Sudeep Dutte9089f42015-04-29 05:32:35 -0700301 scif_teardown_ep(ep);
302 scif_add_epd_to_zombie_list(ep, !SCIF_EPLOCK_HELD);
303 return 0;
304}
305EXPORT_SYMBOL_GPL(scif_close);
306
307/**
308 * scif_flush() - Wakes up any blocking accepts. The endpoint will no longer
309 * accept new connections.
310 * @epd: The end point returned from scif_open()
311 */
312int __scif_flush(scif_epd_t epd)
313{
314 struct scif_endpt *ep = (struct scif_endpt *)epd;
315
316 switch (ep->state) {
317 case SCIFEP_LISTENING:
318 {
319 ep->state = SCIFEP_CLLISTEN;
320
321 /* If an accept is waiting wake it up */
322 wake_up_interruptible(&ep->conwq);
323 break;
324 }
325 default:
326 break;
327 }
328 return 0;
329}
330
331int scif_bind(scif_epd_t epd, u16 pn)
332{
333 struct scif_endpt *ep = (struct scif_endpt *)epd;
334 int ret = 0;
335 int tmp;
336
337 dev_dbg(scif_info.mdev.this_device,
338 "SCIFAPI bind: ep %p %s requested port number %d\n",
339 ep, scif_ep_states[ep->state], pn);
340 if (pn) {
341 /*
342 * Similar to IETF RFC 1700, SCIF ports below
343 * SCIF_ADMIN_PORT_END can only be bound by system (or root)
344 * processes or by processes executed by privileged users.
345 */
346 if (pn < SCIF_ADMIN_PORT_END && !capable(CAP_SYS_ADMIN)) {
347 ret = -EACCES;
348 goto scif_bind_admin_exit;
349 }
350 }
351
352 spin_lock(&ep->lock);
353 if (ep->state == SCIFEP_BOUND) {
354 ret = -EINVAL;
355 goto scif_bind_exit;
356 } else if (ep->state != SCIFEP_UNBOUND) {
357 ret = -EISCONN;
358 goto scif_bind_exit;
359 }
360
361 if (pn) {
362 tmp = scif_rsrv_port(pn);
363 if (tmp != pn) {
364 ret = -EINVAL;
365 goto scif_bind_exit;
366 }
367 } else {
368 pn = scif_get_new_port();
369 if (!pn) {
370 ret = -ENOSPC;
371 goto scif_bind_exit;
372 }
373 }
374
375 ep->state = SCIFEP_BOUND;
376 ep->port.node = scif_info.nodeid;
377 ep->port.port = pn;
378 ep->conn_async_state = ASYNC_CONN_IDLE;
379 ret = pn;
380 dev_dbg(scif_info.mdev.this_device,
381 "SCIFAPI bind: bound to port number %d\n", pn);
382scif_bind_exit:
383 spin_unlock(&ep->lock);
384scif_bind_admin_exit:
385 return ret;
386}
387EXPORT_SYMBOL_GPL(scif_bind);
388
389int scif_listen(scif_epd_t epd, int backlog)
390{
391 struct scif_endpt *ep = (struct scif_endpt *)epd;
392
393 dev_dbg(scif_info.mdev.this_device,
394 "SCIFAPI listen: ep %p %s\n", ep, scif_ep_states[ep->state]);
395 spin_lock(&ep->lock);
396 switch (ep->state) {
397 case SCIFEP_ZOMBIE:
398 case SCIFEP_CLOSING:
399 case SCIFEP_CLLISTEN:
400 case SCIFEP_UNBOUND:
401 case SCIFEP_DISCONNECTED:
402 spin_unlock(&ep->lock);
403 return -EINVAL;
404 case SCIFEP_LISTENING:
405 case SCIFEP_CONNECTED:
406 case SCIFEP_CONNECTING:
407 case SCIFEP_MAPPING:
408 spin_unlock(&ep->lock);
409 return -EISCONN;
410 case SCIFEP_BOUND:
411 break;
412 }
413
414 ep->state = SCIFEP_LISTENING;
415 ep->backlog = backlog;
416
417 ep->conreqcnt = 0;
418 ep->acceptcnt = 0;
419 INIT_LIST_HEAD(&ep->conlist);
420 init_waitqueue_head(&ep->conwq);
421 INIT_LIST_HEAD(&ep->li_accept);
422 spin_unlock(&ep->lock);
423
424 /*
425 * Listen status is complete so delete the qp information not needed
426 * on a listen before placing on the list of listening ep's
427 */
428 scif_teardown_ep(ep);
429 ep->qp_info.qp = NULL;
430
431 spin_lock(&scif_info.eplock);
432 list_add_tail(&ep->list, &scif_info.listen);
433 spin_unlock(&scif_info.eplock);
434 return 0;
435}
436EXPORT_SYMBOL_GPL(scif_listen);
Nikhil Rao76371c72015-04-29 05:32:36 -0700437
438/*
439 ************************************************************************
440 * SCIF connection flow:
441 *
442 * 1) A SCIF listening endpoint can call scif_accept(..) to wait for SCIF
443 * connections via a SCIF_CNCT_REQ message
444 * 2) A SCIF endpoint can initiate a SCIF connection by calling
445 * scif_connect(..) which calls scif_setup_qp_connect(..) which
446 * allocates the local qp for the endpoint ring buffer and then sends
447 * a SCIF_CNCT_REQ to the remote node and waits for a SCIF_CNCT_GNT or
448 * a SCIF_CNCT_REJ message
449 * 3) The peer node handles a SCIF_CNCT_REQ via scif_cnctreq_resp(..) which
450 * wakes up any threads blocked in step 1 or sends a SCIF_CNCT_REJ
451 * message otherwise
452 * 4) A thread blocked waiting for incoming connections allocates its local
453 * endpoint QP and ring buffer following which it sends a SCIF_CNCT_GNT
454 * and waits for a SCIF_CNCT_GNT(N)ACK. If the allocation fails then
455 * the node sends a SCIF_CNCT_REJ message
456 * 5) Upon receipt of a SCIF_CNCT_GNT or a SCIF_CNCT_REJ message the
457 * connecting endpoint is woken up as part of handling
458 * scif_cnctgnt_resp(..) following which it maps the remote endpoints'
459 * QP, updates its outbound QP and sends a SCIF_CNCT_GNTACK message on
460 * success or a SCIF_CNCT_GNTNACK message on failure and completes
461 * the scif_connect(..) API
462 * 6) Upon receipt of a SCIF_CNCT_GNT(N)ACK the accepting endpoint blocked
463 * in step 4 is woken up and completes the scif_accept(..) API
464 * 7) The SCIF connection is now established between the two SCIF endpoints.
465 */
466static int scif_conn_func(struct scif_endpt *ep)
467{
468 int err = 0;
469 struct scifmsg msg;
470 struct device *spdev;
471
472 /* Initiate the first part of the endpoint QP setup */
473 err = scif_setup_qp_connect(ep->qp_info.qp, &ep->qp_info.qp_offset,
474 SCIF_ENDPT_QP_SIZE, ep->remote_dev);
475 if (err) {
476 dev_err(&ep->remote_dev->sdev->dev,
477 "%s err %d qp_offset 0x%llx\n",
478 __func__, err, ep->qp_info.qp_offset);
479 ep->state = SCIFEP_BOUND;
480 goto connect_error_simple;
481 }
482
483 spdev = scif_get_peer_dev(ep->remote_dev);
484 if (IS_ERR(spdev)) {
485 err = PTR_ERR(spdev);
486 goto cleanup_qp;
487 }
488 /* Format connect message and send it */
489 msg.src = ep->port;
490 msg.dst = ep->conn_port;
491 msg.uop = SCIF_CNCT_REQ;
492 msg.payload[0] = (u64)ep;
493 msg.payload[1] = ep->qp_info.qp_offset;
494 err = _scif_nodeqp_send(ep->remote_dev, &msg);
495 if (err)
496 goto connect_error_dec;
497 scif_put_peer_dev(spdev);
498 /*
499 * Wait for the remote node to respond with SCIF_CNCT_GNT or
500 * SCIF_CNCT_REJ message.
501 */
502 err = wait_event_timeout(ep->conwq, ep->state != SCIFEP_CONNECTING,
503 SCIF_NODE_ALIVE_TIMEOUT);
504 if (!err) {
505 dev_err(&ep->remote_dev->sdev->dev,
506 "%s %d timeout\n", __func__, __LINE__);
507 ep->state = SCIFEP_BOUND;
508 }
509 spdev = scif_get_peer_dev(ep->remote_dev);
510 if (IS_ERR(spdev)) {
511 err = PTR_ERR(spdev);
512 goto cleanup_qp;
513 }
514 if (ep->state == SCIFEP_MAPPING) {
515 err = scif_setup_qp_connect_response(ep->remote_dev,
516 ep->qp_info.qp,
517 ep->qp_info.gnt_pld);
518 /*
519 * If the resource to map the queue are not available then
520 * we need to tell the other side to terminate the accept
521 */
522 if (err) {
523 dev_err(&ep->remote_dev->sdev->dev,
524 "%s %d err %d\n", __func__, __LINE__, err);
525 msg.uop = SCIF_CNCT_GNTNACK;
526 msg.payload[0] = ep->remote_ep;
527 _scif_nodeqp_send(ep->remote_dev, &msg);
528 ep->state = SCIFEP_BOUND;
529 goto connect_error_dec;
530 }
531
532 msg.uop = SCIF_CNCT_GNTACK;
533 msg.payload[0] = ep->remote_ep;
534 err = _scif_nodeqp_send(ep->remote_dev, &msg);
535 if (err) {
536 ep->state = SCIFEP_BOUND;
537 goto connect_error_dec;
538 }
539 ep->state = SCIFEP_CONNECTED;
540 mutex_lock(&scif_info.connlock);
541 list_add_tail(&ep->list, &scif_info.connected);
542 mutex_unlock(&scif_info.connlock);
543 dev_dbg(&ep->remote_dev->sdev->dev,
544 "SCIFAPI connect: ep %p connected\n", ep);
545 } else if (ep->state == SCIFEP_BOUND) {
546 dev_dbg(&ep->remote_dev->sdev->dev,
547 "SCIFAPI connect: ep %p connection refused\n", ep);
548 err = -ECONNREFUSED;
549 goto connect_error_dec;
550 }
551 scif_put_peer_dev(spdev);
552 return err;
553connect_error_dec:
554 scif_put_peer_dev(spdev);
555cleanup_qp:
556 scif_cleanup_ep_qp(ep);
557connect_error_simple:
558 return err;
559}
560
561/*
562 * scif_conn_handler:
563 *
564 * Workqueue handler for servicing non-blocking SCIF connect
565 *
566 */
567void scif_conn_handler(struct work_struct *work)
568{
569 struct scif_endpt *ep;
570
571 do {
572 ep = NULL;
573 spin_lock(&scif_info.nb_connect_lock);
574 if (!list_empty(&scif_info.nb_connect_list)) {
575 ep = list_first_entry(&scif_info.nb_connect_list,
576 struct scif_endpt, conn_list);
577 list_del(&ep->conn_list);
578 }
579 spin_unlock(&scif_info.nb_connect_lock);
Ashutosh Dixitb7f94442015-09-29 18:10:44 -0700580 if (ep) {
Nikhil Rao76371c72015-04-29 05:32:36 -0700581 ep->conn_err = scif_conn_func(ep);
Ashutosh Dixitb7f94442015-09-29 18:10:44 -0700582 wake_up_interruptible(&ep->conn_pend_wq);
583 }
Nikhil Rao76371c72015-04-29 05:32:36 -0700584 } while (ep);
585}
586
587int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block)
588{
589 struct scif_endpt *ep = (struct scif_endpt *)epd;
590 int err = 0;
591 struct scif_dev *remote_dev;
592 struct device *spdev;
593
594 dev_dbg(scif_info.mdev.this_device, "SCIFAPI connect: ep %p %s\n", ep,
595 scif_ep_states[ep->state]);
596
597 if (!scif_dev || dst->node > scif_info.maxid)
598 return -ENODEV;
599
600 might_sleep();
601
602 remote_dev = &scif_dev[dst->node];
603 spdev = scif_get_peer_dev(remote_dev);
604 if (IS_ERR(spdev)) {
605 err = PTR_ERR(spdev);
606 return err;
607 }
608
609 spin_lock(&ep->lock);
610 switch (ep->state) {
611 case SCIFEP_ZOMBIE:
612 case SCIFEP_CLOSING:
613 err = -EINVAL;
614 break;
615 case SCIFEP_DISCONNECTED:
616 if (ep->conn_async_state == ASYNC_CONN_INPROGRESS)
617 ep->conn_async_state = ASYNC_CONN_FLUSH_WORK;
618 else
619 err = -EINVAL;
620 break;
621 case SCIFEP_LISTENING:
622 case SCIFEP_CLLISTEN:
623 err = -EOPNOTSUPP;
624 break;
625 case SCIFEP_CONNECTING:
626 case SCIFEP_MAPPING:
627 if (ep->conn_async_state == ASYNC_CONN_INPROGRESS)
628 err = -EINPROGRESS;
629 else
630 err = -EISCONN;
631 break;
632 case SCIFEP_CONNECTED:
633 if (ep->conn_async_state == ASYNC_CONN_INPROGRESS)
634 ep->conn_async_state = ASYNC_CONN_FLUSH_WORK;
635 else
636 err = -EISCONN;
637 break;
638 case SCIFEP_UNBOUND:
639 ep->port.port = scif_get_new_port();
640 if (!ep->port.port) {
641 err = -ENOSPC;
642 } else {
643 ep->port.node = scif_info.nodeid;
644 ep->conn_async_state = ASYNC_CONN_IDLE;
645 }
646 /* Fall through */
647 case SCIFEP_BOUND:
648 /*
649 * If a non-blocking connect has been already initiated
650 * (conn_async_state is either ASYNC_CONN_INPROGRESS or
651 * ASYNC_CONN_FLUSH_WORK), the end point could end up in
652 * SCIF_BOUND due an error in the connection process
653 * (e.g., connection refused) If conn_async_state is
654 * ASYNC_CONN_INPROGRESS - transition to ASYNC_CONN_FLUSH_WORK
655 * so that the error status can be collected. If the state is
656 * already ASYNC_CONN_FLUSH_WORK - then set the error to
657 * EINPROGRESS since some other thread is waiting to collect
658 * error status.
659 */
660 if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
661 ep->conn_async_state = ASYNC_CONN_FLUSH_WORK;
662 } else if (ep->conn_async_state == ASYNC_CONN_FLUSH_WORK) {
663 err = -EINPROGRESS;
664 } else {
665 ep->conn_port = *dst;
666 init_waitqueue_head(&ep->sendwq);
667 init_waitqueue_head(&ep->recvwq);
668 init_waitqueue_head(&ep->conwq);
669 ep->conn_async_state = 0;
670
671 if (unlikely(non_block))
672 ep->conn_async_state = ASYNC_CONN_INPROGRESS;
673 }
674 break;
675 }
676
677 if (err || ep->conn_async_state == ASYNC_CONN_FLUSH_WORK)
678 goto connect_simple_unlock1;
679
680 ep->state = SCIFEP_CONNECTING;
681 ep->remote_dev = &scif_dev[dst->node];
682 ep->qp_info.qp->magic = SCIFEP_MAGIC;
683 if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
Ashutosh Dixitb7f94442015-09-29 18:10:44 -0700684 init_waitqueue_head(&ep->conn_pend_wq);
Nikhil Rao76371c72015-04-29 05:32:36 -0700685 spin_lock(&scif_info.nb_connect_lock);
686 list_add_tail(&ep->conn_list, &scif_info.nb_connect_list);
687 spin_unlock(&scif_info.nb_connect_lock);
688 err = -EINPROGRESS;
689 schedule_work(&scif_info.conn_work);
690 }
691connect_simple_unlock1:
692 spin_unlock(&ep->lock);
693 scif_put_peer_dev(spdev);
694 if (err) {
695 return err;
696 } else if (ep->conn_async_state == ASYNC_CONN_FLUSH_WORK) {
697 flush_work(&scif_info.conn_work);
698 err = ep->conn_err;
699 spin_lock(&ep->lock);
700 ep->conn_async_state = ASYNC_CONN_IDLE;
701 spin_unlock(&ep->lock);
702 } else {
703 err = scif_conn_func(ep);
704 }
705 return err;
706}
707
708int scif_connect(scif_epd_t epd, struct scif_port_id *dst)
709{
710 return __scif_connect(epd, dst, false);
711}
712EXPORT_SYMBOL_GPL(scif_connect);
713
714/**
715 * scif_accept() - Accept a connection request from the remote node
716 *
717 * The function accepts a connection request from the remote node. Successful
718 * complete is indicate by a new end point being created and passed back
719 * to the caller for future reference.
720 *
721 * Upon successful complete a zero will be returned and the peer information
722 * will be filled in.
723 *
724 * If the end point is not in the listening state -EINVAL will be returned.
725 *
726 * If during the connection sequence resource allocation fails the -ENOMEM
727 * will be returned.
728 *
729 * If the function is called with the ASYNC flag set and no connection requests
730 * are pending it will return -EAGAIN.
731 *
732 * If the remote side is not sending any connection requests the caller may
733 * terminate this function with a signal. If so a -EINTR will be returned.
734 */
735int scif_accept(scif_epd_t epd, struct scif_port_id *peer,
736 scif_epd_t *newepd, int flags)
737{
738 struct scif_endpt *lep = (struct scif_endpt *)epd;
739 struct scif_endpt *cep;
740 struct scif_conreq *conreq;
741 struct scifmsg msg;
742 int err;
743 struct device *spdev;
744
745 dev_dbg(scif_info.mdev.this_device,
746 "SCIFAPI accept: ep %p %s\n", lep, scif_ep_states[lep->state]);
747
748 if (flags & ~SCIF_ACCEPT_SYNC)
749 return -EINVAL;
750
751 if (!peer || !newepd)
752 return -EINVAL;
753
754 might_sleep();
755 spin_lock(&lep->lock);
756 if (lep->state != SCIFEP_LISTENING) {
757 spin_unlock(&lep->lock);
758 return -EINVAL;
759 }
760
761 if (!lep->conreqcnt && !(flags & SCIF_ACCEPT_SYNC)) {
762 /* No connection request present and we do not want to wait */
763 spin_unlock(&lep->lock);
764 return -EAGAIN;
765 }
766
767 lep->files = current->files;
768retry_connection:
769 spin_unlock(&lep->lock);
770 /* Wait for the remote node to send us a SCIF_CNCT_REQ */
771 err = wait_event_interruptible(lep->conwq,
772 (lep->conreqcnt ||
773 (lep->state != SCIFEP_LISTENING)));
774 if (err)
775 return err;
776
777 if (lep->state != SCIFEP_LISTENING)
778 return -EINTR;
779
780 spin_lock(&lep->lock);
781
782 if (!lep->conreqcnt)
783 goto retry_connection;
784
785 /* Get the first connect request off the list */
786 conreq = list_first_entry(&lep->conlist, struct scif_conreq, list);
787 list_del(&conreq->list);
788 lep->conreqcnt--;
789 spin_unlock(&lep->lock);
790
791 /* Fill in the peer information */
792 peer->node = conreq->msg.src.node;
793 peer->port = conreq->msg.src.port;
794
795 cep = kzalloc(sizeof(*cep), GFP_KERNEL);
796 if (!cep) {
797 err = -ENOMEM;
798 goto scif_accept_error_epalloc;
799 }
800 spin_lock_init(&cep->lock);
801 mutex_init(&cep->sendlock);
802 mutex_init(&cep->recvlock);
803 cep->state = SCIFEP_CONNECTING;
804 cep->remote_dev = &scif_dev[peer->node];
805 cep->remote_ep = conreq->msg.payload[0];
806
807 cep->qp_info.qp = kzalloc(sizeof(*cep->qp_info.qp), GFP_KERNEL);
808 if (!cep->qp_info.qp) {
809 err = -ENOMEM;
810 goto scif_accept_error_qpalloc;
811 }
812
Ashutosh Dixitb7f94442015-09-29 18:10:44 -0700813 err = scif_anon_inode_getfile(cep);
814 if (err)
815 goto scif_accept_error_anon_inode;
816
Nikhil Rao76371c72015-04-29 05:32:36 -0700817 cep->qp_info.qp->magic = SCIFEP_MAGIC;
818 spdev = scif_get_peer_dev(cep->remote_dev);
819 if (IS_ERR(spdev)) {
820 err = PTR_ERR(spdev);
821 goto scif_accept_error_map;
822 }
823 err = scif_setup_qp_accept(cep->qp_info.qp, &cep->qp_info.qp_offset,
824 conreq->msg.payload[1], SCIF_ENDPT_QP_SIZE,
825 cep->remote_dev);
826 if (err) {
827 dev_dbg(&cep->remote_dev->sdev->dev,
828 "SCIFAPI accept: ep %p new %p scif_setup_qp_accept %d qp_offset 0x%llx\n",
829 lep, cep, err, cep->qp_info.qp_offset);
830 scif_put_peer_dev(spdev);
831 goto scif_accept_error_map;
832 }
833
834 cep->port.node = lep->port.node;
835 cep->port.port = lep->port.port;
836 cep->peer.node = peer->node;
837 cep->peer.port = peer->port;
838 init_waitqueue_head(&cep->sendwq);
839 init_waitqueue_head(&cep->recvwq);
840 init_waitqueue_head(&cep->conwq);
841
842 msg.uop = SCIF_CNCT_GNT;
843 msg.src = cep->port;
844 msg.payload[0] = cep->remote_ep;
845 msg.payload[1] = cep->qp_info.qp_offset;
846 msg.payload[2] = (u64)cep;
847
848 err = _scif_nodeqp_send(cep->remote_dev, &msg);
849 scif_put_peer_dev(spdev);
850 if (err)
851 goto scif_accept_error_map;
852retry:
853 /* Wait for the remote node to respond with SCIF_CNCT_GNT(N)ACK */
854 err = wait_event_timeout(cep->conwq, cep->state != SCIFEP_CONNECTING,
855 SCIF_NODE_ACCEPT_TIMEOUT);
856 if (!err && scifdev_alive(cep))
857 goto retry;
858 err = !err ? -ENODEV : 0;
859 if (err)
860 goto scif_accept_error_map;
861 kfree(conreq);
862
863 spin_lock(&cep->lock);
864
865 if (cep->state == SCIFEP_CLOSING) {
866 /*
867 * Remote failed to allocate resources and NAKed the grant.
868 * There is at this point nothing referencing the new end point.
869 */
870 spin_unlock(&cep->lock);
871 scif_teardown_ep(cep);
872 kfree(cep);
873
874 /* If call with sync flag then go back and wait. */
875 if (flags & SCIF_ACCEPT_SYNC) {
876 spin_lock(&lep->lock);
877 goto retry_connection;
878 }
879 return -EAGAIN;
880 }
881
882 scif_get_port(cep->port.port);
883 *newepd = (scif_epd_t)cep;
884 spin_unlock(&cep->lock);
885 return 0;
886scif_accept_error_map:
Ashutosh Dixitb7f94442015-09-29 18:10:44 -0700887 scif_anon_inode_fput(cep);
888scif_accept_error_anon_inode:
Nikhil Rao76371c72015-04-29 05:32:36 -0700889 scif_teardown_ep(cep);
890scif_accept_error_qpalloc:
891 kfree(cep);
892scif_accept_error_epalloc:
893 msg.uop = SCIF_CNCT_REJ;
894 msg.dst.node = conreq->msg.src.node;
895 msg.dst.port = conreq->msg.src.port;
896 msg.payload[0] = conreq->msg.payload[0];
897 msg.payload[1] = conreq->msg.payload[1];
898 scif_nodeqp_send(&scif_dev[conreq->msg.src.node], &msg);
899 kfree(conreq);
900 return err;
901}
902EXPORT_SYMBOL_GPL(scif_accept);
Sudeep Duttfdd9fd52015-04-29 05:32:37 -0700903
904/*
905 * scif_msg_param_check:
906 * @epd: The end point returned from scif_open()
907 * @len: Length to receive
908 * @flags: blocking or non blocking
909 *
910 * Validate parameters for messaging APIs scif_send(..)/scif_recv(..).
911 */
912static inline int scif_msg_param_check(scif_epd_t epd, int len, int flags)
913{
914 int ret = -EINVAL;
915
916 if (len < 0)
917 goto err_ret;
918 if (flags && (!(flags & SCIF_RECV_BLOCK)))
919 goto err_ret;
920 ret = 0;
921err_ret:
922 return ret;
923}
924
925static int _scif_send(scif_epd_t epd, void *msg, int len, int flags)
926{
927 struct scif_endpt *ep = (struct scif_endpt *)epd;
928 struct scifmsg notif_msg;
929 int curr_xfer_len = 0, sent_len = 0, write_count;
930 int ret = 0;
931 struct scif_qp *qp = ep->qp_info.qp;
932
933 if (flags & SCIF_SEND_BLOCK)
934 might_sleep();
935
936 spin_lock(&ep->lock);
937 while (sent_len != len && SCIFEP_CONNECTED == ep->state) {
938 write_count = scif_rb_space(&qp->outbound_q);
939 if (write_count) {
940 /* Best effort to send as much data as possible */
941 curr_xfer_len = min(len - sent_len, write_count);
942 ret = scif_rb_write(&qp->outbound_q, msg,
943 curr_xfer_len);
944 if (ret < 0)
945 break;
946 /* Success. Update write pointer */
947 scif_rb_commit(&qp->outbound_q);
948 /*
949 * Send a notification to the peer about the
950 * produced data message.
951 */
952 notif_msg.src = ep->port;
953 notif_msg.uop = SCIF_CLIENT_SENT;
954 notif_msg.payload[0] = ep->remote_ep;
955 ret = _scif_nodeqp_send(ep->remote_dev, &notif_msg);
956 if (ret)
957 break;
958 sent_len += curr_xfer_len;
959 msg = msg + curr_xfer_len;
960 continue;
961 }
962 curr_xfer_len = min(len - sent_len, SCIF_ENDPT_QP_SIZE - 1);
963 /* Not enough RB space. return for the Non Blocking case */
964 if (!(flags & SCIF_SEND_BLOCK))
965 break;
966
967 spin_unlock(&ep->lock);
968 /* Wait for a SCIF_CLIENT_RCVD message in the Blocking case */
969 ret =
970 wait_event_interruptible(ep->sendwq,
971 (SCIFEP_CONNECTED != ep->state) ||
972 (scif_rb_space(&qp->outbound_q) >=
973 curr_xfer_len));
974 spin_lock(&ep->lock);
975 if (ret)
976 break;
977 }
978 if (sent_len)
979 ret = sent_len;
980 else if (!ret && SCIFEP_CONNECTED != ep->state)
981 ret = SCIFEP_DISCONNECTED == ep->state ?
982 -ECONNRESET : -ENOTCONN;
983 spin_unlock(&ep->lock);
984 return ret;
985}
986
987static int _scif_recv(scif_epd_t epd, void *msg, int len, int flags)
988{
989 int read_size;
990 struct scif_endpt *ep = (struct scif_endpt *)epd;
991 struct scifmsg notif_msg;
992 int curr_recv_len = 0, remaining_len = len, read_count;
993 int ret = 0;
994 struct scif_qp *qp = ep->qp_info.qp;
995
996 if (flags & SCIF_RECV_BLOCK)
997 might_sleep();
998 spin_lock(&ep->lock);
999 while (remaining_len && (SCIFEP_CONNECTED == ep->state ||
1000 SCIFEP_DISCONNECTED == ep->state)) {
1001 read_count = scif_rb_count(&qp->inbound_q, remaining_len);
1002 if (read_count) {
1003 /*
1004 * Best effort to recv as much data as there
1005 * are bytes to read in the RB particularly
1006 * important for the Non Blocking case.
1007 */
1008 curr_recv_len = min(remaining_len, read_count);
1009 read_size = scif_rb_get_next(&qp->inbound_q,
1010 msg, curr_recv_len);
1011 if (ep->state == SCIFEP_CONNECTED) {
1012 /*
1013 * Update the read pointer only if the endpoint
1014 * is still connected else the read pointer
1015 * might no longer exist since the peer has
1016 * freed resources!
1017 */
1018 scif_rb_update_read_ptr(&qp->inbound_q);
1019 /*
1020 * Send a notification to the peer about the
1021 * consumed data message only if the EP is in
1022 * SCIFEP_CONNECTED state.
1023 */
1024 notif_msg.src = ep->port;
1025 notif_msg.uop = SCIF_CLIENT_RCVD;
1026 notif_msg.payload[0] = ep->remote_ep;
1027 ret = _scif_nodeqp_send(ep->remote_dev,
1028 &notif_msg);
1029 if (ret)
1030 break;
1031 }
1032 remaining_len -= curr_recv_len;
1033 msg = msg + curr_recv_len;
1034 continue;
1035 }
1036 /*
1037 * Bail out now if the EP is in SCIFEP_DISCONNECTED state else
1038 * we will keep looping forever.
1039 */
1040 if (ep->state == SCIFEP_DISCONNECTED)
1041 break;
1042 /*
1043 * Return in the Non Blocking case if there is no data
1044 * to read in this iteration.
1045 */
1046 if (!(flags & SCIF_RECV_BLOCK))
1047 break;
1048 curr_recv_len = min(remaining_len, SCIF_ENDPT_QP_SIZE - 1);
1049 spin_unlock(&ep->lock);
1050 /*
1051 * Wait for a SCIF_CLIENT_SEND message in the blocking case
1052 * or until other side disconnects.
1053 */
1054 ret =
1055 wait_event_interruptible(ep->recvwq,
1056 SCIFEP_CONNECTED != ep->state ||
1057 scif_rb_count(&qp->inbound_q,
1058 curr_recv_len)
1059 >= curr_recv_len);
1060 spin_lock(&ep->lock);
1061 if (ret)
1062 break;
1063 }
1064 if (len - remaining_len)
1065 ret = len - remaining_len;
1066 else if (!ret && ep->state != SCIFEP_CONNECTED)
1067 ret = ep->state == SCIFEP_DISCONNECTED ?
1068 -ECONNRESET : -ENOTCONN;
1069 spin_unlock(&ep->lock);
1070 return ret;
1071}
1072
1073/**
1074 * scif_user_send() - Send data to connection queue
1075 * @epd: The end point returned from scif_open()
1076 * @msg: Address to place data
1077 * @len: Length to receive
1078 * @flags: blocking or non blocking
1079 *
1080 * This function is called from the driver IOCTL entry point
1081 * only and is a wrapper for _scif_send().
1082 */
1083int scif_user_send(scif_epd_t epd, void __user *msg, int len, int flags)
1084{
1085 struct scif_endpt *ep = (struct scif_endpt *)epd;
1086 int err = 0;
1087 int sent_len = 0;
1088 char *tmp;
1089 int loop_len;
1090 int chunk_len = min(len, (1 << (MAX_ORDER + PAGE_SHIFT - 1)));
1091
1092 dev_dbg(scif_info.mdev.this_device,
1093 "SCIFAPI send (U): ep %p %s\n", ep, scif_ep_states[ep->state]);
1094 if (!len)
1095 return 0;
1096
1097 err = scif_msg_param_check(epd, len, flags);
1098 if (err)
1099 goto send_err;
1100
1101 tmp = kmalloc(chunk_len, GFP_KERNEL);
1102 if (!tmp) {
1103 err = -ENOMEM;
1104 goto send_err;
1105 }
1106 /*
1107 * Grabbing the lock before breaking up the transfer in
1108 * multiple chunks is required to ensure that messages do
1109 * not get fragmented and reordered.
1110 */
1111 mutex_lock(&ep->sendlock);
1112 while (sent_len != len) {
1113 loop_len = len - sent_len;
1114 loop_len = min(chunk_len, loop_len);
1115 if (copy_from_user(tmp, msg, loop_len)) {
1116 err = -EFAULT;
1117 goto send_free_err;
1118 }
1119 err = _scif_send(epd, tmp, loop_len, flags);
1120 if (err < 0)
1121 goto send_free_err;
1122 sent_len += err;
1123 msg += err;
1124 if (err != loop_len)
1125 goto send_free_err;
1126 }
1127send_free_err:
1128 mutex_unlock(&ep->sendlock);
1129 kfree(tmp);
1130send_err:
1131 return err < 0 ? err : sent_len;
1132}
1133
1134/**
1135 * scif_user_recv() - Receive data from connection queue
1136 * @epd: The end point returned from scif_open()
1137 * @msg: Address to place data
1138 * @len: Length to receive
1139 * @flags: blocking or non blocking
1140 *
1141 * This function is called from the driver IOCTL entry point
1142 * only and is a wrapper for _scif_recv().
1143 */
1144int scif_user_recv(scif_epd_t epd, void __user *msg, int len, int flags)
1145{
1146 struct scif_endpt *ep = (struct scif_endpt *)epd;
1147 int err = 0;
1148 int recv_len = 0;
1149 char *tmp;
1150 int loop_len;
1151 int chunk_len = min(len, (1 << (MAX_ORDER + PAGE_SHIFT - 1)));
1152
1153 dev_dbg(scif_info.mdev.this_device,
1154 "SCIFAPI recv (U): ep %p %s\n", ep, scif_ep_states[ep->state]);
1155 if (!len)
1156 return 0;
1157
1158 err = scif_msg_param_check(epd, len, flags);
1159 if (err)
1160 goto recv_err;
1161
1162 tmp = kmalloc(chunk_len, GFP_KERNEL);
1163 if (!tmp) {
1164 err = -ENOMEM;
1165 goto recv_err;
1166 }
1167 /*
1168 * Grabbing the lock before breaking up the transfer in
1169 * multiple chunks is required to ensure that messages do
1170 * not get fragmented and reordered.
1171 */
1172 mutex_lock(&ep->recvlock);
1173 while (recv_len != len) {
1174 loop_len = len - recv_len;
1175 loop_len = min(chunk_len, loop_len);
1176 err = _scif_recv(epd, tmp, loop_len, flags);
1177 if (err < 0)
1178 goto recv_free_err;
1179 if (copy_to_user(msg, tmp, err)) {
1180 err = -EFAULT;
1181 goto recv_free_err;
1182 }
1183 recv_len += err;
1184 msg += err;
1185 if (err != loop_len)
1186 goto recv_free_err;
1187 }
1188recv_free_err:
1189 mutex_unlock(&ep->recvlock);
1190 kfree(tmp);
1191recv_err:
1192 return err < 0 ? err : recv_len;
1193}
1194
1195/**
1196 * scif_send() - Send data to connection queue
1197 * @epd: The end point returned from scif_open()
1198 * @msg: Address to place data
1199 * @len: Length to receive
1200 * @flags: blocking or non blocking
1201 *
1202 * This function is called from the kernel mode only and is
1203 * a wrapper for _scif_send().
1204 */
1205int scif_send(scif_epd_t epd, void *msg, int len, int flags)
1206{
1207 struct scif_endpt *ep = (struct scif_endpt *)epd;
1208 int ret;
1209
1210 dev_dbg(scif_info.mdev.this_device,
1211 "SCIFAPI send (K): ep %p %s\n", ep, scif_ep_states[ep->state]);
1212 if (!len)
1213 return 0;
1214
1215 ret = scif_msg_param_check(epd, len, flags);
1216 if (ret)
1217 return ret;
1218 if (!ep->remote_dev)
1219 return -ENOTCONN;
1220 /*
1221 * Grab the mutex lock in the blocking case only
1222 * to ensure messages do not get fragmented/reordered.
1223 * The non blocking mode is protected using spin locks
1224 * in _scif_send().
1225 */
1226 if (flags & SCIF_SEND_BLOCK)
1227 mutex_lock(&ep->sendlock);
1228
1229 ret = _scif_send(epd, msg, len, flags);
1230
1231 if (flags & SCIF_SEND_BLOCK)
1232 mutex_unlock(&ep->sendlock);
1233 return ret;
1234}
1235EXPORT_SYMBOL_GPL(scif_send);
1236
1237/**
1238 * scif_recv() - Receive data from connection queue
1239 * @epd: The end point returned from scif_open()
1240 * @msg: Address to place data
1241 * @len: Length to receive
1242 * @flags: blocking or non blocking
1243 *
1244 * This function is called from the kernel mode only and is
1245 * a wrapper for _scif_recv().
1246 */
1247int scif_recv(scif_epd_t epd, void *msg, int len, int flags)
1248{
1249 struct scif_endpt *ep = (struct scif_endpt *)epd;
1250 int ret;
1251
1252 dev_dbg(scif_info.mdev.this_device,
1253 "SCIFAPI recv (K): ep %p %s\n", ep, scif_ep_states[ep->state]);
1254 if (!len)
1255 return 0;
1256
1257 ret = scif_msg_param_check(epd, len, flags);
1258 if (ret)
1259 return ret;
1260 /*
1261 * Grab the mutex lock in the blocking case only
1262 * to ensure messages do not get fragmented/reordered.
1263 * The non blocking mode is protected using spin locks
1264 * in _scif_send().
1265 */
1266 if (flags & SCIF_RECV_BLOCK)
1267 mutex_lock(&ep->recvlock);
1268
1269 ret = _scif_recv(epd, msg, len, flags);
1270
1271 if (flags & SCIF_RECV_BLOCK)
1272 mutex_unlock(&ep->recvlock);
1273
1274 return ret;
1275}
1276EXPORT_SYMBOL_GPL(scif_recv);
1277
Ashutosh Dixitb7f94442015-09-29 18:10:44 -07001278static inline void _scif_poll_wait(struct file *f, wait_queue_head_t *wq,
1279 poll_table *p, struct scif_endpt *ep)
1280{
1281 /*
1282 * Because poll_wait makes a GFP_KERNEL allocation, give up the lock
1283 * and regrab it afterwards. Because the endpoint state might have
1284 * changed while the lock was given up, the state must be checked
1285 * again after re-acquiring the lock. The code in __scif_pollfd(..)
1286 * does this.
1287 */
1288 spin_unlock(&ep->lock);
1289 poll_wait(f, wq, p);
1290 spin_lock(&ep->lock);
1291}
1292
1293unsigned int
1294__scif_pollfd(struct file *f, poll_table *wait, struct scif_endpt *ep)
1295{
1296 unsigned int mask = 0;
1297
1298 dev_dbg(scif_info.mdev.this_device,
1299 "SCIFAPI pollfd: ep %p %s\n", ep, scif_ep_states[ep->state]);
1300
1301 spin_lock(&ep->lock);
1302
1303 /* Endpoint is waiting for a non-blocking connect to complete */
1304 if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
1305 _scif_poll_wait(f, &ep->conn_pend_wq, wait, ep);
1306 if (ep->conn_async_state == ASYNC_CONN_INPROGRESS) {
1307 if (ep->state == SCIFEP_CONNECTED ||
1308 ep->state == SCIFEP_DISCONNECTED ||
1309 ep->conn_err)
1310 mask |= POLLOUT;
1311 goto exit;
1312 }
1313 }
1314
1315 /* Endpoint is listening for incoming connection requests */
1316 if (ep->state == SCIFEP_LISTENING) {
1317 _scif_poll_wait(f, &ep->conwq, wait, ep);
1318 if (ep->state == SCIFEP_LISTENING) {
1319 if (ep->conreqcnt)
1320 mask |= POLLIN;
1321 goto exit;
1322 }
1323 }
1324
1325 /* Endpoint is connected or disconnected */
1326 if (ep->state == SCIFEP_CONNECTED || ep->state == SCIFEP_DISCONNECTED) {
1327 if (poll_requested_events(wait) & POLLIN)
1328 _scif_poll_wait(f, &ep->recvwq, wait, ep);
1329 if (poll_requested_events(wait) & POLLOUT)
1330 _scif_poll_wait(f, &ep->sendwq, wait, ep);
1331 if (ep->state == SCIFEP_CONNECTED ||
1332 ep->state == SCIFEP_DISCONNECTED) {
1333 /* Data can be read without blocking */
1334 if (scif_rb_count(&ep->qp_info.qp->inbound_q, 1))
1335 mask |= POLLIN;
1336 /* Data can be written without blocking */
1337 if (scif_rb_space(&ep->qp_info.qp->outbound_q))
1338 mask |= POLLOUT;
1339 /* Return POLLHUP if endpoint is disconnected */
1340 if (ep->state == SCIFEP_DISCONNECTED)
1341 mask |= POLLHUP;
1342 goto exit;
1343 }
1344 }
1345
1346 /* Return POLLERR if the endpoint is in none of the above states */
1347 mask |= POLLERR;
1348exit:
1349 spin_unlock(&ep->lock);
1350 return mask;
1351}
1352
1353/**
1354 * scif_poll() - Kernel mode SCIF poll
1355 * @ufds: Array of scif_pollepd structures containing the end points
1356 * and events to poll on
1357 * @nfds: Size of the ufds array
1358 * @timeout_msecs: Timeout in msecs, -ve implies infinite timeout
1359 *
1360 * The code flow in this function is based on do_poll(..) in select.c
1361 *
1362 * Returns the number of endpoints which have pending events or 0 in
1363 * the event of a timeout. If a signal is used for wake up, -EINTR is
1364 * returned.
1365 */
1366int
1367scif_poll(struct scif_pollepd *ufds, unsigned int nfds, long timeout_msecs)
1368{
1369 struct poll_wqueues table;
1370 poll_table *pt;
1371 int i, mask, count = 0, timed_out = timeout_msecs == 0;
1372 u64 timeout = timeout_msecs < 0 ? MAX_SCHEDULE_TIMEOUT
1373 : msecs_to_jiffies(timeout_msecs);
1374
1375 poll_initwait(&table);
1376 pt = &table.pt;
1377 while (1) {
1378 for (i = 0; i < nfds; i++) {
1379 pt->_key = ufds[i].events | POLLERR | POLLHUP;
1380 mask = __scif_pollfd(ufds[i].epd->anon,
1381 pt, ufds[i].epd);
1382 mask &= ufds[i].events | POLLERR | POLLHUP;
1383 if (mask) {
1384 count++;
1385 pt->_qproc = NULL;
1386 }
1387 ufds[i].revents = mask;
1388 }
1389 pt->_qproc = NULL;
1390 if (!count) {
1391 count = table.error;
1392 if (signal_pending(current))
1393 count = -EINTR;
1394 }
1395 if (count || timed_out)
1396 break;
1397
1398 if (!schedule_timeout_interruptible(timeout))
1399 timed_out = 1;
1400 }
1401 poll_freewait(&table);
1402 return count;
1403}
1404EXPORT_SYMBOL_GPL(scif_poll);
1405
Sudeep Duttfdd9fd52015-04-29 05:32:37 -07001406int scif_get_node_ids(u16 *nodes, int len, u16 *self)
1407{
1408 int online = 0;
1409 int offset = 0;
1410 int node;
1411
1412 if (!scif_is_mgmt_node())
1413 scif_get_node_info();
1414
1415 *self = scif_info.nodeid;
1416 mutex_lock(&scif_info.conflock);
1417 len = min_t(int, len, scif_info.total);
1418 for (node = 0; node <= scif_info.maxid; node++) {
1419 if (_scifdev_alive(&scif_dev[node])) {
1420 online++;
1421 if (offset < len)
1422 nodes[offset++] = node;
1423 }
1424 }
1425 dev_dbg(scif_info.mdev.this_device,
1426 "SCIFAPI get_node_ids total %d online %d filled in %d nodes\n",
1427 scif_info.total, online, offset);
1428 mutex_unlock(&scif_info.conflock);
1429
1430 return online;
1431}
1432EXPORT_SYMBOL_GPL(scif_get_node_ids);
Ashutosh Dixitd3d912e2015-09-29 18:11:15 -07001433
1434static int scif_add_client_dev(struct device *dev, struct subsys_interface *si)
1435{
1436 struct scif_client *client =
1437 container_of(si, struct scif_client, si);
1438 struct scif_peer_dev *spdev =
1439 container_of(dev, struct scif_peer_dev, dev);
1440
1441 if (client->probe)
1442 client->probe(spdev);
1443 return 0;
1444}
1445
1446static void scif_remove_client_dev(struct device *dev,
1447 struct subsys_interface *si)
1448{
1449 struct scif_client *client =
1450 container_of(si, struct scif_client, si);
1451 struct scif_peer_dev *spdev =
1452 container_of(dev, struct scif_peer_dev, dev);
1453
1454 if (client->remove)
1455 client->remove(spdev);
1456}
1457
1458void scif_client_unregister(struct scif_client *client)
1459{
1460 subsys_interface_unregister(&client->si);
1461}
1462EXPORT_SYMBOL_GPL(scif_client_unregister);
1463
1464int scif_client_register(struct scif_client *client)
1465{
1466 struct subsys_interface *si = &client->si;
1467
1468 si->name = client->name;
1469 si->subsys = &scif_peer_bus;
1470 si->add_dev = scif_add_client_dev;
1471 si->remove_dev = scif_remove_client_dev;
1472
1473 return subsys_interface_register(&client->si);
1474}
1475EXPORT_SYMBOL_GPL(scif_client_register);