blob: 7180d566c74b998c7dcdb4c03b399bad703c060a [file] [log] [blame]
Sudeep Dutt40cb5942015-04-29 05:32:34 -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 "../bus/scif_bus.h"
19#include "scif_peer_bus.h"
20#include "scif_main.h"
21#include "scif_nodeqp.h"
22#include "scif_map.h"
23
24/*
25 ************************************************************************
26 * SCIF node Queue Pair (QP) setup flow:
27 *
28 * 1) SCIF driver gets probed with a scif_hw_dev via the scif_hw_bus
29 * 2) scif_setup_qp(..) allocates the local qp and calls
30 * scif_setup_qp_connect(..) which allocates and maps the local
31 * buffer for the inbound QP
32 * 3) The local node updates the device page with the DMA address of the QP
33 * 4) A delayed work is scheduled (qp_dwork) which periodically reads if
34 * the peer node has updated its QP DMA address
35 * 5) Once a valid non zero address is found in the QP DMA address field
36 * in the device page, the local node maps the remote node's QP,
37 * updates its outbound QP and sends a SCIF_INIT message to the peer
38 * 6) The SCIF_INIT message is received by the peer node QP interrupt bottom
39 * half handler by calling scif_init(..)
40 * 7) scif_init(..) registers a new SCIF peer node by calling
41 * scif_peer_register_device(..) which signifies the addition of a new
42 * SCIF node
43 * 8) On the mgmt node, P2P network setup/teardown is initiated if all the
44 * remote nodes are online via scif_p2p_setup(..)
45 * 9) For P2P setup, the host maps the remote nodes' aperture and memory
46 * bars and sends a SCIF_NODE_ADD message to both nodes
47 * 10) As part of scif_nodeadd, both nodes set up their local inbound
48 * QPs and send a SCIF_NODE_ADD_ACK to the mgmt node
49 * 11) As part of scif_node_add_ack(..) the mgmt node forwards the
50 * SCIF_NODE_ADD_ACK to the remote nodes
51 * 12) As part of scif_node_add_ack(..) the remote nodes update their
52 * outbound QPs, make sure they can access memory on the remote node
53 * and then add a new SCIF peer node by calling
54 * scif_peer_register_device(..) which signifies the addition of a new
55 * SCIF node.
56 * 13) The SCIF network is now established across all nodes.
57 *
58 ************************************************************************
59 * SCIF node QP teardown flow (initiated by non mgmt node):
60 *
61 * 1) SCIF driver gets a remove callback with a scif_hw_dev via the scif_hw_bus
62 * 2) The device page QP DMA address field is updated with 0x0
63 * 3) A non mgmt node now cleans up all local data structures and sends a
64 * SCIF_EXIT message to the peer and waits for a SCIF_EXIT_ACK
65 * 4) As part of scif_exit(..) handling scif_disconnect_node(..) is called
66 * 5) scif_disconnect_node(..) sends a SCIF_NODE_REMOVE message to all the
67 * peers and waits for a SCIF_NODE_REMOVE_ACK
68 * 6) As part of scif_node_remove(..) a remote node unregisters the peer
69 * node from the SCIF network and sends a SCIF_NODE_REMOVE_ACK
70 * 7) When the mgmt node has received all the SCIF_NODE_REMOVE_ACKs
71 * it sends itself a node remove message whose handling cleans up local
72 * data structures and unregisters the peer node from the SCIF network
73 * 8) The mgmt node sends a SCIF_EXIT_ACK
74 * 9) Upon receipt of the SCIF_EXIT_ACK the node initiating the teardown
75 * completes the SCIF remove routine
76 * 10) The SCIF network is now torn down for the node initiating the
77 * teardown sequence
78 *
79 ************************************************************************
80 * SCIF node QP teardown flow (initiated by mgmt node):
81 *
82 * 1) SCIF driver gets a remove callback with a scif_hw_dev via the scif_hw_bus
83 * 2) The device page QP DMA address field is updated with 0x0
84 * 3) The mgmt node calls scif_disconnect_node(..)
85 * 4) scif_disconnect_node(..) sends a SCIF_NODE_REMOVE message to all the peers
86 * and waits for a SCIF_NODE_REMOVE_ACK
87 * 5) As part of scif_node_remove(..) a remote node unregisters the peer
88 * node from the SCIF network and sends a SCIF_NODE_REMOVE_ACK
89 * 6) When the mgmt node has received all the SCIF_NODE_REMOVE_ACKs
90 * it unregisters the peer node from the SCIF network
91 * 7) The mgmt node sends a SCIF_EXIT message and waits for a SCIF_EXIT_ACK.
92 * 8) A non mgmt node upon receipt of a SCIF_EXIT message calls scif_stop(..)
93 * which would clean up local data structures for all SCIF nodes and
94 * then send a SCIF_EXIT_ACK back to the mgmt node
95 * 9) Upon receipt of the SCIF_EXIT_ACK the the mgmt node sends itself a node
96 * remove message whose handling cleans up local data structures and
97 * destroys any P2P mappings.
98 * 10) The SCIF hardware device for which a remove callback was received is now
99 * disconnected from the SCIF network.
100 */
101/*
102 * Initializes "local" data structures for the QP. Allocates the QP
103 * ring buffer (rb) and initializes the "in bound" queue.
104 */
105int scif_setup_qp_connect(struct scif_qp *qp, dma_addr_t *qp_offset,
106 int local_size, struct scif_dev *scifdev)
107{
Sudeep Duttd1824322015-09-29 18:16:25 -0700108 void *local_q = qp->inbound_q.rb_base;
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700109 int err = 0;
110 u32 tmp_rd = 0;
111
112 spin_lock_init(&qp->send_lock);
113 spin_lock_init(&qp->recv_lock);
114
Sudeep Duttd1824322015-09-29 18:16:25 -0700115 /* Allocate rb only if not already allocated */
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700116 if (!local_q) {
Sudeep Duttd1824322015-09-29 18:16:25 -0700117 local_q = kzalloc(local_size, GFP_KERNEL);
118 if (!local_q) {
119 err = -ENOMEM;
120 return err;
121 }
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700122 }
Sudeep Duttd1824322015-09-29 18:16:25 -0700123
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700124 err = scif_map_single(&qp->local_buf, local_q, scifdev, local_size);
125 if (err)
126 goto kfree;
127 /*
128 * To setup the inbound_q, the buffer lives locally, the read pointer
129 * is remote and the write pointer is local.
130 */
131 scif_rb_init(&qp->inbound_q,
132 &tmp_rd,
133 &qp->local_write,
134 local_q, get_count_order(local_size));
135 /*
136 * The read pointer is NULL initially and it is unsafe to use the ring
137 * buffer til this changes!
138 */
139 qp->inbound_q.read_ptr = NULL;
140 err = scif_map_single(qp_offset, qp,
141 scifdev, sizeof(struct scif_qp));
142 if (err)
143 goto unmap;
144 qp->local_qp = *qp_offset;
145 return err;
146unmap:
147 scif_unmap_single(qp->local_buf, scifdev, local_size);
148 qp->local_buf = 0;
149kfree:
150 kfree(local_q);
151 return err;
152}
153
154/* When the other side has already done it's allocation, this is called */
155int scif_setup_qp_accept(struct scif_qp *qp, dma_addr_t *qp_offset,
156 dma_addr_t phys, int local_size,
157 struct scif_dev *scifdev)
158{
159 void *local_q;
160 void *remote_q;
161 struct scif_qp *remote_qp;
162 int remote_size;
163 int err = 0;
164
165 spin_lock_init(&qp->send_lock);
166 spin_lock_init(&qp->recv_lock);
167 /* Start by figuring out where we need to point */
168 remote_qp = scif_ioremap(phys, sizeof(struct scif_qp), scifdev);
169 if (!remote_qp)
170 return -EIO;
171 qp->remote_qp = remote_qp;
172 if (qp->remote_qp->magic != SCIFEP_MAGIC) {
173 err = -EIO;
174 goto iounmap;
175 }
176 qp->remote_buf = remote_qp->local_buf;
177 remote_size = qp->remote_qp->inbound_q.size;
178 remote_q = scif_ioremap(qp->remote_buf, remote_size, scifdev);
179 if (!remote_q) {
180 err = -EIO;
181 goto iounmap;
182 }
183 qp->remote_qp->local_write = 0;
184 /*
185 * To setup the outbound_q, the buffer lives in remote memory,
186 * the read pointer is local, the write pointer is remote
187 */
188 scif_rb_init(&qp->outbound_q,
189 &qp->local_read,
190 &qp->remote_qp->local_write,
191 remote_q,
192 get_count_order(remote_size));
193 local_q = kzalloc(local_size, GFP_KERNEL);
194 if (!local_q) {
195 err = -ENOMEM;
196 goto iounmap_1;
197 }
198 err = scif_map_single(&qp->local_buf, local_q, scifdev, local_size);
199 if (err)
200 goto kfree;
201 qp->remote_qp->local_read = 0;
202 /*
203 * To setup the inbound_q, the buffer lives locally, the read pointer
204 * is remote and the write pointer is local
205 */
206 scif_rb_init(&qp->inbound_q,
207 &qp->remote_qp->local_read,
208 &qp->local_write,
209 local_q, get_count_order(local_size));
210 err = scif_map_single(qp_offset, qp, scifdev,
211 sizeof(struct scif_qp));
212 if (err)
213 goto unmap;
214 qp->local_qp = *qp_offset;
215 return err;
216unmap:
217 scif_unmap_single(qp->local_buf, scifdev, local_size);
218 qp->local_buf = 0;
219kfree:
220 kfree(local_q);
221iounmap_1:
222 scif_iounmap(remote_q, remote_size, scifdev);
223 qp->outbound_q.rb_base = NULL;
224iounmap:
225 scif_iounmap(qp->remote_qp, sizeof(struct scif_qp), scifdev);
226 qp->remote_qp = NULL;
227 return err;
228}
229
230int scif_setup_qp_connect_response(struct scif_dev *scifdev,
231 struct scif_qp *qp, u64 payload)
232{
233 int err = 0;
234 void *r_buf;
235 int remote_size;
236 phys_addr_t tmp_phys;
237
238 qp->remote_qp = scif_ioremap(payload, sizeof(struct scif_qp), scifdev);
239
240 if (!qp->remote_qp) {
241 err = -ENOMEM;
242 goto error;
243 }
244
245 if (qp->remote_qp->magic != SCIFEP_MAGIC) {
246 dev_err(&scifdev->sdev->dev,
247 "SCIFEP_MAGIC mismatch between self %d remote %d\n",
248 scif_dev[scif_info.nodeid].node, scifdev->node);
249 err = -ENODEV;
250 goto error;
251 }
252
253 tmp_phys = qp->remote_qp->local_buf;
254 remote_size = qp->remote_qp->inbound_q.size;
255 r_buf = scif_ioremap(tmp_phys, remote_size, scifdev);
256
257 if (!r_buf)
258 return -EIO;
259
260 qp->local_read = 0;
261 scif_rb_init(&qp->outbound_q,
262 &qp->local_read,
263 &qp->remote_qp->local_write,
264 r_buf,
265 get_count_order(remote_size));
266 /*
Ashutosh Dixitd3d912e2015-09-29 18:11:15 -0700267 * Because the node QP may already be processing an INIT message, set
268 * the read pointer so the cached read offset isn't lost
269 */
270 qp->remote_qp->local_read = qp->inbound_q.current_read_offset;
271 /*
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700272 * resetup the inbound_q now that we know where the
273 * inbound_read really is.
274 */
275 scif_rb_init(&qp->inbound_q,
276 &qp->remote_qp->local_read,
277 &qp->local_write,
278 qp->inbound_q.rb_base,
279 get_count_order(qp->inbound_q.size));
280error:
281 return err;
282}
283
284static __always_inline void
285scif_send_msg_intr(struct scif_dev *scifdev)
286{
287 struct scif_hw_dev *sdev = scifdev->sdev;
288
289 if (scifdev_is_p2p(scifdev))
290 sdev->hw_ops->send_p2p_intr(sdev, scifdev->rdb, &scifdev->mmio);
291 else
292 sdev->hw_ops->send_intr(sdev, scifdev->rdb);
293}
294
295int scif_qp_response(phys_addr_t phys, struct scif_dev *scifdev)
296{
297 int err = 0;
298 struct scifmsg msg;
299
300 err = scif_setup_qp_connect_response(scifdev, scifdev->qpairs, phys);
301 if (!err) {
302 /*
303 * Now that everything is setup and mapped, we're ready
304 * to tell the peer about our queue's location
305 */
306 msg.uop = SCIF_INIT;
307 msg.dst.node = scifdev->node;
308 err = scif_nodeqp_send(scifdev, &msg);
309 }
310 return err;
311}
312
313void scif_send_exit(struct scif_dev *scifdev)
314{
315 struct scifmsg msg;
316 int ret;
317
318 scifdev->exit = OP_IN_PROGRESS;
319 msg.uop = SCIF_EXIT;
320 msg.src.node = scif_info.nodeid;
321 msg.dst.node = scifdev->node;
322 ret = scif_nodeqp_send(scifdev, &msg);
323 if (ret)
324 goto done;
325 /* Wait for a SCIF_EXIT_ACK message */
326 wait_event_timeout(scif_info.exitwq, scifdev->exit == OP_COMPLETED,
327 SCIF_NODE_ALIVE_TIMEOUT);
328done:
329 scifdev->exit = OP_IDLE;
330}
331
332int scif_setup_qp(struct scif_dev *scifdev)
333{
334 int err = 0;
335 int local_size;
336 struct scif_qp *qp;
337
338 local_size = SCIF_NODE_QP_SIZE;
339
340 qp = kzalloc(sizeof(*qp), GFP_KERNEL);
341 if (!qp) {
342 err = -ENOMEM;
343 return err;
344 }
345 qp->magic = SCIFEP_MAGIC;
346 scifdev->qpairs = qp;
347 err = scif_setup_qp_connect(qp, &scifdev->qp_dma_addr,
348 local_size, scifdev);
349 if (err)
350 goto free_qp;
351 /*
352 * We're as setup as we can be. The inbound_q is setup, w/o a usable
353 * outbound q. When we get a message, the read_ptr will be updated,
354 * and we will pull the message.
355 */
356 return err;
357free_qp:
358 kfree(scifdev->qpairs);
359 scifdev->qpairs = NULL;
360 return err;
361}
362
363static void scif_p2p_freesg(struct scatterlist *sg)
364{
365 kfree(sg);
366}
367
368static struct scatterlist *
Sudeep Dutta6344432015-07-22 11:50:10 -0700369scif_p2p_setsg(phys_addr_t pa, int page_size, int page_cnt)
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700370{
371 struct scatterlist *sg;
372 struct page *page;
373 int i;
374
375 sg = kcalloc(page_cnt, sizeof(struct scatterlist), GFP_KERNEL);
376 if (!sg)
377 return NULL;
378 sg_init_table(sg, page_cnt);
379 for (i = 0; i < page_cnt; i++) {
Sudeep Dutta6344432015-07-22 11:50:10 -0700380 page = pfn_to_page(pa >> PAGE_SHIFT);
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700381 sg_set_page(&sg[i], page, page_size, 0);
Sudeep Dutta6344432015-07-22 11:50:10 -0700382 pa += page_size;
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700383 }
384 return sg;
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700385}
386
387/* Init p2p mappings required to access peerdev from scifdev */
388static struct scif_p2p_info *
389scif_init_p2p_info(struct scif_dev *scifdev, struct scif_dev *peerdev)
390{
391 struct scif_p2p_info *p2p;
392 int num_mmio_pages, num_aper_pages, sg_page_shift, err, num_aper_chunks;
393 struct scif_hw_dev *psdev = peerdev->sdev;
394 struct scif_hw_dev *sdev = scifdev->sdev;
395
396 num_mmio_pages = psdev->mmio->len >> PAGE_SHIFT;
397 num_aper_pages = psdev->aper->len >> PAGE_SHIFT;
398
399 p2p = kzalloc(sizeof(*p2p), GFP_KERNEL);
400 if (!p2p)
401 return NULL;
Sudeep Dutta6344432015-07-22 11:50:10 -0700402 p2p->ppi_sg[SCIF_PPI_MMIO] = scif_p2p_setsg(psdev->mmio->pa,
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700403 PAGE_SIZE, num_mmio_pages);
404 if (!p2p->ppi_sg[SCIF_PPI_MMIO])
405 goto free_p2p;
406 p2p->sg_nentries[SCIF_PPI_MMIO] = num_mmio_pages;
407 sg_page_shift = get_order(min(psdev->aper->len, (u64)(1 << 30)));
408 num_aper_chunks = num_aper_pages >> (sg_page_shift - PAGE_SHIFT);
Sudeep Dutta6344432015-07-22 11:50:10 -0700409 p2p->ppi_sg[SCIF_PPI_APER] = scif_p2p_setsg(psdev->aper->pa,
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700410 1 << sg_page_shift,
411 num_aper_chunks);
412 p2p->sg_nentries[SCIF_PPI_APER] = num_aper_chunks;
413 err = dma_map_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_MMIO],
414 num_mmio_pages, PCI_DMA_BIDIRECTIONAL);
415 if (err != num_mmio_pages)
416 goto scif_p2p_free;
417 err = dma_map_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_APER],
418 num_aper_chunks, PCI_DMA_BIDIRECTIONAL);
419 if (err != num_aper_chunks)
420 goto dma_unmap;
421 p2p->ppi_da[SCIF_PPI_MMIO] = sg_dma_address(p2p->ppi_sg[SCIF_PPI_MMIO]);
422 p2p->ppi_da[SCIF_PPI_APER] = sg_dma_address(p2p->ppi_sg[SCIF_PPI_APER]);
423 p2p->ppi_len[SCIF_PPI_MMIO] = num_mmio_pages;
424 p2p->ppi_len[SCIF_PPI_APER] = num_aper_pages;
425 p2p->ppi_peer_id = peerdev->node;
426 return p2p;
427dma_unmap:
428 dma_unmap_sg(&sdev->dev, p2p->ppi_sg[SCIF_PPI_MMIO],
429 p2p->sg_nentries[SCIF_PPI_MMIO], DMA_BIDIRECTIONAL);
430scif_p2p_free:
431 scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_MMIO]);
432 scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_APER]);
433free_p2p:
434 kfree(p2p);
435 return NULL;
436}
437
438/**
439 * scif_node_connect: Respond to SCIF_NODE_CONNECT interrupt message
440 * @dst: Destination node
441 *
442 * Connect the src and dst node by setting up the p2p connection
443 * between them. Management node here acts like a proxy.
444 */
445static void scif_node_connect(struct scif_dev *scifdev, int dst)
446{
447 struct scif_dev *dev_j = scifdev;
448 struct scif_dev *dev_i = NULL;
449 struct scif_p2p_info *p2p_ij = NULL; /* bus addr for j from i */
450 struct scif_p2p_info *p2p_ji = NULL; /* bus addr for i from j */
451 struct scif_p2p_info *p2p;
452 struct list_head *pos, *tmp;
453 struct scifmsg msg;
454 int err;
455 u64 tmppayload;
456
457 if (dst < 1 || dst > scif_info.maxid)
458 return;
459
460 dev_i = &scif_dev[dst];
461
462 if (!_scifdev_alive(dev_i))
463 return;
464 /*
465 * If the p2p connection is already setup or in the process of setting
466 * up then just ignore this request. The requested node will get
467 * informed by SCIF_NODE_ADD_ACK or SCIF_NODE_ADD_NACK
468 */
469 if (!list_empty(&dev_i->p2p)) {
470 list_for_each_safe(pos, tmp, &dev_i->p2p) {
471 p2p = list_entry(pos, struct scif_p2p_info, ppi_list);
472 if (p2p->ppi_peer_id == dev_j->node)
473 return;
474 }
475 }
476 p2p_ij = scif_init_p2p_info(dev_i, dev_j);
477 if (!p2p_ij)
478 return;
479 p2p_ji = scif_init_p2p_info(dev_j, dev_i);
480 if (!p2p_ji)
481 return;
482 list_add_tail(&p2p_ij->ppi_list, &dev_i->p2p);
483 list_add_tail(&p2p_ji->ppi_list, &dev_j->p2p);
484
485 /*
486 * Send a SCIF_NODE_ADD to dev_i, pass it its bus address
487 * as seen from dev_j
488 */
489 msg.uop = SCIF_NODE_ADD;
490 msg.src.node = dev_j->node;
491 msg.dst.node = dev_i->node;
492
493 msg.payload[0] = p2p_ji->ppi_da[SCIF_PPI_APER];
494 msg.payload[1] = p2p_ij->ppi_da[SCIF_PPI_MMIO];
495 msg.payload[2] = p2p_ij->ppi_da[SCIF_PPI_APER];
496 msg.payload[3] = p2p_ij->ppi_len[SCIF_PPI_APER] << PAGE_SHIFT;
497
498 err = scif_nodeqp_send(dev_i, &msg);
499 if (err) {
500 dev_err(&scifdev->sdev->dev,
501 "%s %d error %d\n", __func__, __LINE__, err);
502 return;
503 }
504
505 /* Same as above but to dev_j */
506 msg.uop = SCIF_NODE_ADD;
507 msg.src.node = dev_i->node;
508 msg.dst.node = dev_j->node;
509
510 tmppayload = msg.payload[0];
511 msg.payload[0] = msg.payload[2];
512 msg.payload[2] = tmppayload;
513 msg.payload[1] = p2p_ji->ppi_da[SCIF_PPI_MMIO];
514 msg.payload[3] = p2p_ji->ppi_len[SCIF_PPI_APER] << PAGE_SHIFT;
515
516 scif_nodeqp_send(dev_j, &msg);
517}
518
519static void scif_p2p_setup(void)
520{
521 int i, j;
522
523 if (!scif_info.p2p_enable)
524 return;
525
526 for (i = 1; i <= scif_info.maxid; i++)
527 if (!_scifdev_alive(&scif_dev[i]))
528 return;
529
530 for (i = 1; i <= scif_info.maxid; i++) {
531 for (j = 1; j <= scif_info.maxid; j++) {
532 struct scif_dev *scifdev = &scif_dev[i];
533
534 if (i == j)
535 continue;
536 scif_node_connect(scifdev, j);
537 }
538 }
539}
540
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700541static char *message_types[] = {"BAD",
542 "INIT",
543 "EXIT",
544 "SCIF_EXIT_ACK",
545 "SCIF_NODE_ADD",
546 "SCIF_NODE_ADD_ACK",
547 "SCIF_NODE_ADD_NACK",
548 "REMOVE_NODE",
Nikhil Rao76371c72015-04-29 05:32:36 -0700549 "REMOVE_NODE_ACK",
550 "CNCT_REQ",
551 "CNCT_GNT",
552 "CNCT_GNTACK",
553 "CNCT_GNTNACK",
554 "CNCT_REJ",
555 "DISCNCT",
Sudeep Duttfdd9fd52015-04-29 05:32:37 -0700556 "DISCNT_ACK",
557 "CLIENT_SENT",
558 "CLIENT_RCVD",
Sudeep Duttd1824322015-09-29 18:16:25 -0700559 "SCIF_GET_NODE_INFO",
560 "REGISTER",
561 "REGISTER_ACK",
562 "REGISTER_NACK",
563 "UNREGISTER",
564 "UNREGISTER_ACK",
565 "UNREGISTER_NACK",
566 "ALLOC_REQ",
567 "ALLOC_GNT",
568 "ALLOC_REJ",
569 "FREE_PHYS",
570 "FREE_VIRT",
571 "MUNMAP",
572 "MARK",
573 "MARK_ACK",
574 "MARK_NACK",
575 "WAIT",
576 "WAIT_ACK",
577 "WAIT_NACK",
578 "SIGNAL_LOCAL",
579 "SIGNAL_REMOTE",
580 "SIG_ACK",
581 "SIG_NACK"};
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700582
583static void
584scif_display_message(struct scif_dev *scifdev, struct scifmsg *msg,
585 const char *label)
586{
587 if (!scif_info.en_msg_log)
588 return;
589 if (msg->uop > SCIF_MAX_MSG) {
590 dev_err(&scifdev->sdev->dev,
591 "%s: unknown msg type %d\n", label, msg->uop);
592 return;
593 }
594 dev_info(&scifdev->sdev->dev,
595 "%s: msg type %s, src %d:%d, dest %d:%d payload 0x%llx:0x%llx:0x%llx:0x%llx\n",
596 label, message_types[msg->uop], msg->src.node, msg->src.port,
597 msg->dst.node, msg->dst.port, msg->payload[0], msg->payload[1],
598 msg->payload[2], msg->payload[3]);
599}
600
601int _scif_nodeqp_send(struct scif_dev *scifdev, struct scifmsg *msg)
602{
603 struct scif_qp *qp = scifdev->qpairs;
604 int err = -ENOMEM, loop_cnt = 0;
605
606 scif_display_message(scifdev, msg, "Sent");
607 if (!qp) {
608 err = -EINVAL;
609 goto error;
610 }
611 spin_lock(&qp->send_lock);
612
613 while ((err = scif_rb_write(&qp->outbound_q,
614 msg, sizeof(struct scifmsg)))) {
615 mdelay(1);
616#define SCIF_NODEQP_SEND_TO_MSEC (3 * 1000)
617 if (loop_cnt++ > (SCIF_NODEQP_SEND_TO_MSEC)) {
618 err = -ENODEV;
619 break;
620 }
621 }
622 if (!err)
623 scif_rb_commit(&qp->outbound_q);
624 spin_unlock(&qp->send_lock);
625 if (!err) {
626 if (scifdev_self(scifdev))
627 /*
628 * For loopback we need to emulate an interrupt by
629 * queuing work for the queue handling real node
630 * Qp interrupts.
631 */
632 queue_work(scifdev->intr_wq, &scifdev->intr_bh);
633 else
634 scif_send_msg_intr(scifdev);
635 }
636error:
637 if (err)
638 dev_dbg(&scifdev->sdev->dev,
639 "%s %d error %d uop %d\n",
640 __func__, __LINE__, err, msg->uop);
641 return err;
642}
643
644/**
645 * scif_nodeqp_send - Send a message on the node queue pair
646 * @scifdev: Scif Device.
647 * @msg: The message to be sent.
648 */
649int scif_nodeqp_send(struct scif_dev *scifdev, struct scifmsg *msg)
650{
651 int err;
652 struct device *spdev = NULL;
653
654 if (msg->uop > SCIF_EXIT_ACK) {
655 /* Dont send messages once the exit flow has begun */
656 if (OP_IDLE != scifdev->exit)
657 return -ENODEV;
658 spdev = scif_get_peer_dev(scifdev);
659 if (IS_ERR(spdev)) {
660 err = PTR_ERR(spdev);
661 return err;
662 }
663 }
664 err = _scif_nodeqp_send(scifdev, msg);
665 if (msg->uop > SCIF_EXIT_ACK)
666 scif_put_peer_dev(spdev);
667 return err;
668}
669
670/*
671 * scif_misc_handler:
672 *
673 * Work queue handler for servicing miscellaneous SCIF tasks.
674 * Examples include:
Sudeep Duttd1824322015-09-29 18:16:25 -0700675 * 1) Remote fence requests.
676 * 2) Destruction of temporary registered windows
677 * created during scif_vreadfrom()/scif_vwriteto().
678 * 3) Cleanup of zombie endpoints.
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700679 */
680void scif_misc_handler(struct work_struct *work)
681{
Sudeep Duttd1824322015-09-29 18:16:25 -0700682 scif_rma_handle_remote_fences();
683 scif_rma_destroy_windows();
684 scif_rma_destroy_tcw_invalid();
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700685 scif_cleanup_zombie_epd();
686}
687
688/**
689 * scif_init() - Respond to SCIF_INIT interrupt message
690 * @scifdev: Remote SCIF device node
691 * @msg: Interrupt message
692 */
693static __always_inline void
694scif_init(struct scif_dev *scifdev, struct scifmsg *msg)
695{
696 /*
697 * Allow the thread waiting for device page updates for the peer QP DMA
698 * address to complete initializing the inbound_q.
699 */
700 flush_delayed_work(&scifdev->qp_dwork);
Ashutosh Dixitd3d912e2015-09-29 18:11:15 -0700701
702 scif_peer_register_device(scifdev);
703
704 if (scif_is_mgmt_node()) {
705 mutex_lock(&scif_info.conflock);
706 scif_p2p_setup();
707 mutex_unlock(&scif_info.conflock);
708 }
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700709}
710
711/**
712 * scif_exit() - Respond to SCIF_EXIT interrupt message
713 * @scifdev: Remote SCIF device node
714 * @msg: Interrupt message
715 *
716 * This function stops the SCIF interface for the node which sent
717 * the SCIF_EXIT message and starts waiting for that node to
718 * resetup the queue pair again.
719 */
720static __always_inline void
721scif_exit(struct scif_dev *scifdev, struct scifmsg *unused)
722{
723 scifdev->exit_ack_pending = true;
724 if (scif_is_mgmt_node())
725 scif_disconnect_node(scifdev->node, false);
726 else
727 scif_stop(scifdev);
728 schedule_delayed_work(&scifdev->qp_dwork,
729 msecs_to_jiffies(1000));
730}
731
732/**
733 * scif_exitack() - Respond to SCIF_EXIT_ACK interrupt message
734 * @scifdev: Remote SCIF device node
735 * @msg: Interrupt message
736 *
737 */
738static __always_inline void
739scif_exit_ack(struct scif_dev *scifdev, struct scifmsg *unused)
740{
741 scifdev->exit = OP_COMPLETED;
742 wake_up(&scif_info.exitwq);
743}
744
745/**
746 * scif_node_add() - Respond to SCIF_NODE_ADD interrupt message
747 * @scifdev: Remote SCIF device node
748 * @msg: Interrupt message
749 *
750 * When the mgmt node driver has finished initializing a MIC node queue pair it
751 * marks the node as online. It then looks for all currently online MIC cards
752 * and send a SCIF_NODE_ADD message to identify the ID of the new card for
753 * peer to peer initialization
754 *
755 * The local node allocates its incoming queue and sends its address in the
756 * SCIF_NODE_ADD_ACK message back to the mgmt node, the mgmt node "reflects"
757 * this message to the new node
758 */
759static __always_inline void
760scif_node_add(struct scif_dev *scifdev, struct scifmsg *msg)
761{
762 struct scif_dev *newdev;
763 dma_addr_t qp_offset;
764 int qp_connect;
765 struct scif_hw_dev *sdev;
766
767 dev_dbg(&scifdev->sdev->dev,
768 "Scifdev %d:%d received NODE_ADD msg for node %d\n",
769 scifdev->node, msg->dst.node, msg->src.node);
770 dev_dbg(&scifdev->sdev->dev,
771 "Remote address for this node's aperture %llx\n",
772 msg->payload[0]);
773 newdev = &scif_dev[msg->src.node];
774 newdev->node = msg->src.node;
775 newdev->sdev = scif_dev[SCIF_MGMT_NODE].sdev;
776 sdev = newdev->sdev;
777
778 if (scif_setup_intr_wq(newdev)) {
779 dev_err(&scifdev->sdev->dev,
780 "failed to setup interrupts for %d\n", msg->src.node);
781 goto interrupt_setup_error;
782 }
783 newdev->mmio.va = ioremap_nocache(msg->payload[1], sdev->mmio->len);
784 if (!newdev->mmio.va) {
785 dev_err(&scifdev->sdev->dev,
786 "failed to map mmio for %d\n", msg->src.node);
787 goto mmio_map_error;
788 }
789 newdev->qpairs = kzalloc(sizeof(*newdev->qpairs), GFP_KERNEL);
790 if (!newdev->qpairs)
791 goto qp_alloc_error;
792 /*
793 * Set the base address of the remote node's memory since it gets
794 * added to qp_offset
795 */
796 newdev->base_addr = msg->payload[0];
797
798 qp_connect = scif_setup_qp_connect(newdev->qpairs, &qp_offset,
799 SCIF_NODE_QP_SIZE, newdev);
800 if (qp_connect) {
801 dev_err(&scifdev->sdev->dev,
802 "failed to setup qp_connect %d\n", qp_connect);
803 goto qp_connect_error;
804 }
805
806 newdev->db = sdev->hw_ops->next_db(sdev);
807 newdev->cookie = sdev->hw_ops->request_irq(sdev, scif_intr_handler,
808 "SCIF_INTR", newdev,
809 newdev->db);
810 if (IS_ERR(newdev->cookie))
811 goto qp_connect_error;
812 newdev->qpairs->magic = SCIFEP_MAGIC;
813 newdev->qpairs->qp_state = SCIF_QP_OFFLINE;
814
815 msg->uop = SCIF_NODE_ADD_ACK;
816 msg->dst.node = msg->src.node;
817 msg->src.node = scif_info.nodeid;
818 msg->payload[0] = qp_offset;
819 msg->payload[2] = newdev->db;
820 scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], msg);
821 return;
822qp_connect_error:
823 kfree(newdev->qpairs);
824 newdev->qpairs = NULL;
825qp_alloc_error:
826 iounmap(newdev->mmio.va);
827 newdev->mmio.va = NULL;
828mmio_map_error:
829interrupt_setup_error:
830 dev_err(&scifdev->sdev->dev,
831 "node add failed for node %d\n", msg->src.node);
832 msg->uop = SCIF_NODE_ADD_NACK;
833 msg->dst.node = msg->src.node;
834 msg->src.node = scif_info.nodeid;
835 scif_nodeqp_send(&scif_dev[SCIF_MGMT_NODE], msg);
836}
837
838void scif_poll_qp_state(struct work_struct *work)
839{
840#define SCIF_NODE_QP_RETRY 100
841#define SCIF_NODE_QP_TIMEOUT 100
842 struct scif_dev *peerdev = container_of(work, struct scif_dev,
843 p2p_dwork.work);
844 struct scif_qp *qp = &peerdev->qpairs[0];
845
846 if (qp->qp_state != SCIF_QP_ONLINE ||
847 qp->remote_qp->qp_state != SCIF_QP_ONLINE) {
848 if (peerdev->p2p_retry++ == SCIF_NODE_QP_RETRY) {
849 dev_err(&peerdev->sdev->dev,
850 "Warning: QP check timeout with state %d\n",
851 qp->qp_state);
852 goto timeout;
853 }
854 schedule_delayed_work(&peerdev->p2p_dwork,
855 msecs_to_jiffies(SCIF_NODE_QP_TIMEOUT));
856 return;
857 }
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700858 return;
859timeout:
860 dev_err(&peerdev->sdev->dev,
861 "%s %d remote node %d offline, state = 0x%x\n",
862 __func__, __LINE__, peerdev->node, qp->qp_state);
863 qp->remote_qp->qp_state = SCIF_QP_OFFLINE;
Ashutosh Dixitd3d912e2015-09-29 18:11:15 -0700864 scif_peer_unregister_device(peerdev);
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700865 scif_cleanup_scifdev(peerdev);
866}
867
868/**
869 * scif_node_add_ack() - Respond to SCIF_NODE_ADD_ACK interrupt message
870 * @scifdev: Remote SCIF device node
871 * @msg: Interrupt message
872 *
873 * After a MIC node receives the SCIF_NODE_ADD_ACK message it send this
874 * message to the mgmt node to confirm the sequence is finished.
875 *
876 */
877static __always_inline void
878scif_node_add_ack(struct scif_dev *scifdev, struct scifmsg *msg)
879{
880 struct scif_dev *peerdev;
881 struct scif_qp *qp;
882 struct scif_dev *dst_dev = &scif_dev[msg->dst.node];
883
884 dev_dbg(&scifdev->sdev->dev,
885 "Scifdev %d received SCIF_NODE_ADD_ACK msg src %d dst %d\n",
886 scifdev->node, msg->src.node, msg->dst.node);
887 dev_dbg(&scifdev->sdev->dev,
888 "payload %llx %llx %llx %llx\n", msg->payload[0],
889 msg->payload[1], msg->payload[2], msg->payload[3]);
890 if (scif_is_mgmt_node()) {
891 /*
892 * the lock serializes with scif_qp_response_ack. The mgmt node
893 * is forwarding the NODE_ADD_ACK message from src to dst we
894 * need to make sure that the dst has already received a
895 * NODE_ADD for src and setup its end of the qp to dst
896 */
897 mutex_lock(&scif_info.conflock);
898 msg->payload[1] = scif_info.maxid;
899 scif_nodeqp_send(dst_dev, msg);
900 mutex_unlock(&scif_info.conflock);
901 return;
902 }
903 peerdev = &scif_dev[msg->src.node];
904 peerdev->sdev = scif_dev[SCIF_MGMT_NODE].sdev;
905 peerdev->node = msg->src.node;
906
907 qp = &peerdev->qpairs[0];
908
909 if ((scif_setup_qp_connect_response(peerdev, &peerdev->qpairs[0],
910 msg->payload[0])))
911 goto local_error;
912 peerdev->rdb = msg->payload[2];
913 qp->remote_qp->qp_state = SCIF_QP_ONLINE;
Ashutosh Dixitd3d912e2015-09-29 18:11:15 -0700914
915 scif_peer_register_device(peerdev);
916
Sudeep Dutt40cb5942015-04-29 05:32:34 -0700917 schedule_delayed_work(&peerdev->p2p_dwork, 0);
918 return;
919local_error:
920 scif_cleanup_scifdev(peerdev);
921}
922
923/**
924 * scif_node_add_nack: Respond to SCIF_NODE_ADD_NACK interrupt message
925 * @msg: Interrupt message
926 *
927 * SCIF_NODE_ADD failed, so inform the waiting wq.
928 */
929static __always_inline void
930scif_node_add_nack(struct scif_dev *scifdev, struct scifmsg *msg)
931{
932 if (scif_is_mgmt_node()) {
933 struct scif_dev *dst_dev = &scif_dev[msg->dst.node];
934
935 dev_dbg(&scifdev->sdev->dev,
936 "SCIF_NODE_ADD_NACK received from %d\n", scifdev->node);
937 scif_nodeqp_send(dst_dev, msg);
938 }
939}
940
941/*
942 * scif_node_remove: Handle SCIF_NODE_REMOVE message
943 * @msg: Interrupt message
944 *
945 * Handle node removal.
946 */
947static __always_inline void
948scif_node_remove(struct scif_dev *scifdev, struct scifmsg *msg)
949{
950 int node = msg->payload[0];
951 struct scif_dev *scdev = &scif_dev[node];
952
953 scdev->node_remove_ack_pending = true;
954 scif_handle_remove_node(node);
955}
956
957/*
958 * scif_node_remove_ack: Handle SCIF_NODE_REMOVE_ACK message
959 * @msg: Interrupt message
960 *
961 * The peer has acked a SCIF_NODE_REMOVE message.
962 */
963static __always_inline void
964scif_node_remove_ack(struct scif_dev *scifdev, struct scifmsg *msg)
965{
966 struct scif_dev *sdev = &scif_dev[msg->payload[0]];
967
968 atomic_inc(&sdev->disconn_rescnt);
969 wake_up(&sdev->disconn_wq);
970}
971
Sudeep Duttfdd9fd52015-04-29 05:32:37 -0700972/**
973 * scif_get_node_info: Respond to SCIF_GET_NODE_INFO interrupt message
974 * @msg: Interrupt message
975 *
976 * Retrieve node info i.e maxid and total from the mgmt node.
977 */
978static __always_inline void
979scif_get_node_info_resp(struct scif_dev *scifdev, struct scifmsg *msg)
980{
981 if (scif_is_mgmt_node()) {
982 swap(msg->dst.node, msg->src.node);
983 mutex_lock(&scif_info.conflock);
984 msg->payload[1] = scif_info.maxid;
985 msg->payload[2] = scif_info.total;
986 mutex_unlock(&scif_info.conflock);
987 scif_nodeqp_send(scifdev, msg);
988 } else {
989 struct completion *node_info =
990 (struct completion *)msg->payload[3];
991
992 mutex_lock(&scif_info.conflock);
993 scif_info.maxid = msg->payload[1];
994 scif_info.total = msg->payload[2];
995 complete_all(node_info);
996 mutex_unlock(&scif_info.conflock);
997 }
998}
999
Sudeep Dutt40cb5942015-04-29 05:32:34 -07001000static void
1001scif_msg_unknown(struct scif_dev *scifdev, struct scifmsg *msg)
1002{
1003 /* Bogus Node Qp Message? */
1004 dev_err(&scifdev->sdev->dev,
1005 "Unknown message 0x%xn scifdev->node 0x%x\n",
1006 msg->uop, scifdev->node);
1007}
1008
1009static void (*scif_intr_func[SCIF_MAX_MSG + 1])
1010 (struct scif_dev *, struct scifmsg *msg) = {
1011 scif_msg_unknown, /* Error */
1012 scif_init, /* SCIF_INIT */
1013 scif_exit, /* SCIF_EXIT */
1014 scif_exit_ack, /* SCIF_EXIT_ACK */
1015 scif_node_add, /* SCIF_NODE_ADD */
1016 scif_node_add_ack, /* SCIF_NODE_ADD_ACK */
1017 scif_node_add_nack, /* SCIF_NODE_ADD_NACK */
1018 scif_node_remove, /* SCIF_NODE_REMOVE */
1019 scif_node_remove_ack, /* SCIF_NODE_REMOVE_ACK */
Nikhil Rao76371c72015-04-29 05:32:36 -07001020 scif_cnctreq, /* SCIF_CNCT_REQ */
1021 scif_cnctgnt, /* SCIF_CNCT_GNT */
1022 scif_cnctgnt_ack, /* SCIF_CNCT_GNTACK */
1023 scif_cnctgnt_nack, /* SCIF_CNCT_GNTNACK */
1024 scif_cnctrej, /* SCIF_CNCT_REJ */
1025 scif_discnct, /* SCIF_DISCNCT */
1026 scif_discnt_ack, /* SCIF_DISCNT_ACK */
Sudeep Duttfdd9fd52015-04-29 05:32:37 -07001027 scif_clientsend, /* SCIF_CLIENT_SENT */
1028 scif_clientrcvd, /* SCIF_CLIENT_RCVD */
1029 scif_get_node_info_resp,/* SCIF_GET_NODE_INFO */
Sudeep Duttd1824322015-09-29 18:16:25 -07001030 scif_recv_reg, /* SCIF_REGISTER */
1031 scif_recv_reg_ack, /* SCIF_REGISTER_ACK */
1032 scif_recv_reg_nack, /* SCIF_REGISTER_NACK */
1033 scif_recv_unreg, /* SCIF_UNREGISTER */
1034 scif_recv_unreg_ack, /* SCIF_UNREGISTER_ACK */
1035 scif_recv_unreg_nack, /* SCIF_UNREGISTER_NACK */
1036 scif_alloc_req, /* SCIF_ALLOC_REQ */
1037 scif_alloc_gnt_rej, /* SCIF_ALLOC_GNT */
1038 scif_alloc_gnt_rej, /* SCIF_ALLOC_REJ */
1039 scif_free_virt, /* SCIF_FREE_VIRT */
1040 scif_recv_munmap, /* SCIF_MUNMAP */
1041 scif_recv_mark, /* SCIF_MARK */
1042 scif_recv_mark_resp, /* SCIF_MARK_ACK */
1043 scif_recv_mark_resp, /* SCIF_MARK_NACK */
1044 scif_recv_wait, /* SCIF_WAIT */
1045 scif_recv_wait_resp, /* SCIF_WAIT_ACK */
1046 scif_recv_wait_resp, /* SCIF_WAIT_NACK */
1047 scif_recv_sig_local, /* SCIF_SIG_LOCAL */
1048 scif_recv_sig_remote, /* SCIF_SIG_REMOTE */
1049 scif_recv_sig_resp, /* SCIF_SIG_ACK */
1050 scif_recv_sig_resp, /* SCIF_SIG_NACK */
Sudeep Dutt40cb5942015-04-29 05:32:34 -07001051};
1052
1053/**
1054 * scif_nodeqp_msg_handler() - Common handler for node messages
1055 * @scifdev: Remote device to respond to
1056 * @qp: Remote memory pointer
1057 * @msg: The message to be handled.
1058 *
1059 * This routine calls the appropriate routine to handle a Node Qp
1060 * message receipt
1061 */
1062static int scif_max_msg_id = SCIF_MAX_MSG;
1063
1064static void
1065scif_nodeqp_msg_handler(struct scif_dev *scifdev,
1066 struct scif_qp *qp, struct scifmsg *msg)
1067{
1068 scif_display_message(scifdev, msg, "Rcvd");
1069
1070 if (msg->uop > (u32)scif_max_msg_id) {
1071 /* Bogus Node Qp Message? */
1072 dev_err(&scifdev->sdev->dev,
1073 "Unknown message 0x%xn scifdev->node 0x%x\n",
1074 msg->uop, scifdev->node);
1075 return;
1076 }
1077
1078 scif_intr_func[msg->uop](scifdev, msg);
1079}
1080
1081/**
1082 * scif_nodeqp_intrhandler() - Interrupt handler for node messages
1083 * @scifdev: Remote device to respond to
1084 * @qp: Remote memory pointer
1085 *
1086 * This routine is triggered by the interrupt mechanism. It reads
1087 * messages from the node queue RB and calls the Node QP Message handling
1088 * routine.
1089 */
1090void scif_nodeqp_intrhandler(struct scif_dev *scifdev, struct scif_qp *qp)
1091{
1092 struct scifmsg msg;
1093 int read_size;
1094
1095 do {
1096 read_size = scif_rb_get_next(&qp->inbound_q, &msg, sizeof(msg));
1097 if (!read_size)
1098 break;
1099 scif_nodeqp_msg_handler(scifdev, qp, &msg);
1100 /*
1101 * The node queue pair is unmapped so skip the read pointer
1102 * update after receipt of a SCIF_EXIT_ACK
1103 */
1104 if (SCIF_EXIT_ACK == msg.uop)
1105 break;
1106 scif_rb_update_read_ptr(&qp->inbound_q);
1107 } while (1);
1108}
1109
1110/**
1111 * scif_loopb_wq_handler - Loopback Workqueue Handler.
1112 * @work: loop back work
1113 *
1114 * This work queue routine is invoked by the loopback work queue handler.
1115 * It grabs the recv lock, dequeues any available messages from the head
1116 * of the loopback message list, calls the node QP message handler,
1117 * waits for it to return, then frees up this message and dequeues more
1118 * elements of the list if available.
1119 */
1120static void scif_loopb_wq_handler(struct work_struct *unused)
1121{
1122 struct scif_dev *scifdev = scif_info.loopb_dev;
1123 struct scif_qp *qp = scifdev->qpairs;
1124 struct scif_loopb_msg *msg;
1125
1126 do {
1127 msg = NULL;
1128 spin_lock(&qp->recv_lock);
1129 if (!list_empty(&scif_info.loopb_recv_q)) {
1130 msg = list_first_entry(&scif_info.loopb_recv_q,
1131 struct scif_loopb_msg,
1132 list);
1133 list_del(&msg->list);
1134 }
1135 spin_unlock(&qp->recv_lock);
1136
1137 if (msg) {
1138 scif_nodeqp_msg_handler(scifdev, qp, &msg->msg);
1139 kfree(msg);
1140 }
1141 } while (msg);
1142}
1143
1144/**
1145 * scif_loopb_msg_handler() - Workqueue handler for loopback messages.
1146 * @scifdev: SCIF device
1147 * @qp: Queue pair.
1148 *
1149 * This work queue routine is triggered when a loopback message is received.
1150 *
1151 * We need special handling for receiving Node Qp messages on a loopback SCIF
1152 * device via two workqueues for receiving messages.
1153 *
1154 * The reason we need the extra workqueue which is not required with *normal*
1155 * non-loopback SCIF devices is the potential classic deadlock described below:
1156 *
1157 * Thread A tries to send a message on a loopback SCIF device and blocks since
1158 * there is no space in the RB while it has the send_lock held or another
1159 * lock called lock X for example.
1160 *
1161 * Thread B: The Loopback Node QP message receive workqueue receives the message
1162 * and tries to send a message (eg an ACK) to the loopback SCIF device. It tries
1163 * to grab the send lock again or lock X and deadlocks with Thread A. The RB
1164 * cannot be drained any further due to this classic deadlock.
1165 *
1166 * In order to avoid deadlocks as mentioned above we have an extra level of
1167 * indirection achieved by having two workqueues.
1168 * 1) The first workqueue whose handler is scif_loopb_msg_handler reads
1169 * messages from the Node QP RB, adds them to a list and queues work for the
1170 * second workqueue.
1171 *
1172 * 2) The second workqueue whose handler is scif_loopb_wq_handler dequeues
1173 * messages from the list, handles them, frees up the memory and dequeues
1174 * more elements from the list if possible.
1175 */
1176int
1177scif_loopb_msg_handler(struct scif_dev *scifdev, struct scif_qp *qp)
1178{
1179 int read_size;
1180 struct scif_loopb_msg *msg;
1181
1182 do {
1183 msg = kmalloc(sizeof(*msg), GFP_KERNEL);
1184 if (!msg)
1185 return -ENOMEM;
1186 read_size = scif_rb_get_next(&qp->inbound_q, &msg->msg,
1187 sizeof(struct scifmsg));
1188 if (read_size != sizeof(struct scifmsg)) {
1189 kfree(msg);
1190 scif_rb_update_read_ptr(&qp->inbound_q);
1191 break;
1192 }
1193 spin_lock(&qp->recv_lock);
1194 list_add_tail(&msg->list, &scif_info.loopb_recv_q);
1195 spin_unlock(&qp->recv_lock);
1196 queue_work(scif_info.loopb_wq, &scif_info.loopb_work);
1197 scif_rb_update_read_ptr(&qp->inbound_q);
1198 } while (read_size == sizeof(struct scifmsg));
1199 return read_size;
1200}
1201
1202/**
1203 * scif_setup_loopback_qp - One time setup work for Loopback Node Qp.
1204 * @scifdev: SCIF device
1205 *
1206 * Sets up the required loopback workqueues, queue pairs and ring buffers
1207 */
1208int scif_setup_loopback_qp(struct scif_dev *scifdev)
1209{
1210 int err = 0;
1211 void *local_q;
1212 struct scif_qp *qp;
Sudeep Dutt40cb5942015-04-29 05:32:34 -07001213
1214 err = scif_setup_intr_wq(scifdev);
1215 if (err)
1216 goto exit;
1217 INIT_LIST_HEAD(&scif_info.loopb_recv_q);
1218 snprintf(scif_info.loopb_wqname, sizeof(scif_info.loopb_wqname),
1219 "SCIF LOOPB %d", scifdev->node);
1220 scif_info.loopb_wq =
1221 alloc_ordered_workqueue(scif_info.loopb_wqname, 0);
1222 if (!scif_info.loopb_wq) {
1223 err = -ENOMEM;
1224 goto destroy_intr;
1225 }
1226 INIT_WORK(&scif_info.loopb_work, scif_loopb_wq_handler);
1227 /* Allocate Self Qpair */
1228 scifdev->qpairs = kzalloc(sizeof(*scifdev->qpairs), GFP_KERNEL);
1229 if (!scifdev->qpairs) {
1230 err = -ENOMEM;
1231 goto destroy_loopb_wq;
1232 }
1233
1234 qp = scifdev->qpairs;
1235 qp->magic = SCIFEP_MAGIC;
1236 spin_lock_init(&qp->send_lock);
1237 spin_lock_init(&qp->recv_lock);
1238
1239 local_q = kzalloc(SCIF_NODE_QP_SIZE, GFP_KERNEL);
1240 if (!local_q) {
1241 err = -ENOMEM;
1242 goto free_qpairs;
1243 }
1244 /*
1245 * For loopback the inbound_q and outbound_q are essentially the same
1246 * since the Node sends a message on the loopback interface to the
1247 * outbound_q which is then received on the inbound_q.
1248 */
1249 scif_rb_init(&qp->outbound_q,
1250 &qp->local_read,
1251 &qp->local_write,
1252 local_q, get_count_order(SCIF_NODE_QP_SIZE));
1253
1254 scif_rb_init(&qp->inbound_q,
1255 &qp->local_read,
1256 &qp->local_write,
1257 local_q, get_count_order(SCIF_NODE_QP_SIZE));
1258 scif_info.nodeid = scifdev->node;
Ashutosh Dixitd3d912e2015-09-29 18:11:15 -07001259
1260 scif_peer_register_device(scifdev);
1261
Sudeep Dutt40cb5942015-04-29 05:32:34 -07001262 scif_info.loopb_dev = scifdev;
1263 return err;
Sudeep Dutt40cb5942015-04-29 05:32:34 -07001264free_qpairs:
1265 kfree(scifdev->qpairs);
1266destroy_loopb_wq:
1267 destroy_workqueue(scif_info.loopb_wq);
1268destroy_intr:
1269 scif_destroy_intr_wq(scifdev);
1270exit:
1271 return err;
1272}
1273
1274/**
1275 * scif_destroy_loopback_qp - One time uninit work for Loopback Node Qp
1276 * @scifdev: SCIF device
1277 *
1278 * Destroys the workqueues and frees up the Ring Buffer and Queue Pair memory.
1279 */
1280int scif_destroy_loopback_qp(struct scif_dev *scifdev)
1281{
Ashutosh Dixitd3d912e2015-09-29 18:11:15 -07001282 scif_peer_unregister_device(scifdev);
Sudeep Dutt40cb5942015-04-29 05:32:34 -07001283 destroy_workqueue(scif_info.loopb_wq);
1284 scif_destroy_intr_wq(scifdev);
1285 kfree(scifdev->qpairs->outbound_q.rb_base);
1286 kfree(scifdev->qpairs);
1287 scifdev->sdev = NULL;
1288 scif_info.loopb_dev = NULL;
1289 return 0;
1290}
1291
1292void scif_destroy_p2p(struct scif_dev *scifdev)
1293{
1294 struct scif_dev *peer_dev;
1295 struct scif_p2p_info *p2p;
1296 struct list_head *pos, *tmp;
1297 int bd;
1298
1299 mutex_lock(&scif_info.conflock);
1300 /* Free P2P mappings in the given node for all its peer nodes */
1301 list_for_each_safe(pos, tmp, &scifdev->p2p) {
1302 p2p = list_entry(pos, struct scif_p2p_info, ppi_list);
1303 dma_unmap_sg(&scifdev->sdev->dev, p2p->ppi_sg[SCIF_PPI_MMIO],
1304 p2p->sg_nentries[SCIF_PPI_MMIO],
1305 DMA_BIDIRECTIONAL);
1306 dma_unmap_sg(&scifdev->sdev->dev, p2p->ppi_sg[SCIF_PPI_APER],
1307 p2p->sg_nentries[SCIF_PPI_APER],
1308 DMA_BIDIRECTIONAL);
1309 scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_MMIO]);
1310 scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_APER]);
1311 list_del(pos);
1312 kfree(p2p);
1313 }
1314
1315 /* Free P2P mapping created in the peer nodes for the given node */
1316 for (bd = SCIF_MGMT_NODE + 1; bd <= scif_info.maxid; bd++) {
1317 peer_dev = &scif_dev[bd];
1318 list_for_each_safe(pos, tmp, &peer_dev->p2p) {
1319 p2p = list_entry(pos, struct scif_p2p_info, ppi_list);
1320 if (p2p->ppi_peer_id == scifdev->node) {
1321 dma_unmap_sg(&peer_dev->sdev->dev,
1322 p2p->ppi_sg[SCIF_PPI_MMIO],
1323 p2p->sg_nentries[SCIF_PPI_MMIO],
1324 DMA_BIDIRECTIONAL);
1325 dma_unmap_sg(&peer_dev->sdev->dev,
1326 p2p->ppi_sg[SCIF_PPI_APER],
1327 p2p->sg_nentries[SCIF_PPI_APER],
1328 DMA_BIDIRECTIONAL);
1329 scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_MMIO]);
1330 scif_p2p_freesg(p2p->ppi_sg[SCIF_PPI_APER]);
1331 list_del(pos);
1332 kfree(p2p);
1333 }
1334 }
1335 }
1336 mutex_unlock(&scif_info.conflock);
1337}