Updated `README.md` with instructions for building/using the kernel module.
[xeon-phi-kernel-module] / micscif / micscif_nm.c
CommitLineData
800f879a
AT
1/*
2 * Copyright 2010-2017 Intel Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * Disclaimer: The codes contained in these modules may be specific to
14 * the Intel Software Development Platform codenamed Knights Ferry,
15 * and the Intel product codenamed Knights Corner, and are not backward
16 * compatible with other Intel products. Additionally, Intel will NOT
17 * support the codes or instruction set in future products.
18 *
19 * Intel offers no warranty of any kind regarding the code. This code is
20 * licensed on an "AS IS" basis and Intel is not obligated to provide
21 * any support, assistance, installation, training, or other services
22 * of any kind. Intel is also not obligated to provide any updates,
23 * enhancements or extensions. Intel specifically disclaims any warranty
24 * of merchantability, non-infringement, fitness for any particular
25 * purpose, and any other warranty.
26 *
27 * Further, Intel disclaims all liability of any kind, including but
28 * not limited to liability for infringement of any proprietary rights,
29 * relating to the use of the code, even if Intel is notified of the
30 * possibility of such liability. Except as expressly stated in an Intel
31 * license agreement provided with this code and agreed upon with Intel,
32 * no license, express or implied, by estoppel or otherwise, to any
33 * intellectual property rights is granted herein.
34 */
35
36/* SCIF Node Management */
37
38#include "mic/micscif.h"
39#ifndef _MIC_SCIF_
40#include "mic_common.h"
41
42#endif
43#include "mic/micscif_map.h"
44#include "mic/micscif_intr.h"
45#ifdef _MIC_SCIF_
46extern mic_dma_handle_t mic_dma_handle;
47#else
48extern bool mic_crash_dump_enabled;
49#endif
50
51
52/**
53 * micscif_create_node_dep:
54 *
55 * @dev: Remote SCIF device.
56 * @nr_pages: number of pages*
57 *
58 * Increment the map SCIF device ref count and notify the host if this is the
59 * first dependency being create between the two nodes.
60 */
61void
62micscif_create_node_dep(struct micscif_dev *dev, int nr_pages)
63{
64#ifdef SCIF_ENABLE_PM
65 struct nodemsg notif_msg;
66
67 if (dev) {
68 mutex_lock(&dev->sd_lock);
69 if (!dev->scif_map_ref_cnt) {
70 /* Notify Host if this is the first dependency being created */
71 notif_msg.uop = SCIF_NODE_CREATE_DEP;
72 notif_msg.src.node = ms_info.mi_nodeid;
73 notif_msg.payload[0] = dev->sd_node;
74 /* No error handling for Host SCIF device */
75 micscif_nodeqp_send(&scif_dev[SCIF_HOST_NODE], &notif_msg, NULL);
76 }
77 dev->scif_map_ref_cnt += nr_pages;
78 mutex_unlock(&dev->sd_lock);
79 }
80#endif
81}
82
83/**
84 * micscif_destroy_node_dep:
85 *
86 * @dev: Remote SCIF device.
87 * @nr_pages: number of pages
88 *
89 * Decrement the map SCIF device ref count and notify the host if a dependency
90 * no longer exists between two nodes.
91 */
92void
93micscif_destroy_node_dep(struct micscif_dev *dev, int nr_pages)
94{
95#ifdef SCIF_ENABLE_PM
96 struct nodemsg notif_msg;
97
98 if (dev) {
99 mutex_lock(&dev->sd_lock);
100 dev->scif_map_ref_cnt -= nr_pages;
101 if (!dev->scif_map_ref_cnt) {
102 /* Notify Host if all dependencies have been destroyed */
103 notif_msg.uop = SCIF_NODE_DESTROY_DEP;
104 notif_msg.src.node = ms_info.mi_nodeid;
105 notif_msg.payload[0] = dev->sd_node;
106 /* No error handling for Host SCIF device */
107 micscif_nodeqp_send(&scif_dev[SCIF_HOST_NODE], &notif_msg, NULL);
108 }
109 mutex_unlock(&dev->sd_lock);
110 }
111#endif
112}
113
114/**
115 * micscif_callback:
116 *
117 * @node: node id of the node added/removed.
118 * @event_type: SCIF_NODE_ADDED if a new node is added
119 * SCIF_NODE_REMOVED if a new node is removed
120 *
121 * Calls the callback function whenever a new node is added/removed
122 */
123static void micscif_callback(uint16_t node, enum scif_event_type event_type)
124{
125 struct list_head *pos;
126 struct scif_callback *temp;
127 union eventd event;
128
129 switch (event_type) {
130 case SCIF_NODE_ADDED:
131 event.scif_node_added = node;
132 break;
133 case SCIF_NODE_REMOVED:
134 event.scif_node_removed = node;
135 break;
136 default:
137 return;
138 }
139
140 mutex_lock(&ms_info.mi_event_cblock);
141 list_for_each(pos, &ms_info.mi_event_cb) {
142 temp = list_entry(pos, struct scif_callback, list_member);
143 temp->callback_handler(event_type, event);
144 }
145 mutex_unlock(&ms_info.mi_event_cblock);
146}
147
148/**
149 * micscif_node_remove_callback:
150 *
151 * @node: node id of the node removed.
152 *
153 * Calls the callback function whenever a new node is removed
154 */
155static void micscif_node_remove_callback(int node)
156{
157 micscif_callback((uint16_t)node, SCIF_NODE_REMOVED);
158}
159
160/**
161 * micscif_node_add_callback:
162 *
163 * @node: node id of the node added.
164 *
165 * Calls the callback function whenever a new node is added
166 */
167void micscif_node_add_callback(int node)
168{
169 micscif_callback((uint16_t)node, SCIF_NODE_ADDED);
170}
171
172void micscif_cleanup_qp(struct micscif_dev *dev)
173{
174 struct micscif_qp *qp;
175
176 qp = &dev->qpairs[0];
177
178 if (!qp)
179 return;
180
181 scif_iounmap((void*)qp->remote_qp, sizeof(struct micscif_qp), dev);
182 scif_iounmap((void*)dev->qpairs[0].outbound_q.rb_base, sizeof(struct micscif_qp), dev);
183 qp->remote_qp = NULL;
184 dev->qpairs[0].local_write = 0;
185 dev->qpairs[0].inbound_q.current_write_offset = 0;
186 dev->qpairs[0].inbound_q.current_read_offset = 0;
187#ifdef _MIC_SCIF_
188 kfree((void*)(qp->inbound_q.rb_base));
189 kfree(dev->qpairs);
190 qp = NULL;
191#endif
192}
193
194/*
195 * micscif_cleanup_scifdev
196 *
197 * @dev: Remote SCIF device.
198 * Uninitialize SCIF data structures for remote SCIF device.
199 */
200void micscif_cleanup_scifdev(struct micscif_dev *dev, bool destroy_wq)
201{
202 int64_t ret;
203#ifndef _MIC_SCIF_
204 mic_ctx_t *mic_ctx;
205#endif
206 if (SCIFDEV_NOTPRESENT == dev->sd_state) {
207#ifdef _MIC_SCIF_
208 /*
209 * If there are any stale qp allocated due to
210 * p2p connection failures then cleanup now
211 */
212 micscif_cleanup_qp(dev);
213#endif
214 return;
215 }
216
217 dev->sd_wait_status = OP_FAILED;
218 wake_up(&dev->sd_wq);
219
220#ifdef _MIC_SCIF_
221 /*
222 * Need to protect destruction of the workqueue since this code
223 * can be called from two contexts:
224 * a) Remove Node Handling.
225 * b) SCIF driver unload
226 */
227 mutex_lock(&dev->sd_lock);
228 if ((SCIFDEV_RUNNING != dev->sd_state) && (SCIFDEV_SLEEPING != dev->sd_state))
229 goto unlock;
230 dev->sd_state = SCIFDEV_STOPPED;
231 wake_up(&dev->sd_p2p_wq);
232 mutex_unlock(&dev->sd_lock);
233 deregister_scif_intr_handler(dev);
234 if (destroy_wq && dev->sd_intr_wq) {
235 destroy_workqueue(dev->sd_intr_wq);
236 dev->sd_intr_wq = NULL;
237 }
238#endif
239
240 mutex_lock(&dev->sd_lock);
241#ifndef _MIC_SCIF_
242 if ((SCIFDEV_RUNNING != dev->sd_state) && (SCIFDEV_SLEEPING != dev->sd_state))
243 goto unlock;
244 dev->sd_state = SCIFDEV_STOPPED;
245#endif
246 /*
247 * Change the state of the remote SCIF device
248 * to idle as soon as the activity counter is
249 * zero. The node state and ref count is
250 * maintained within a single atomic_long_t.
251 * No timeout for this tight loop since we expect
252 * the node to complete the API it is currently
253 * executing following which the scif_ref_count
254 * will drop to zero.
255 */
256 do {
257 ret = atomic_long_cmpxchg(
258 &dev->scif_ref_cnt, 0, SCIF_NODE_IDLE);
259 cpu_relax();
260 } while (ret && ret != SCIF_NODE_IDLE);
261
262 mutex_unlock(&dev->sd_lock);
263 /* Cleanup temporary registered windows */
264 flush_workqueue(ms_info.mi_misc_wq);
265 mutex_lock(&dev->sd_lock);
266
267#ifdef _MIC_SCIF_
268 drain_dma_global(mic_dma_handle);
269#else
270 mic_ctx = get_per_dev_ctx(dev->sd_node - 1);
271 drain_dma_global(mic_ctx->dma_handle);
272 micscif_destroy_p2p(mic_ctx);
273#endif
274 scif_invalidate_ep(dev->sd_node);
275 micscif_kill_apps_with_mmaps(dev->sd_node);
276
277 micscif_cleanup_qp(dev);
278 mutex_unlock(&dev->sd_lock);
279#ifndef _MIC_SCIF_
280 mutex_lock(&ms_info.mi_conflock);
281 ms_info.mi_mask &= ~(0x1 << dev->sd_node);
282 ms_info.mi_total--;
283 mutex_unlock(&ms_info.mi_conflock);
284#endif
285
286 /* Wait for all applications to unmap remote memory mappings. */
287 wait_event(dev->sd_mmap_wq,
288 !micscif_rma_do_apps_have_mmaps(dev->sd_node));
289 micscif_cleanup_rma_for_zombies(dev->sd_node);
290 micscif_node_remove_callback(dev->sd_node);
291 return;
292unlock:
293 mutex_unlock(&dev->sd_lock);
294}
295
296/*
297 * micscif_remove_node:
298 *
299 * @mask: bitmask of nodes in the deactivation set.
300 * @flags: Type of deactivation set i.e. Power Management,
301 * RAS, Maintenance Mode etc.
302 * @block: Can block.
303 *
304 * Attempt to deactivate a set of remote SCIF devices nodes passed in mask.
305 * If the SCIF activity ref count is positive for a remote node then
306 * the approporiate bit in the input bitmask is reset and the resultant
307 * bitmask is returned.
308 */
309uint64_t micscif_handle_remove_node(uint64_t mask, uint64_t payload)
310{
311 int64_t ret;
312 int err = 0;
313 uint32_t i;
314 struct micscif_dev *dev;
315 uint64_t flags = 0;
316 flags = payload & 0x00000000FFFFFFFF;
317
318 switch(flags) {
319 case DISCONN_TYPE_POWER_MGMT:
320 {
321 uint8_t *nodemask_buf = NULL;
322 int size = payload >> 32;
323
324#ifndef _MIC_SCIF_
325 nodemask_buf = mic_data.dd_pm.nodemask;
326#else
327 nodemask_buf = scif_ioremap(mask, size, &scif_dev[SCIF_HOST_NODE]);
328#endif
329 if (!nodemask_buf) {
330 err = EAGAIN;
331 break;
332 }
333
334 for (i = 0; i <= ms_info.mi_maxid; i++) {
335 dev = &scif_dev[i];
336 if (!get_nodemask_bit(nodemask_buf , i))
337 continue;
338 /*
339 * Try for the SCIF device lock. Bail out if
340 * it is already grabbed since some other
341 * thread is already working on some other
342 * node state transition for this remote SCIF device.
343 */
344 if (mutex_trylock(&dev->sd_lock)) {
345
346 if (SCIFDEV_RUNNING != dev->sd_state) {
347 mutex_unlock(&dev->sd_lock);
348 continue;
349 }
350 /*
351 * Change the state of the remote SCIF device
352 * to idle only if the activity counter is
353 * already zero. The node state and ref count
354 * is maintained within a single atomic_long_t.
355 */
356 ret = atomic_long_cmpxchg(
357 &dev->scif_ref_cnt, 0, SCIF_NODE_IDLE);
358
359 if (!ret || ret == SCIF_NODE_IDLE) {
360 if (!ret) {
361#ifdef _MIC_SCIF_
362 drain_dma_global(mic_dma_handle);
363#else
364 mic_ctx_t *mic_ctx = get_per_dev_ctx(dev->sd_node - 1);
365 drain_dma_global(mic_ctx->dma_handle);
366#endif
367 }
368 /*
369 * Turn off the remote SCIF device.
370 * Any communication to this SCIF
371 * after this point will require a
372 * wake up message to the host.
373 */
374 dev->sd_state = SCIFDEV_SLEEPING;
375 err = 0;
376 }
377 else {
378 /*
379 * Cannot put the remote SCIF device
380 * to sleep.
381 */
382 err = EAGAIN;
383 mutex_unlock(&dev->sd_lock);
384 break;
385 }
386 mutex_unlock(&dev->sd_lock);
387 } else {
388 err = EAGAIN;
389 break;
390 }
391 }
392
393#ifndef _MIC_SCIF_
394 scif_iounmap(nodemask_buf, size, &scif_dev[SCIF_HOST_NODE]);
395#endif
396
397 break;
398 }
399 case DISCONN_TYPE_LOST_NODE:
400 {
401 /* In the case of lost node, first paramater
402 * is the node id and not a mask.
403 */
404 dev = &scif_dev[mask];
405 micscif_cleanup_scifdev(dev, !DESTROY_WQ);
406 break;
407 }
408 default:
409 {
410 /* Unknown remove node flags */
411 BUG_ON(1);
412 }
413 }
414
415 return err;
416}
417
418/**
419 * set_nodemask_bit:
420 *
421 * @node_id[in]: node id to be set in the mask
422 *
423 * Set bit in the nodemask. each bit represents node. set bit to add node in to
424 * activation/de-activation set
425 */
426//void
427//set_nodemask_bit(uint64_t *nodemask, uint32_t node_id)
428void
429set_nodemask_bit(uint8_t* nodemask, uint32_t node_id, int val)
430{
431 int index = 0;
432 uint8_t *temp_mask;
433
434 index = (int) node_id / 8;
435 temp_mask = nodemask + index;
436 node_id = node_id - (index * 8);
437 if (val)
438 *temp_mask |= (1ULL << node_id);
439 else
440 *temp_mask &= ~(1ULL << node_id);
441}
442
443/**
444 * check_nodemask_bit:
445 *
446 * @node_id[in]: node id to be set in the mask
447 *
448 * Check if a bit in the nodemask corresponding to a
449 * node id is set.
450 *
451 * return 1 if the bit is set. 0 if the bit is cleared.
452 */
453int
454get_nodemask_bit(uint8_t* nodemask, uint32_t node_id) {
455 int index = 0;
456 uint8_t *temp_mask;
457
458 index = (int) node_id / 8;
459 temp_mask = nodemask + index;
460 node_id = node_id - (index * 8);
461 return *temp_mask & (1ULL << node_id);
462
463}
464/**
465* nodemask_isvalid - Check if a nodemask is valid after
466* calculating the de-activation set.
467*
468* @nodemask[in]: The nodemask to be checked.
469*
470* Returns true if valid.
471*/
472bool nodemask_isvalid(uint8_t* nodemask) {
473 uint32_t i;
474 for (i = 0; i <= ms_info.mi_maxid; i++) {
475 if (get_nodemask_bit(nodemask, i))
476 return true;
477 }
478
479 return false;
480}
481
482#ifndef _MIC_SCIF_
483/*
484 * micscif_send_rmnode_msg:
485 *
486 * @mask: Bitmask of nodes in the deactivation set.
487 * @node: Destination node for a deactivation set.
488 * @flags: Type of deactivation set i.e. Power Management,
489 * RAS, Maintenance Mode etc.
490 * @orig_node: The node which triggered this remove node message.
491 *
492 * Sends a deactivation request to the valid nodes not included in the
493 * deactivation set from the Host and waits for a response.
494 * Returns the response mask received from the node.
495 */
496uint64_t micscif_send_pm_rmnode_msg(int node, uint64_t nodemask_addr,
497 uint64_t nodemask_size, int orig_node) {
498
499 uint64_t ret;
500 struct nodemsg notif_msg;
501 struct micscif_dev *dev = &scif_dev[node];
502
503 /*
504 * Send remove node msg only to running nodes.
505 * An idle node need not know about another _lost_ node
506 * until it wakes up. When it does, it will request the
507 * host to wake up the _lost_ node to which the host will
508 * respond with a NACK
509 */
510
511 if (SCIFDEV_RUNNING != dev->sd_state)
512 return -ENODEV;
513
514 notif_msg.uop = SCIF_NODE_REMOVE;
515 notif_msg.src.node = ms_info.mi_nodeid;
516 notif_msg.dst.node = node;
517 notif_msg.payload[0] = nodemask_addr;
518 notif_msg.payload[1] = DISCONN_TYPE_POWER_MGMT;
519 notif_msg.payload[1] |= (nodemask_size << 32);
520 notif_msg.payload[2] = atomic_long_read(&ms_info.mi_unique_msgid);
521 notif_msg.payload[3] = orig_node;
522 /* Send the request to remove a set of nodes */
523 pr_debug("Send PM rmnode msg for node %d to node %d\n", orig_node, node);
524 ret = micscif_nodeqp_send(dev, &notif_msg, NULL);
525
526 return ret;
527}
528
529uint64_t micscif_send_lost_node_rmnode_msg(int node, int orig_node) {
530 uint64_t ret;
531 struct nodemsg notif_msg;
532 struct micscif_dev *dev = &scif_dev[node];
533
534 /*
535 * Send remove node msg only to running nodes.
536 * An idle node need not know about another _lost_ node
537 * until it wakes up. When it does, it will request the
538 * host to wake up the _lost_ node to which the host will
539 * respond with a NACK
540 */
541 if (SCIFDEV_RUNNING != dev->sd_state)
542 return -ENODEV;
543
544 micscif_inc_node_refcnt(dev, 1);
545 notif_msg.uop = SCIF_NODE_REMOVE;
546 notif_msg.src.node = ms_info.mi_nodeid;
547 notif_msg.dst.node = node;
548 notif_msg.payload[0] = orig_node;
549 notif_msg.payload[1] = DISCONN_TYPE_LOST_NODE;
550 notif_msg.payload[3] = orig_node;
551 /* Send the request to remove a set of nodes */
552 ret = micscif_nodeqp_send(dev, &notif_msg, NULL);
553 micscif_dec_node_refcnt(dev, 1);
554
555 return ret;
556}
557
558/*
559 * micpm_nodemask_uninit:
560 * @node - node to uninitalize
561 *
562 * Deallocate memory for per-card nodemask buffer
563*/
564void
565micpm_nodemask_uninit(mic_ctx_t* mic_ctx)
566{
567 if (mic_ctx && mic_ctx->micpm_ctx.nodemask.va) {
568 mic_ctx_unmap_single(mic_ctx, mic_ctx->micpm_ctx.nodemask.pa,
569 mic_ctx->micpm_ctx.nodemask.len);
570 kfree(mic_ctx->micpm_ctx.nodemask.va);
571 }
572}
573
574/*
575 * micpm_nodemask_init:
576 * @num_devs - no of scif nodes including the host
577 * @node - node to initialize
578 *
579 * Allocate memory for per-card nodemask buffer
580*/
581int
582micpm_nodemask_init(uint32_t num_devs, mic_ctx_t* mic_ctx)
583{
584 if (!mic_ctx)
585 return 0;
586
587 mic_ctx->micpm_ctx.nodemask.len = ((int) (num_devs / 8) +
588 ((num_devs % 8) ? 1 : 0));
589 mic_ctx->micpm_ctx.nodemask.va = (uint8_t *)
590 kzalloc(mic_ctx->micpm_ctx.nodemask.len, GFP_KERNEL);
591
592 if (!mic_ctx->micpm_ctx.nodemask.va) {
593 PM_DEBUG("Error allocating nodemask buffer\n");
594 return -ENOMEM;
595 }
596
597 mic_ctx->micpm_ctx.nodemask.pa = mic_ctx_map_single(mic_ctx,
598 mic_ctx->micpm_ctx.nodemask.va,
599 mic_ctx->micpm_ctx.nodemask.len);
600
601 if(mic_map_error(mic_ctx->micpm_ctx.nodemask.pa)) {
602 PM_PRINT("Error Mapping nodemask buffer\n");
603 kfree(mic_ctx->micpm_ctx.nodemask.va);
604 }
605 return 0;
606}
607
608/**
609 * micpm_disconn_uninit:
610 * @num_devs - no of scif nodes including host
611 * Note - can not use ms_info.mi_total(total no of scif nodes) as it is updated after the driver load is complete
612 *
613 * Reset/re-initialize data structures needed for PM disconnection. This is necessary everytime the board is reset.
614 * Since host(node 0)represents one of the node in network, it is necessary to clear dependency of host with the given node
615 */
616int
617micpm_disconn_uninit(uint32_t num_devs)
618{
619 uint32_t i;
620 uint32_t status = 0;
621
622 /*
623 * ms_info.mi_total is updated after the driver load is complete
624 * switching back to static allocation of max nodes
625 */
626
627 if (ms_info.mi_depmtrx) {
628
629 for (i = 0; i < (int)num_devs; i++) {
630 if (ms_info.mi_depmtrx[i]) {
631 kfree(ms_info.mi_depmtrx[i]);
632 }
633 }
634 kfree(ms_info.mi_depmtrx);
635 }
636
637 if (mic_data.dd_pm.nodemask)
638 kfree(mic_data.dd_pm.nodemask);
639
640 return status;
641}
642
643/**
644 * micpm_disconn_init:
645 * @num_devs - no of scif nodes including host
646 * Note - can not use ms_info.mi_total(total no of scif nodes) as it is updated after the driver load is complete
647 *
648 * Allocate memory for dependency graph. Initialize dependencies for the node.
649 * The memory allocated is based on the no of devices present during driver load.
650 */
651int
652micpm_disconn_init(uint32_t num_devs)
653{
654 uint32_t i;
655 uint32_t status = 0;
656 mic_ctx_t *mic_ctx;
657
658 if (ms_info.mi_depmtrx)
659 return status;
660
661 ms_info.mi_depmtrx = (uint32_t**)kzalloc(sizeof(uint32_t*) * num_devs, GFP_KERNEL);
662 if (!ms_info.mi_depmtrx) {
663 pr_debug("dependency graph initialization failed\n");
664 status = -ENOMEM;
665 goto exit;
666 }
667
668 for (i = 0; i < (int)num_devs; i++) {
669 ms_info.mi_depmtrx[i] = (uint32_t*)kzalloc(sizeof(uint32_t) * num_devs, GFP_KERNEL);
670 if (!ms_info.mi_depmtrx[i]) {
671 micpm_disconn_uninit(num_devs);
672 pr_debug("dependency graph initialization failed\n");
673 status = -ENOMEM;
674 goto exit;
675 }
676 }
677 init_waitqueue_head(&ms_info.mi_disconn_wq);
678 atomic_long_set(&ms_info.mi_unique_msgid, 0);
679
680 //In Windows, this code is executed during micpm_probe
681 for(i = 0; i < (num_devs - 1); i++) {
682 mic_ctx = get_per_dev_ctx(i);
683 status = micpm_nodemask_init(num_devs, mic_ctx);
684 if (status)
685 goto exit;
686 }
687
688 /* Set up a nodemask buffer for Host scif node in a common pm_ctx */
689 mic_data.dd_pm.nodemask_len = ((int) (num_devs / 8) +
690 ((num_devs % 8) ? 1 : 0));
691 mic_data.dd_pm.nodemask = (uint8_t *)
692 kzalloc(mic_data.dd_pm.nodemask_len, GFP_KERNEL);
693
694 if (!mic_data.dd_pm.nodemask) {
695 PM_DEBUG("Error allocating nodemask buffer\n");
696 status = -ENOMEM;
697 goto exit;
698 }
699
700exit:
701 return status;
702}
703
704/**
705 * micscif_set_nodedep:
706 *
707 * @src_node: node which is creating dependency.
708 * @dst_node: node on which dependency is being created
709 *
710 * sets the given value in dependency graph for src_node -> dst_node
711 */
712void
713micscif_set_nodedep(uint32_t src_node, uint32_t dst_node, enum dependency_state state)
714{
715 /* We dont need to lock dependency graph while updating
716 * as every node will modify its own row
717 */
718 if (ms_info.mi_depmtrx)
719 ms_info.mi_depmtrx[src_node][dst_node] = state;
720}
721
722/**
723 * micscif_get_nodedep:
724 *
725 * @src_node: node which has/has not created dependency.
726 * @dst_node: node on which dependency was/was not created
727 *
728 * gets the current value in dependency graph for src_node -> dst_node
729 */
730enum dependency_state
731micscif_get_nodedep(uint32_t src_node, uint32_t dst_node)
732{
733 enum dependency_state state = DEP_STATE_NOT_DEPENDENT;
734 if (ms_info.mi_depmtrx)
735 state = ms_info.mi_depmtrx[src_node][dst_node];
736 return state;
737}
738
739/**
740 * init_depgraph_stack:
741 *
742 * @stack_ptr: list head.
743 *
744 * Initialize linked list to be used as stack
745 */
746int
747init_depgraph_stack(struct list_head *stack_ptr)
748{
749 int status = 0;
750
751 if (!stack_ptr) {
752 pr_debug("%s argument stack_ptr is invalid\n", __func__);
753 status = -EINVAL;
754 goto exit;
755 }
756 /* Initialize stack */
757 INIT_LIST_HEAD(stack_ptr);
758
759exit:
760 return status;
761}
762
763/**
764 * uninit_depgraph_stack:
765 *
766 * @stack_ptr: list head for linked list(stack).
767 *
768 * Empty stack(linked list). Pop all the nodes left in the stack.
769 */
770int
771uninit_depgraph_stack(struct list_head *stack_ptr)
772{
773 int status = 0;
774 uint32_t node_id;
775 if (!stack_ptr) {
776 pr_debug("%s argument stack_ptr is invalid\n", __func__);
777 status = -EINVAL;
778 goto exit;
779 }
780
781 /* pop all the nodes left in the stack */
782 while (!is_stack_empty(stack_ptr)) {
783 status = stack_pop_node(stack_ptr, &node_id);
784 if (status) {
785 pr_debug("%s error while cleaning up depgraph stack\n", __func__);
786 status = -EINVAL;
787 goto exit;
788 }
789 }
790
791exit:
792 return status;
793}
794
795/**
796 * is_stack_empty:
797 *
798 * @stack_ptr: list head for linked list(stack).
799 *
800 * returns true if the stack is empty.
801 */
802int
803is_stack_empty(struct list_head *stack_ptr)
804{
805 if(list_empty(stack_ptr)) {
806 return 1;
807 }
808 return 0;
809}
810
811/**
812 * stack_push_node:
813 *
814 * @stack_ptr[in]: list head for linked list(stack).
815 * @node_id[in]: node id to be pushed
816 *
817 * Push node in to the stack i.e. create node and add it at the start of linked list
818 */
819int
820stack_push_node(struct list_head *stack_ptr, uint32_t node_id)
821{
822 int status = 0;
823 struct stack_node *datanode = NULL;
824
825 datanode = kmalloc(sizeof(struct stack_node), GFP_KERNEL);
826 if (!datanode) {
827 pr_debug("%s error allocating memory to stack node.\n", __func__);
828 status = -ENOMEM;
829 goto exit;
830 }
831
832 datanode->node_id = node_id;
833 list_add(&datanode->next, stack_ptr);
834exit:
835 return status;
836}
837
838/**
839 * stack_pop_node:
840 *
841 * @stack_ptr[in]: list head for linked list(stack).
842 * @node_id[out]: pointer to the node id to be popped
843 *
844 * Pop node from the stack i.e. delete first entry of linked list and return its data.
845 */
846int
847stack_pop_node(struct list_head *stack_ptr, uint32_t *node_id)
848{
849 int status = 0;
850 struct stack_node *datanode = NULL;
851
852 if(is_stack_empty(stack_ptr)) {
853 pr_debug("%s stack found empty when tried to pop\n", __func__);
854 status = -EFAULT;
855 goto exit;
856 }
857
858 datanode = list_first_entry(stack_ptr, struct stack_node, next);
859 if (!datanode) {
860 pr_debug("%s Unable to pop from stack\n", __func__);
861 status = -EFAULT;
862 goto exit;
863 }
864 *node_id = datanode->node_id;
865
866 list_del(&datanode->next);
867 if (datanode) {
868 kfree(datanode);
869 }
870
871exit:
872 return status;
873}
874
875/**
876 * micscif_get_activeset:
877 *
878 * @node_id[in]: source node id.
879 * @nodemask[out]: bitmask of nodes present in activation set
880 *
881 * Algorithm to find out activation set for the given source node. Activation set is used to re-connect node into
882 * the scif network.
883 */
884int
885micscif_get_activeset(uint32_t node_id, uint8_t *nodemask)
886{
887 int status = 0;
888 uint32_t i = 0;
889 struct list_head stack;
890 uint8_t visited[128] = {0}; // 128 is max number of nodes.
891 uint32_t num_nodes = ms_info.mi_maxid + 1;
892 mic_ctx_t *mic_ctx;
893
894 if (!ms_info.mi_depmtrx) {
895 status = -EINVAL;
896 goto exit;
897 }
898
899 status = init_depgraph_stack(&stack);
900 if (status) {
901 pr_debug("%s failed to initilize depgraph stack\n", __func__);
902 goto exit;
903 }
904
905 status = stack_push_node(&stack, node_id);
906 if (status) {
907 pr_debug("%s error while running activation set algorithm\n", __func__);
908 goto exit;
909 }
910
911 /* mark node visited to avoid repetition of the algorithm for the same node */
912 visited[node_id] = 1;
913
914 while (!is_stack_empty(&stack)) {
915 status = stack_pop_node(&stack, &node_id);
916 if (status) {
917 pr_debug("%s error while running activation set algorithm\n", __func__);
918 goto exit;
919 }
920
921 /* include node_id in the activation set*/
922 set_nodemask_bit(nodemask, node_id, 1);
923
924 for (i = 0; i < num_nodes; i++) {
925 /* check if node has dependency on any node 'i' which is also disconnected at this time*/
926 if ((!visited[i]) && (ms_info.mi_depmtrx[node_id][i] == DEP_STATE_DISCONNECTED)) {
927 visited[i] = 1;
928 if (i == 0)
929 continue;
930 mic_ctx = get_per_dev_ctx(i - 1);
931 if ((mic_ctx->micpm_ctx.idle_state == PM_IDLE_STATE_PC3) ||
932 (mic_ctx->micpm_ctx.idle_state == PM_IDLE_STATE_PC6)) {
933 status = stack_push_node(&stack, i);
934 if (status) {
935 pr_debug("%s error while running activation set algorithm\n", __func__);
936 goto exit;
937 }
938 }
939 }
940 }
941 } /* end of while (!is_stack_empty(&stack)) */
942exit:
943 uninit_depgraph_stack(&stack);
944 return status;
945}
946
947/**
948 * micscif_get_minimal_deactiveset:
949 *
950 * @node_id[in]: source node id.
951 * @nodemask[out]: bitmask of nodes present in de-activation set
952 * @visited[in/out]: information of which nodes are already visited in de-activation set algorithm
953 *
954 * Algorithm to find out minimum/must de-activation set for the given source node. This method is part of and used by
955 * micscif_get_deactiveset.
956 */
957int micscif_get_minimal_deactiveset(uint32_t node_id, uint8_t *nodemask, uint8_t *visited)
958{
959 int status = 0;
960 uint32_t i = 0;
961 struct list_head stack;
962 uint32_t num_nodes = ms_info.mi_maxid + 1;
963
964 if (!ms_info.mi_depmtrx) {
965 status = -EINVAL;
966 goto exit;
967 }
968
969 status = init_depgraph_stack(&stack);
970 if (!visited) {
971 pr_debug("%s invalid parameter visited", __func__);
972 status = -EINVAL;
973 goto exit_pop;
974 }
975
976 if (status) {
977 pr_debug("%s failed to initilize depgraph stack\n", __func__);
978 goto exit_pop;
979 }
980
981 status = stack_push_node(&stack, node_id);
982 if (status) {
983 pr_debug("%s error while running de-activation set algorithm\n", __func__);
984 goto exit_pop;
985 }
986
987 /* mark node visited to avoid repetition of the algorithm for the same node */
988 visited[node_id] = 1;
989
990 while (!is_stack_empty(&stack)) {
991
992 status = stack_pop_node(&stack, &node_id);
993 if (status) {
994 pr_debug("%s error while running de-activation set algorithm\n", __func__);
995 goto exit_pop;
996 }
997
998 /* include node_id in the activation set*/
999 set_nodemask_bit(nodemask, node_id, 1);
1000
1001 for (i = 0; i < num_nodes; i++) {
1002 if (!visited[i]) {
1003 if (ms_info.mi_depmtrx[i][node_id] == DEP_STATE_DEPENDENT) {
1004 /* The algorithm terminates, if we find any dependent node active */
1005 status = -EOPNOTSUPP;
1006 goto exit_pop;
1007 } else if(ms_info.mi_depmtrx[i][node_id] == DEP_STATE_DISCONNECT_READY) {
1008 /* node is dependent but ready to get disconnected */
1009 visited[i] = 1;
1010 status = stack_push_node(&stack, i);
1011 if (status) {
1012 pr_debug("%s error while running de-activation set algorithm\n", __func__);
1013 goto exit_pop;
1014 }
1015 }
1016 }
1017 }
1018 }/*end of while(!is_stack_empty(&stack))*/
1019
1020exit_pop:
1021 while (!is_stack_empty(&stack)) {
1022 status = stack_pop_node(&stack, &node_id);
1023 if (status) {
1024 pr_debug("%s error while running activation set algorithm\n", __func__);
1025 break;
1026 }
1027 if (visited)
1028 visited[node_id] = 0;
1029 }
1030exit:
1031 return status;
1032}
1033
1034/**
1035 * micscif_get_deactiveset:
1036 *
1037 * @node_id[in]: source node id.
1038 * @nodemask[out]: bitmask of nodes present in de-activation set
1039 * @max_disconn: flag to restrict de-activation set algoritthm to minimum/must set.
1040 * True value indicates maximum de-activation set
1041 *
1042 * Algorithm to find out de-activation set for the given source node. De-activation set is used to disconnect node into
1043 * the scif network. The algorithm can find out maximum possible de-activation set(required in situations like
1044 * power management)if the max_possible flag is set.
1045 */
1046int
1047micscif_get_deactiveset(uint32_t node_id, uint8_t *nodemask, int max_disconn)
1048{
1049 int status = 0;
1050 uint32_t i = 0;
1051 struct list_head stack;
1052 uint8_t *visited = NULL;
1053 uint8_t cont_next_step = 0;
1054 uint32_t num_nodes = ms_info.mi_maxid + 1;
1055 mic_ctx_t *mic_ctx;
1056
1057 if (!ms_info.mi_depmtrx) {
1058 status = -EINVAL;
1059 goto exit;
1060 }
1061
1062 status = init_depgraph_stack(&stack);
1063 if (status) {
1064 pr_debug("%s failed to initilize depgraph stack\n", __func__);
1065 goto exit;
1066 }
1067
1068 visited = kzalloc(sizeof(uint8_t) * num_nodes, GFP_KERNEL);
1069 if (!visited) {
1070 pr_debug("%s failed to allocated memory for visited array", __func__);
1071 status = -ENOMEM;
1072 goto exit;
1073 }
1074
1075 status = stack_push_node(&stack, node_id);
1076 if (status) {
1077 pr_debug("%s error while running de-activation set algorithm\n", __func__);
1078 goto exit;
1079 }
1080
1081 while (!is_stack_empty(&stack)) {
1082
1083 status = stack_pop_node(&stack, &node_id);
1084 if (status) {
1085 pr_debug("%s error while running de-activation set algorithm\n", __func__);
1086 goto exit;
1087 }
1088
1089 /* check if we want to find out maximum possible de-activation set */
1090 if (max_disconn) {
1091 cont_next_step = 1;
1092 }
1093
1094 if (!visited[node_id]) {
1095 status = micscif_get_minimal_deactiveset(node_id, nodemask, visited);
1096 if (status) {
1097 if (status == -EOPNOTSUPP) {
1098 pr_debug("%s No deactivation set found for node %d", __func__, node_id);
1099 cont_next_step = 0;
1100 }
1101 else {
1102 pr_debug("%s Failed to calculate deactivation set", __func__);
1103 goto exit;
1104 }
1105 }
1106
1107 } /* end for if (!visited[node_id]) */
1108
1109 if (cont_next_step) {
1110 for (i = 0; i < num_nodes; i++) {
1111 /* check if we can put more nodes 'i' in de-activation set if this node(dependent node)
1112 * is de-activating
1113 */
1114 if ((!visited[i]) &&
1115 (ms_info.mi_depmtrx[node_id][i] == DEP_STATE_DISCONNECT_READY)) {
1116 if (i == 0)
1117 continue;
1118 mic_ctx = get_per_dev_ctx(i - 1);
1119 if (mic_ctx->micpm_ctx.idle_state ==
1120 PM_IDLE_STATE_PC3_READY) {
1121 /* This node might be able to get into deactivation set */
1122 status = stack_push_node(&stack, i);
1123 if (status) {
1124 pr_debug("%s error while running de-activation set algorithm\n", __func__);
1125 goto exit;
1126 }
1127 }
1128 }
1129 }
1130 }
1131 } /* end for while (!is_stack_empty(&stack)) */
1132
1133 if (!nodemask_isvalid(nodemask)) {
1134 pr_debug("%s No deactivation set found for node %d",
1135 __func__, node_id);
1136 status = -EOPNOTSUPP;
1137 }
1138exit:
1139 if (visited) {
1140 kfree(visited);
1141 }
1142 uninit_depgraph_stack(&stack);
1143 return status;
1144}
1145
1146/* micscif_update_p2p_state:
1147 *
1148 * Update the p2p_disc_state of peer node peer_id in the p2p list of node node_id.
1149 *
1150 * @node_id: The node id whose p2p list needs to be updated.
1151 * @peer_id: The node id in the p2p list of the node_id that will get updated.
1152 * @scif_state: The state to be updated to.
1153 *
1154 */
1155void micscif_update_p2p_state(uint32_t node_id, uint32_t peer_id, enum scif_state state) {
1156
1157 struct micscif_dev *dev;
1158 struct list_head *pos, *tmp;
1159 struct scif_p2p_info *p2p;
1160
1161 dev = &scif_dev[node_id];
1162 if (!list_empty(&dev->sd_p2p)) {
1163 list_for_each_safe(pos, tmp, &dev->sd_p2p) {
1164 p2p = list_entry(pos, struct scif_p2p_info,
1165 ppi_list);
1166 if(p2p->ppi_peer_id == peer_id) {
1167 p2p->ppi_disc_state = state;
1168 break;
1169 }
1170 }
1171 }
1172}
1173
1174/* micscif_p2p_node_exists: Check if a node exists in the
1175 * list of nodes that have been sent an rmnode message.
1176 *
1177 * node_list: The list that contains the nodes that has been
1178 * sent the rmnode message for this transaction.
1179 * node_id: the node to be searched for.
1180 *
1181 * returns: true of the node exists.False otherwise
1182 */
1183bool micscif_rmnode_msg_sent(struct list_head *node_list, uint32_t node_id) {
1184
1185 struct list_head *pos1, *tmp1;
1186 struct stack_node *added_node;
1187
1188 if (!list_empty(node_list)) {
1189 list_for_each_safe(pos1, tmp1, node_list) {
1190 added_node = list_entry(pos1, struct stack_node, next);
1191 if(added_node->node_id == node_id)
1192 return true;
1193 }
1194 }
1195 return false;
1196}
1197
1198/**
1199 * micscif_execute_disconnecte: Perform PM disconnection of a node
1200 * with its neighboring nodes.
1201 *
1202 * node_id: The node to be disconnected.
1203 * nodemask: Mask containing the list of nodes (including node_id)
1204 * to be disconnected.
1205 * node_list: List of nodes that received the disconnection message.
1206 */
1207int micscif_execute_disconnect(uint32_t node_id,
1208 uint8_t *nodemask,
1209 struct list_head *node_list)
1210{
1211 uint32_t status = 0;
1212 int ret;
1213 uint64_t msg_cnt = 0;
1214 uint32_t i = 0;
1215 int pending_wakeups = 0;
1216 mic_ctx_t *send_rmnode_ctx;
1217 uint32_t node;
1218 mic_ctx_t *mic_ctx = get_per_dev_ctx(node_id - 1);
1219 struct scif_p2p_info *p2p;
1220 struct list_head *pos, *tmp;
1221 struct micscif_dev *dev;
1222
1223
1224 /* Always send rmnode msg to SCIF_HOST_NODE */
1225 memcpy(mic_data.dd_pm.nodemask, nodemask,
1226 mic_data.dd_pm.nodemask_len);
1227 ret = (int) micscif_send_pm_rmnode_msg(SCIF_HOST_NODE, 0, mic_data.dd_pm.nodemask_len,
1228 node_id);
1229 /* Add this node to msg list. */
1230 if(!ret) {
1231 msg_cnt++;
1232 stack_push_node(node_list, SCIF_HOST_NODE);
1233 }
1234
1235 if((ret == 0)||(ret == -ENODEV)) {
1236 status = 0;
1237 }
1238
1239 /* For each node in the nodemask, traverse its p2p list
1240 * and send rmnode_msg to those nodes 1) That are not also
1241 * in the node mask and 2) That have not been already sent
1242 * rmnode messages in this transaction and 3) That have
1243 * their disconnection state as RUNNING.
1244 */
1245 for (i = 0; i <= ms_info.mi_maxid; i++) {
1246 /* verify if the node is present in deactivation set */
1247 if (!get_nodemask_bit(nodemask, i))
1248 continue;
1249
1250 /* Get to the p2p list of this node */
1251 dev = &scif_dev[i];
1252 list_for_each_safe(pos, tmp, &dev->sd_p2p) {
1253 p2p = list_entry(pos, struct scif_p2p_info,
1254 ppi_list);
1255
1256 if (get_nodemask_bit(nodemask, p2p->ppi_peer_id))
1257 continue;
1258 if (p2p->ppi_disc_state == SCIFDEV_SLEEPING)
1259 continue;
1260
1261 if(micscif_rmnode_msg_sent(node_list, p2p->ppi_peer_id))
1262 continue;
1263 send_rmnode_ctx = get_per_dev_ctx(p2p->ppi_peer_id - 1);
1264 if (!send_rmnode_ctx->micpm_ctx.nodemask.va) {
1265 status = -EINVAL;
1266 goto list_cleanup;
1267 }
1268
1269 memcpy(send_rmnode_ctx->micpm_ctx.nodemask.va, nodemask,
1270 send_rmnode_ctx->micpm_ctx.nodemask.len);
1271 ret = (int) micscif_send_pm_rmnode_msg(p2p->ppi_peer_id,
1272 send_rmnode_ctx->micpm_ctx.nodemask.pa,
1273 send_rmnode_ctx->micpm_ctx.nodemask.len,node_id);
1274
1275 /* Add this node to msg list. */
1276 if(!ret) {
1277 msg_cnt++;
1278 stack_push_node(node_list, p2p->ppi_peer_id);
1279 }
1280
1281 if((ret == 0)||(ret == -ENODEV)) {
1282 status = 0;
1283 }
1284 }
1285 }
1286
1287 ret = wait_event_timeout(ms_info.mi_disconn_wq,
1288 (atomic_read(&mic_ctx->disconn_rescnt) == msg_cnt) ||
1289 (pending_wakeups = atomic_read(&mic_data.dd_pm.wakeup_in_progress)),
1290 NODE_ALIVE_TIMEOUT);
1291 if ((!ret) || (atomic_read(&mic_ctx->disconn_rescnt) != msg_cnt)
1292 || (ms_info.mi_disconnect_status == OP_FAILED)) {
1293 pr_debug("SCIF disconnect failed. "
1294 "remove_node messages sent: = %llu "
1295 "remove_node acks received: %d "
1296 "Pending wakeups: %d ret = %d\n", msg_cnt,
1297 atomic_read(&mic_ctx->disconn_rescnt),
1298 pending_wakeups, ret);
1299
1300 status = -EAGAIN;
1301 goto list_cleanup;
1302 }
1303 return status;
1304
1305list_cleanup:
1306 while (!is_stack_empty(node_list))
1307 stack_pop_node(node_list, &node);
1308 return status;
1309}
1310
1311/**
1312 * micscif_node_disconnect:
1313 *
1314 * @node_id[in]: source node id.
1315 * @nodemask[out]: bitmask of nodes that have to be disconnected together.
1316 * it represents node_id
1317 * @disconn_type[in]: flag to identify disconnection type. (for example - power mgmt, lost node, maintenance mode etc)
1318 *
1319 * Method responsible for disconnecting node from the scif network. considers dependencies with other node.
1320 * finds out deactivation set. Sends node queue pair messages to all the scif nodes outside deactivation set
1321 * returns error if node can not be disconnected from the network.
1322 */
1323int micscif_disconnect_node(uint32_t node_id, uint8_t *nodemask, enum disconn_type type)
1324{
1325 uint32_t status = 0;
1326 int ret;
1327 uint64_t msg_cnt = 0;
1328 uint32_t i = 0;
1329 mic_ctx_t *mic_ctx = 0;
1330 struct list_head node_list;
1331 uint32_t node;
1332
1333 if (!node_id)
1334 return -EINVAL;
1335
1336 mic_ctx = get_per_dev_ctx(node_id - 1);
1337
1338 if (!mic_ctx)
1339 return -EINVAL;
1340
1341 switch(type) {
1342 case DISCONN_TYPE_POWER_MGMT:
1343 {
1344 if (!nodemask)
1345 return -EINVAL;
1346
1347 atomic_long_add(1, &ms_info.mi_unique_msgid);
1348 atomic_set(&mic_ctx->disconn_rescnt, 0);
1349 ms_info.mi_disconnect_status = OP_IN_PROGRESS;
1350 INIT_LIST_HEAD(&node_list);
1351
1352 status = micscif_execute_disconnect(node_id,
1353 nodemask, &node_list);
1354 if (status)
1355 return status;
1356
1357 /* Reset unique msg_id */
1358 atomic_long_set(&ms_info.mi_unique_msgid, 0);
1359
1360 while (!is_stack_empty(&node_list)) {
1361 status = stack_pop_node(&node_list, &node);
1362 if (status)
1363 break;
1364
1365 for (i = 0; i <= ms_info.mi_maxid; i++) {
1366 if (!get_nodemask_bit(nodemask, i))
1367 continue;
1368 micscif_update_p2p_state(i, node, SCIFDEV_SLEEPING);
1369 }
1370 }
1371 break;
1372 }
1373 case DISCONN_TYPE_LOST_NODE:
1374 {
1375 atomic_long_add(1, &ms_info.mi_unique_msgid);
1376 atomic_set(&mic_ctx->disconn_rescnt, 0);
1377
1378 for (i = 0; ((i <= ms_info.mi_maxid) && (i != node_id)); i++) {
1379 ret = (int)micscif_send_lost_node_rmnode_msg(i, node_id);
1380 if(!ret)
1381 msg_cnt++;
1382 if((ret == 0)||(ret == -ENODEV)) {
1383 status = 0;
1384 }
1385 }
1386
1387 ret = wait_event_timeout(ms_info.mi_disconn_wq,
1388 (atomic_read(&mic_ctx->disconn_rescnt) == msg_cnt),
1389 NODE_ALIVE_TIMEOUT);
1390 break;
1391 }
1392 default:
1393 status = -EINVAL;
1394 }
1395
1396 return status;
1397}
1398
1399/**
1400 * micscif_node_connect:
1401 *
1402 * @node_id[in]: node to wakeup.
1403 * @bool get_ref[in]: Also get node reference after wakeup by incrementing the PM reference count
1404 *
1405 * Method responsible for connecting node into the scif network. considers dependencies with other node.
1406 * finds out activation set. connects all the depenendent nodes in the activation set
1407 * returns error if node can not be connected from the network.
1408 */
1409int
1410micscif_connect_node(uint32_t node_id, bool get_ref)
1411{
1412 return do_idlestate_exit(get_per_dev_ctx(node_id - 1), get_ref);
1413}
1414
1415uint64_t micscif_send_node_alive(int node)
1416{
1417 struct nodemsg alive_msg;
1418 struct micscif_dev *dev = &scif_dev[node];
1419 int err;
1420
1421 alive_msg.uop = SCIF_NODE_ALIVE;
1422 alive_msg.src.node = ms_info.mi_nodeid;
1423 alive_msg.dst.node = node;
1424 pr_debug("node alive msg sent to node %d\n", node);
1425 micscif_inc_node_refcnt(dev, 1);
1426 err = micscif_nodeqp_send(dev, &alive_msg, NULL);
1427 micscif_dec_node_refcnt(dev, 1);
1428 return err;
1429}
1430
1431int micscif_handle_lostnode(uint32_t node_id)
1432{
1433 mic_ctx_t *mic_ctx;
1434 uint32_t status = -EOPNOTSUPP;
1435#ifdef MM_HANDLER_ENABLE
1436 uint8_t *mmio_va;
1437 sbox_scratch1_reg_t scratch1reg = {0};
1438#endif
1439
1440 printk("%s %d node %d\n", __func__, __LINE__, node_id);
1441 mic_ctx = get_per_dev_ctx(node_id - 1);
1442
1443 if (mic_ctx->state != MIC_ONLINE && mic_ctx->state != MIC_SHUTDOWN)
1444 return 0;
1445
1446 if (mic_crash_dump_enabled) {
1447 if (!(status = vmcore_create(mic_ctx)))
1448 printk("%s %d node %d ready for crash dump!\n",
1449 __func__, __LINE__, node_id);
1450 else
1451 printk(KERN_ERR "%s %d node %d crash dump failed status %d\n",
1452 __func__, __LINE__, node_id, status);
1453 }
1454
1455 mic_ctx->crash_count++;
1456 mutex_lock(&mic_ctx->state_lock);
1457 if (mic_ctx->state == MIC_ONLINE ||
1458 mic_ctx->state == MIC_SHUTDOWN)
1459 mic_setstate(mic_ctx, MIC_LOST);
1460 mutex_unlock(&mic_ctx->state_lock);
1461
1462 /* mpssd will handle core dump and reset/auto reboot */
1463 if (mic_crash_dump_enabled && !status)
1464 return status;
1465
1466 printk("%s %d stopping node %d to recover lost node!\n",
1467 __func__, __LINE__, node_id);
1468 status = adapter_stop_device(mic_ctx, 1, !RESET_REATTEMPT);
1469 wait_for_reset(mic_ctx);
1470
1471 if (!ms_info.mi_watchdog_auto_reboot) {
1472 printk("%s %d cannot boot node %d to recover lost node since auto_reboot is off\n",
1473 __func__, __LINE__, node_id);
1474 return status;
1475 }
1476
1477/* Disabling MM handler invocation till it is ready to handle errors
1478 * till then we just reboot the card
1479 */
1480#ifdef MM_HANDLER_ENABLE
1481 mmio_va = mic_ctx->mmio.va;
1482 scratch1reg.bits.status = FLASH_CMD_INVALID;
1483
1484 if(mic_ctx->bi_family == FAMILY_ABR) {
1485 printk("Node %d lost. Cannot recover in KNF\n", node_id);
1486 status = adapter_start_device(mic_ctx);
1487 return status;
1488 }
1489
1490 printk("Booting maintenance mode handler\n");
1491 status = set_card_usage_mode(mic_ctx, USAGE_MODE_MAINTENANCE, NULL, 0);
1492 if(status) {
1493 printk("Unable to boot maintenance mode\n");
1494 return status;
1495 }
1496
1497 status = send_flash_cmd(mic_ctx, RAS_CMD, NULL, 0);
1498 if(status) {
1499 printk("Unable to recover node\n");
1500 return status;
1501 }
1502 while(scratch1reg.bits.status != FLASH_CMD_COMPLETED) {
1503 ret = SBOX_READ(mmio_va, SBOX_SCRATCH1);
1504 scratch1reg.value = ret;
1505 msleep(1);
1506 i++;
1507 printk("Looping for status (time = %d ms)\n", i);
1508 if(i > NODE_ALIVE_TIMEOUT) {
1509 status = -ETIME;
1510 printk("Unable to recover node. Status bit is : %d\n",
1511 scratch1reg.bits.status);
1512 return status;
1513 }
1514
1515 }
1516#endif
1517 printk("%s %d booting node %d to recover lost node!\n",
1518 __func__, __LINE__, node_id);
1519 status = adapter_start_device(mic_ctx);
1520 return status;
1521}
1522
1523void micscif_watchdog_handler(struct work_struct *work)
1524{
1525 struct micscif_dev *dev =
1526 container_of(to_delayed_work(work),
1527 struct micscif_dev, sd_watchdog_work);
1528 struct _mic_ctx_t *mic_ctx;
1529 int i = dev->sd_node, err, ret;
1530
1531 mic_ctx = get_per_dev_ctx(i - 1);
1532
1533 switch (mic_ctx->sdbic1) {
1534 case SYSTEM_HALT:
1535 case SYSTEM_POWER_OFF:
1536 {
1537 adapter_stop_device(mic_ctx, 1, !RESET_REATTEMPT);
1538 wait_for_reset(mic_ctx);
1539 mic_ctx->sdbic1 = 0;
1540 break;
1541 }
1542 case SYSTEM_RESTART:
1543 {
1544 mic_setstate(mic_ctx, MIC_LOST);
1545 mic_ctx->sdbic1 = 0;
1546 break;
1547 }
1548 case SYSTEM_BOOTING:
1549 case SYSTEM_RUNNING:
1550#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0))
1551 case SYSTEM_SUSPEND_DISK:
1552#endif
1553 break;
1554 case 0xdead:
1555 if (mic_crash_dump_enabled)
1556 micscif_handle_lostnode(i);
1557 mic_ctx->sdbic1 = 0;
1558 break;
1559 default:
1560 break;
1561 }
1562
1563 switch (mic_ctx->state) {
1564 case MIC_ONLINE:
1565 break;
1566 case MIC_BOOT:
1567 goto restart_timer;
1568 case MIC_SHUTDOWN:
1569 case MIC_LOST:
1570 case MIC_READY:
1571 case MIC_NORESPONSE:
1572 case MIC_BOOTFAIL:
1573 case MIC_RESET:
1574 case MIC_RESETFAIL:
1575 case MIC_INVALID:
1576 return;
1577 }
1578
1579 if (!ms_info.mi_watchdog_enabled)
1580 return;
1581
1582 err = micpm_get_reference(mic_ctx, false);
1583 if (err == -EAGAIN) {
1584 goto restart_timer;
1585 } else if (err == -ENODEV) {
1586 micscif_handle_lostnode(i);
1587 goto restart_timer;
1588 }
1589
1590 if (1 != atomic_cmpxchg(&dev->sd_node_alive, 1, 0)) {
1591
1592 err = (int)(micscif_send_node_alive(i));
1593
1594 if (err) {
1595 micpm_put_reference(mic_ctx);
1596 goto restart_timer;
1597 }
1598
1599 ret = wait_event_timeout(dev->sd_watchdog_wq,
1600 (atomic_cmpxchg(&dev->sd_node_alive, 1, 0) == 1),
1601 NODE_ALIVE_TIMEOUT);
1602 if (!ret || err)
1603 micscif_handle_lostnode(i);
1604 }
1605 micpm_put_reference(mic_ctx);
1606
1607restart_timer:
1608 if (dev->sd_ln_wq)
1609 queue_delayed_work(dev->sd_ln_wq,
1610 &dev->sd_watchdog_work, NODE_ALIVE_TIMEOUT);
1611}
1612#else
1613
1614long micscif_suspend(uint8_t* nodemask) {
1615 long ret = 0;
1616 int i;
1617 struct micscif_dev *dev;
1618
1619 for (i = 0; i <= ms_info.mi_maxid; i++) {
1620 if (get_nodemask_bit(nodemask , i)) {
1621 dev = &scif_dev[i];
1622 if (SCIFDEV_RUNNING != dev->sd_state)
1623 continue;
1624
1625 ret = atomic_long_cmpxchg(
1626 &dev->scif_ref_cnt, 0, SCIF_NODE_IDLE);
1627 if (!ret || ret == SCIF_NODE_IDLE) {
1628 dev->sd_state = SCIFDEV_SLEEPING;
1629 ret = 0;
1630 }
1631 else {
1632 set_nodemask_bit(nodemask, i, 0);
1633 ret = EAGAIN;
1634 }
1635 }
1636 }
1637 return ret;
1638}
1639/*
1640 * scif_suspend_handler - SCIF tasks before transition to low power state.
1641 */
1642int micscif_suspend_handler(struct notifier_block *this,
1643 unsigned long event, void *ptr)
1644{
1645 int ret = 0;
1646#ifdef SCIF_ENABLE_PM
1647 int node = 0;
1648 int size;
1649 uint8_t *nodemask_buf;
1650
1651 size = ((int) ((ms_info.mi_maxid + 1) / 8) +
1652 (((ms_info.mi_maxid + 1) % 8) ? 1 : 0));
1653 nodemask_buf = (uint8_t*)kzalloc(size, GFP_ATOMIC);
1654 if(!nodemask_buf)
1655 return -ENOMEM;
1656
1657 for (node = 0; node <= ms_info.mi_maxid; node++) {
1658 if ((node != SCIF_HOST_NODE) && (node != ms_info.mi_nodeid))
1659 set_nodemask_bit(nodemask_buf, node, 1);
1660 }
1661
1662 if (micscif_suspend(nodemask_buf)){
1663 ret = -EBUSY;
1664 goto clean_up;
1665 }
1666
1667 dma_suspend(mic_dma_handle);
1668clean_up:
1669 kfree(nodemask_buf);
1670#endif
1671 return ret;
1672}
1673
1674/*
1675 * micscif_resume_handler - SCIF tasks after wake up from low power state.
1676 */
1677int micscif_resume_handler(struct notifier_block *this,
1678 unsigned long event, void *ptr)
1679{
1680#ifdef SCIF_ENABLE_PM
1681#ifdef _MIC_SCIF_
1682 queue_work(ms_info.mi_misc_wq, &ms_info.mi_misc_work);
1683#endif
1684 dma_resume(mic_dma_handle);
1685#endif
1686 return 0;
1687}
1688
1689/*
1690 * scif_fail_suspend_handler - SCIF tasks if a previous scif_suspend call has
1691 * failed since a low power state transition could not be completed.
1692 */
1693int micscif_fail_suspend_handler(struct notifier_block *this,
1694 unsigned long event, void *ptr)
1695{
1696/* Stub out function since it is an optimization that isn't working properly */
1697#if 0
1698#ifdef SCIF_ENABLE_PM
1699 int node = 0;
1700 long ret;
1701 struct micscif_dev *dev;
1702
1703 for (node = 0; node <= ms_info.mi_maxid; node++) {
1704 dev = &scif_dev[node];
1705 ret = atomic_long_cmpxchg(&dev->scif_ref_cnt, SCIF_NODE_IDLE, 0);
1706 if (ret != SCIF_NODE_IDLE)
1707 continue;
1708 if (SCIFDEV_SLEEPING == dev->sd_state)
1709 dev->sd_state = SCIFDEV_RUNNING;
1710 }
1711#endif
1712#endif
1713 return 0;
1714}
1715
1716void micscif_get_node_info(void)
1717{
1718 struct nodemsg msg;
1719 struct get_node_info node_info;
1720
1721 init_waitqueue_head(&node_info.wq);
1722 node_info.state = OP_IN_PROGRESS;
1723 micscif_inc_node_refcnt(&scif_dev[SCIF_HOST_NODE], 1);
1724 msg.uop = SCIF_GET_NODE_INFO;
1725 msg.src.node = ms_info.mi_nodeid;
1726 msg.dst.node = SCIF_HOST_NODE;
1727 msg.payload[3] = (uint64_t)&node_info;
1728
1729 if ((micscif_nodeqp_send(&scif_dev[SCIF_HOST_NODE], &msg, NULL)))
1730 goto done;
1731
1732 wait_event(node_info.wq, node_info.state != OP_IN_PROGRESS);
1733done:
1734 micscif_dec_node_refcnt(&scif_dev[SCIF_HOST_NODE], 1);
1735 /* Synchronize with the thread waking us up */
1736 mutex_lock(&ms_info.mi_conflock);
1737 mutex_unlock(&ms_info.mi_conflock);
1738 ;
1739}
1740#endif /* _MIC_SCIF_ */