1215976Sjmallett/***********************license start***************
2232812Sjmallett * Copyright (c) 2003-2010  Cavium Inc. (support@cavium.com). All rights
3215976Sjmallett * reserved.
4215976Sjmallett *
5215976Sjmallett *
6215976Sjmallett * Redistribution and use in source and binary forms, with or without
7215976Sjmallett * modification, are permitted provided that the following conditions are
8215976Sjmallett * met:
9215976Sjmallett *
10215976Sjmallett *   * Redistributions of source code must retain the above copyright
11215976Sjmallett *     notice, this list of conditions and the following disclaimer.
12215976Sjmallett *
13215976Sjmallett *   * Redistributions in binary form must reproduce the above
14215976Sjmallett *     copyright notice, this list of conditions and the following
15215976Sjmallett *     disclaimer in the documentation and/or other materials provided
16215976Sjmallett *     with the distribution.
17215976Sjmallett
18232812Sjmallett *   * Neither the name of Cavium Inc. nor the names of
19215976Sjmallett *     its contributors may be used to endorse or promote products
20215976Sjmallett *     derived from this software without specific prior written
21215976Sjmallett *     permission.
22215976Sjmallett
23215976Sjmallett * This Software, including technical data, may be subject to U.S. export  control
24215976Sjmallett * laws, including the U.S. Export Administration Act and its  associated
25215976Sjmallett * regulations, and may be subject to export or import  regulations in other
26215976Sjmallett * countries.
27215976Sjmallett
28215976Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30215976Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31215976Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32215976Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33215976Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34215976Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35215976Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36215976Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
37215976Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38215976Sjmallett ***********************license end**************************************/
39215976Sjmallett
40215976Sjmallett/**
41215976Sjmallett * @file
42215976Sjmallett *
43215976Sjmallett * Provides APIs for applications to register for hotplug. It also provides
44215976Sjmallett * APIs for requesting shutdown of a running target application.
45215976Sjmallett *
46215976Sjmallett * <hr>$Revision: $<hr>
47215976Sjmallett */
48215976Sjmallett
49215976Sjmallett#include "cvmx-app-hotplug.h"
50215976Sjmallett#include "cvmx-spinlock.h"
51232812Sjmallett#include "cvmx-debug.h"
52215976Sjmallett
53215976Sjmallett//#define DEBUG 1
54215976Sjmallett
55232812Sjmallettstatic cvmx_app_hotplug_global_t *hotplug_global_ptr = 0;
56232812Sjmallett
57215976Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_USER
58215976Sjmallett
59215976Sjmallettstatic CVMX_SHARED cvmx_spinlock_t cvmx_app_hotplug_sync_lock = { CVMX_SPINLOCK_UNLOCKED_VAL };
60215976Sjmallettstatic CVMX_SHARED cvmx_spinlock_t cvmx_app_hotplug_lock = { CVMX_SPINLOCK_UNLOCKED_VAL };
61215976Sjmallettstatic CVMX_SHARED cvmx_app_hotplug_info_t *cvmx_app_hotplug_info_ptr = NULL;
62215976Sjmallett
63215976Sjmallettstatic void __cvmx_app_hotplug_shutdown(int irq_number, uint64_t registers[32], void *user_arg);
64215976Sjmallettstatic void __cvmx_app_hotplug_sync(void);
65215976Sjmallettstatic void __cvmx_app_hotplug_reset(void);
66215976Sjmallett
67232812Sjmallett/* Declaring this array here is a compile time check to ensure that the
68232812Sjmallett   size of  cvmx_app_hotplug_info_t is 1024. If the size is not 1024
69232812Sjmallett   the size of the array will be -1 and this results in a compilation
70232812Sjmallett   error */
71232812Sjmallettchar __hotplug_info_check[(sizeof(cvmx_app_hotplug_info_t) == 1024) ? 1 : -1];
72215976Sjmallett/**
73215976Sjmallett * This routine registers an application for hotplug. It installs a handler for
74215976Sjmallett * any incoming shutdown request. It also registers a callback routine from the
75215976Sjmallett * application. This callback is invoked when the application receives a
76215976Sjmallett * shutdown notification.
77215976Sjmallett *
78215976Sjmallett * This routine only needs to be called once per application.
79215976Sjmallett *
80215976Sjmallett * @param fn      Callback routine from the application.
81215976Sjmallett * @param arg     Argument to the application callback routine.
82215976Sjmallett * @return        Return 0 on success, -1 on failure
83215976Sjmallett *
84215976Sjmallett */
85215976Sjmallettint cvmx_app_hotplug_register(void(*fn)(void*), void* arg)
86215976Sjmallett{
87215976Sjmallett    /* Find the list of applications launched by bootoct utility. */
88215976Sjmallett
89215976Sjmallett    if (!(cvmx_app_hotplug_info_ptr = cvmx_app_hotplug_get_info(cvmx_sysinfo_get()->core_mask)))
90215976Sjmallett    {
91215976Sjmallett        /* Application not launched by bootoct? */
92215976Sjmallett        printf("ERROR: cmvx_app_hotplug_register() failed\n");
93215976Sjmallett        return -1;
94215976Sjmallett    }
95215976Sjmallett
96215976Sjmallett    /* Register the callback */
97215976Sjmallett    cvmx_app_hotplug_info_ptr->data = CAST64(arg);
98215976Sjmallett    cvmx_app_hotplug_info_ptr->shutdown_callback = CAST64(fn);
99215976Sjmallett
100215976Sjmallett#ifdef DEBUG
101232812Sjmallett    printf("cvmx_app_hotplug_register(): coremask 0x%x valid %d\n",
102215976Sjmallett                  cvmx_app_hotplug_info_ptr->coremask, cvmx_app_hotplug_info_ptr->valid);
103215976Sjmallett#endif
104215976Sjmallett
105215976Sjmallett    cvmx_interrupt_register(CVMX_IRQ_MBOX0, __cvmx_app_hotplug_shutdown, NULL);
106215976Sjmallett
107215976Sjmallett    return 0;
108215976Sjmallett}
109215976Sjmallett
110215976Sjmallett/**
111232812Sjmallett * This routine deprecates the the cvmx_app_hotplug_register method. This
112232812Sjmallett * registers application for hotplug and the application will have CPU
113232812Sjmallett * hotplug callbacks. Various callbacks are specified in cb.
114232812Sjmallett * cvmx_app_hotplug_callbacks_t documents the callbacks
115215976Sjmallett *
116232812Sjmallett * This routine only needs to be called once per application.
117232812Sjmallett *
118232812Sjmallett * @param cb      Callback routine from the application.
119232812Sjmallett * @param arg     Argument to the application callback routins
120232812Sjmallett * @param app_shutdown   When set to 1 the application will invoke core_shutdown
121232812Sjmallett                         on each core. When set to 0 core shutdown will be
122232812Sjmallett                         called invoked automatically after invoking the
123232812Sjmallett                         application callback.
124232812Sjmallett * @return        Return index of app on success, -1 on failure
125232812Sjmallett *
126232812Sjmallett */
127232812Sjmallettint cvmx_app_hotplug_register_cb(cvmx_app_hotplug_callbacks_t *cb, void* arg,
128232812Sjmallett                                 int app_shutdown)
129232812Sjmallett{
130232812Sjmallett    cvmx_app_hotplug_info_t *app_info;
131232812Sjmallett
132232812Sjmallett    /* Find the list of applications launched by bootoct utility. */
133232812Sjmallett    app_info = cvmx_app_hotplug_get_info(cvmx_sysinfo_get()->core_mask);
134232812Sjmallett    cvmx_app_hotplug_info_ptr = app_info;
135232812Sjmallett    if (!app_info)
136232812Sjmallett    {
137232812Sjmallett        /* Application not launched by bootoct? */
138232812Sjmallett        printf("ERROR: cmvx_app_hotplug_register() failed\n");
139232812Sjmallett        return -1;
140232812Sjmallett    }
141232812Sjmallett    /* Register the callback */
142232812Sjmallett    app_info->data = CAST64(arg);
143232812Sjmallett    app_info->shutdown_callback  = CAST64(cb->shutdown_callback);
144232812Sjmallett    app_info->cores_added_callback = CAST64(cb->cores_added_callback);
145232812Sjmallett    app_info->cores_removed_callback = CAST64(cb->cores_removed_callback);
146232812Sjmallett    app_info->unplug_callback = CAST64(cb->unplug_core_callback);
147232812Sjmallett    app_info->hotplug_start = CAST64(cb->hotplug_start);
148232812Sjmallett    app_info->app_shutdown = app_shutdown;
149232812Sjmallett#ifdef DEBUG
150232812Sjmallett    printf("cvmx_app_hotplug_register(): coremask 0x%x valid %d\n",
151232812Sjmallett           app_info->coremask, app_info->valid);
152232812Sjmallett#endif
153232812Sjmallett
154232812Sjmallett    cvmx_interrupt_register(CVMX_IRQ_MBOX0, __cvmx_app_hotplug_shutdown, NULL);
155232812Sjmallett    return 0;
156232812Sjmallett
157232812Sjmallett}
158232812Sjmallett
159232812Sjmallettvoid cvmx_app_hotplug_remove_self_from_core_mask(void)
160232812Sjmallett{
161232812Sjmallett    int core = cvmx_get_core_num();
162232812Sjmallett    uint32_t core_mask = 1ull << core;
163232812Sjmallett
164232812Sjmallett    cvmx_spinlock_lock(&cvmx_app_hotplug_lock);
165232812Sjmallett    cvmx_app_hotplug_info_ptr->coremask = cvmx_app_hotplug_info_ptr->coremask & ~core_mask ;
166232812Sjmallett    cvmx_app_hotplug_info_ptr->hotplug_activated_coremask =
167232812Sjmallett        cvmx_app_hotplug_info_ptr->hotplug_activated_coremask & ~core_mask ;
168232812Sjmallett    cvmx_spinlock_unlock(&cvmx_app_hotplug_lock);
169232812Sjmallett}
170232812Sjmallett
171232812Sjmallett
172232812Sjmallett
173232812Sjmallett/**
174232812Sjmallett*  Returns 1 if the running core is being unplugged, else it returns 0.
175232812Sjmallett*/
176232812Sjmallettint is_core_being_unplugged(void)
177232812Sjmallett{
178232812Sjmallett    if (cvmx_app_hotplug_info_ptr->unplug_cores &
179232812Sjmallett        (1ull << cvmx_get_core_num()))
180232812Sjmallett        return 1;
181232812Sjmallett    return 0;
182232812Sjmallett}
183232812Sjmallett
184232812Sjmallett
185232812Sjmallett/**
186232812Sjmallett * Activate the current application core for receiving hotplug shutdown requests.
187232812Sjmallett *
188215976Sjmallett * This routine makes sure that each core belonging to the application is enabled
189215976Sjmallett * to receive the shutdown notification and also provides a barrier sync to make
190215976Sjmallett * sure that all cores are ready.
191215976Sjmallett */
192215976Sjmallettint cvmx_app_hotplug_activate(void)
193215976Sjmallett{
194232812Sjmallett    uint64_t cnt = 0;
195232812Sjmallett    uint64_t cnt_interval = 10000000;
196215976Sjmallett
197232812Sjmallett    while (!cvmx_app_hotplug_info_ptr)
198232812Sjmallett    {
199232812Sjmallett        cnt++;
200232812Sjmallett        if ((cnt % cnt_interval) == 0)
201232812Sjmallett            printf("waiting for cnt=%lld\n", (unsigned long long)cnt);
202232812Sjmallett    }
203232812Sjmallett
204232812Sjmallett    if (cvmx_app_hotplug_info_ptr->hplugged_cores & (1ull << cvmx_get_core_num()))
205232812Sjmallett    {
206232812Sjmallett#ifdef DEBUG
207232812Sjmallett        printf("core=%d : is being hotplugged \n", cvmx_get_core_num());
208232812Sjmallett#endif
209232812Sjmallett        cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get();
210232812Sjmallett        sys_info_ptr->core_mask |= 1ull << cvmx_get_core_num();
211232812Sjmallett    }
212232812Sjmallett    else
213232812Sjmallett    {
214232812Sjmallett        __cvmx_app_hotplug_sync();
215232812Sjmallett    }
216215976Sjmallett    cvmx_spinlock_lock(&cvmx_app_hotplug_lock);
217215976Sjmallett    if (!cvmx_app_hotplug_info_ptr)
218215976Sjmallett    {
219215976Sjmallett        cvmx_spinlock_unlock(&cvmx_app_hotplug_lock);
220215976Sjmallett        printf("ERROR: This application is not registered for hotplug\n");
221232812Sjmallett        return -1;
222215976Sjmallett    }
223215976Sjmallett    /* Enable the interrupt before we mark the core as activated */
224215976Sjmallett    cvmx_interrupt_unmask_irq(CVMX_IRQ_MBOX0);
225232812Sjmallett    cvmx_app_hotplug_info_ptr->hotplug_activated_coremask |= (1ull<<cvmx_get_core_num());
226215976Sjmallett
227215976Sjmallett#ifdef DEBUG
228232812Sjmallett    printf("cvmx_app_hotplug_activate(): coremask 0x%x valid %d sizeof %d\n",
229215976Sjmallett                 cvmx_app_hotplug_info_ptr->coremask, cvmx_app_hotplug_info_ptr->valid,
230215976Sjmallett                 sizeof(*cvmx_app_hotplug_info_ptr));
231215976Sjmallett#endif
232215976Sjmallett
233215976Sjmallett    cvmx_spinlock_unlock(&cvmx_app_hotplug_lock);
234215976Sjmallett
235215976Sjmallett    return 0;
236215976Sjmallett}
237215976Sjmallett
238215976Sjmallett/**
239215976Sjmallett * This routine is only required if cvmx_app_hotplug_shutdown_request() was called
240215976Sjmallett * with wait=0. This routine waits for the application shutdown to complete.
241215976Sjmallett *
242215976Sjmallett * @param coremask     Coremask the application is running on.
243215976Sjmallett * @return             0 on success, -1 on error
244215976Sjmallett *
245215976Sjmallett */
246215976Sjmallettint cvmx_app_hotplug_shutdown_complete(uint32_t coremask)
247215976Sjmallett{
248215976Sjmallett    cvmx_app_hotplug_info_t *hotplug_info_ptr;
249215976Sjmallett
250215976Sjmallett    if (!(hotplug_info_ptr = cvmx_app_hotplug_get_info(coremask)))
251215976Sjmallett    {
252215976Sjmallett        printf("\nERROR: Failed to get hotplug info for coremask: 0x%x\n", (unsigned int)coremask);
253215976Sjmallett        return -1;
254215976Sjmallett    }
255215976Sjmallett
256215976Sjmallett    while(!hotplug_info_ptr->shutdown_done);
257215976Sjmallett
258215976Sjmallett    /* Clean up the hotplug info region for this app */
259215976Sjmallett    bzero(hotplug_info_ptr, sizeof(*hotplug_info_ptr));
260215976Sjmallett
261215976Sjmallett    return 0;
262215976Sjmallett}
263215976Sjmallett
264215976Sjmallett/**
265215976Sjmallett * Disable recognition of any incoming shutdown request.
266215976Sjmallett */
267215976Sjmallett
268215976Sjmallettvoid cvmx_app_hotplug_shutdown_disable(void)
269215976Sjmallett{
270215976Sjmallett    cvmx_interrupt_mask_irq(CVMX_IRQ_MBOX0);
271215976Sjmallett}
272215976Sjmallett
273215976Sjmallett/**
274215976Sjmallett * Re-enable recognition of incoming shutdown requests.
275215976Sjmallett */
276215976Sjmallett
277215976Sjmallettvoid cvmx_app_hotplug_shutdown_enable(void)
278215976Sjmallett{
279215976Sjmallett    cvmx_interrupt_unmask_irq(CVMX_IRQ_MBOX0);
280215976Sjmallett}
281215976Sjmallett
282232812Sjmallett/**
283232812Sjmallett*  Request shutdown of the currently running core. Should be
284232812Sjmallett*  called by the application when it has been registered with
285232812Sjmallett*  app_shutdown option set to 1.
286232812Sjmallett*/
287232812Sjmallettvoid cvmx_app_hotplug_core_shutdown(void)
288232812Sjmallett{
289232812Sjmallett    uint32_t flags;
290232812Sjmallett    if (cvmx_app_hotplug_info_ptr->shutdown_cores)
291232812Sjmallett    {
292232812Sjmallett        cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get();
293232812Sjmallett       __cvmx_app_hotplug_sync();
294232812Sjmallett        if (cvmx_coremask_first_core(sys_info_ptr->core_mask))
295232812Sjmallett        {
296232812Sjmallett            bzero(cvmx_app_hotplug_info_ptr,
297232812Sjmallett                  sizeof(*cvmx_app_hotplug_info_ptr));
298232812Sjmallett            #ifdef DEBUG
299232812Sjmallett            printf("__cvmx_app_hotplug_shutdown(): setting shutdown done! \n");
300232812Sjmallett            #endif
301232812Sjmallett            cvmx_app_hotplug_info_ptr->shutdown_done = 1;
302232812Sjmallett        }
303232812Sjmallett        /* Tell the debugger that this application is finishing.  */
304232812Sjmallett        cvmx_debug_finish ();
305232812Sjmallett        flags = cvmx_interrupt_disable_save();
306232812Sjmallett        __cvmx_app_hotplug_sync();
307232812Sjmallett        /* Reset the core */
308232812Sjmallett        __cvmx_app_hotplug_reset();
309232812Sjmallett    }
310232812Sjmallett    else
311232812Sjmallett    {
312232812Sjmallett        cvmx_sysinfo_remove_self_from_core_mask();
313232812Sjmallett        cvmx_app_hotplug_remove_self_from_core_mask();
314232812Sjmallett        flags = cvmx_interrupt_disable_save();
315232812Sjmallett        __cvmx_app_hotplug_reset();
316232812Sjmallett    }
317232812Sjmallett}
318232812Sjmallett
319215976Sjmallett/*
320232812Sjmallett * ISR for the incoming shutdown request interrupt.
321215976Sjmallett */
322232812Sjmallettstatic void __cvmx_app_hotplug_shutdown(int irq_number, uint64_t registers[32],
323232812Sjmallett                                        void *user_arg)
324215976Sjmallett{
325215976Sjmallett    cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get();
326232812Sjmallett    uint64_t mbox;
327232812Sjmallett    cvmx_app_hotplug_info_t *ai = cvmx_app_hotplug_info_ptr;
328232812Sjmallett    int dbg = 0;
329215976Sjmallett
330232812Sjmallett#ifdef DEBUG
331232812Sjmallett    dbg = 1;
332232812Sjmallett#endif
333215976Sjmallett    cvmx_interrupt_mask_irq(CVMX_IRQ_MBOX0);
334215976Sjmallett
335232812Sjmallett    mbox = cvmx_read_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()));
336215976Sjmallett    /* Clear the interrupt */
337232812Sjmallett    cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), mbox);
338215976Sjmallett
339215976Sjmallett    /* Make sure the write above completes */
340215976Sjmallett    cvmx_read_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()));
341215976Sjmallett
342232812Sjmallett
343215976Sjmallett    if (!cvmx_app_hotplug_info_ptr)
344215976Sjmallett    {
345215976Sjmallett        printf("ERROR: Application is not registered for hotplug!\n");
346215976Sjmallett        return;
347215976Sjmallett    }
348215976Sjmallett
349232812Sjmallett    if (ai->hotplug_activated_coremask != sys_info_ptr->core_mask)
350215976Sjmallett    {
351232812Sjmallett        printf("ERROR: Shutdown requested when not all app cores have "
352232812Sjmallett               "activated hotplug\n" "Application coremask: 0x%x Hotplug "
353232812Sjmallett               "coremask: 0x%x\n", (unsigned int)sys_info_ptr->core_mask,
354232812Sjmallett               (unsigned int)ai->hotplug_activated_coremask);
355232812Sjmallett        return;
356215976Sjmallett    }
357215976Sjmallett
358232812Sjmallett    if (mbox & 1ull)
359232812Sjmallett    {
360232812Sjmallett        int core = cvmx_get_core_num();
361232812Sjmallett        if (dbg)
362232812Sjmallett            printf("Shutting down application .\n");
363232812Sjmallett        /* Call the application's own callback function */
364232812Sjmallett        if (ai->shutdown_callback)
365232812Sjmallett        {
366232812Sjmallett            ((void(*)(void*))(long)ai->shutdown_callback)(CASTPTR(void *, ai->data));
367232812Sjmallett        }
368232812Sjmallett        else
369232812Sjmallett        {
370232812Sjmallett            printf("ERROR : Shutdown callback has not been registered\n");
371232812Sjmallett        }
372232812Sjmallett        if (!ai->app_shutdown)
373232812Sjmallett        {
374232812Sjmallett            if (dbg)
375232812Sjmallett                printf("%s : core = %d Invoking app shutdown\n", __FUNCTION__, core);
376232812Sjmallett            cvmx_app_hotplug_core_shutdown();
377232812Sjmallett        }
378232812Sjmallett    }
379232812Sjmallett    else if (mbox & 2ull)
380232812Sjmallett    {
381232812Sjmallett        int core = cvmx_get_core_num();
382232812Sjmallett        int unplug = is_core_being_unplugged();
383232812Sjmallett        if (dbg) printf("%s : core=%d Unplug event \n", __FUNCTION__, core);
384215976Sjmallett
385232812Sjmallett        if (unplug)
386232812Sjmallett        {
387232812Sjmallett            /* Call the application's own callback function */
388232812Sjmallett            if (ai->unplug_callback)
389232812Sjmallett            {
390232812Sjmallett                if (dbg) printf("%s : core=%d Calling unplug callback\n",
391232812Sjmallett                                __FUNCTION__, core);
392232812Sjmallett                ((void(*)(void*))(long)ai->unplug_callback)(CASTPTR(void *,
393232812Sjmallett                                                           ai->data));
394232812Sjmallett            }
395232812Sjmallett            if (!ai->app_shutdown)
396232812Sjmallett            {
397232812Sjmallett                if (dbg) printf("%s : core = %d Invoking app shutdown\n",
398232812Sjmallett                                __FUNCTION__, core);
399232812Sjmallett                cvmx_app_hotplug_core_shutdown();
400232812Sjmallett            }
401232812Sjmallett        }
402232812Sjmallett        else
403232812Sjmallett        {
404232812Sjmallett            if (ai->cores_removed_callback)
405232812Sjmallett            {
406232812Sjmallett                if (dbg) printf("%s : core=%d Calling cores removed callback\n",
407232812Sjmallett                                __FUNCTION__, core);
408232812Sjmallett                ((void(*)(uint32_t, void*))(long)ai->cores_removed_callback)
409232812Sjmallett                    (ai->unplug_cores, CASTPTR(void *, ai->data));
410232812Sjmallett            }
411232812Sjmallett            cvmx_interrupt_unmask_irq(CVMX_IRQ_MBOX0);
412232812Sjmallett        }
413232812Sjmallett    }
414232812Sjmallett    else if (mbox & 4ull)
415232812Sjmallett    {
416232812Sjmallett        int core = cvmx_get_core_num();
417232812Sjmallett        if (dbg) printf("%s : core=%d Add cores event \n", __FUNCTION__, core);
418215976Sjmallett
419232812Sjmallett        if (ai->cores_added_callback)
420232812Sjmallett        {
421232812Sjmallett            if (dbg) printf("%s : core=%d Calling cores added callback\n",
422232812Sjmallett                            __FUNCTION__, core);
423232812Sjmallett            ((void(*)(uint32_t, void*))(long)ai->cores_added_callback)
424232812Sjmallett                (ai->hplugged_cores, CASTPTR(void *, ai->data));
425232812Sjmallett        }
426232812Sjmallett        cvmx_interrupt_unmask_irq(CVMX_IRQ_MBOX0);
427232812Sjmallett    }
428232812Sjmallett    else
429215976Sjmallett    {
430232812Sjmallett        printf("ERROR: unexpected mbox=%llx\n", (unsigned long long)mbox);
431215976Sjmallett    }
432215976Sjmallett
433215976Sjmallett}
434215976Sjmallett
435215976Sjmallettvoid __cvmx_app_hotplug_reset(void)
436215976Sjmallett{
437232812Sjmallett#define IDLE_CORE_BLOCK_NAME    "idle-core-loop"
438232812Sjmallett#define HPLUG_MAKE_XKPHYS(x)       ((1ULL << 63) | (x))
439232812Sjmallett    uint64_t reset_addr;
440232812Sjmallett    const cvmx_bootmem_named_block_desc_t *block_desc;
441232812Sjmallett
442232812Sjmallett    block_desc = cvmx_bootmem_find_named_block(IDLE_CORE_BLOCK_NAME);
443232812Sjmallett    if (!block_desc) {
444232812Sjmallett        cvmx_dprintf("Named block(%s) is not created\n", IDLE_CORE_BLOCK_NAME);
445232812Sjmallett        /* loop here, should not happen */
446232812Sjmallett        __asm__ volatile (
447232812Sjmallett                          ".set noreorder      \n"
448232812Sjmallett                          "\tsync               \n"
449232812Sjmallett                          "\tnop               \n"
450232812Sjmallett                          "1:\twait            \n"
451232812Sjmallett                          "\tb 1b              \n"
452232812Sjmallett                          "\tnop               \n"
453232812Sjmallett                          ".set reorder        \n"
454232812Sjmallett                          ::
455232812Sjmallett                          );
456232812Sjmallett    }
457232812Sjmallett
458232812Sjmallett    reset_addr = HPLUG_MAKE_XKPHYS(block_desc->base_addr);
459232812Sjmallett    asm volatile ("       .set push                \n"
460232812Sjmallett                  "       .set mips64              \n"
461232812Sjmallett                  "       .set noreorder           \n"
462232812Sjmallett                  "       move  $2, %[addr]        \n"
463232812Sjmallett                  "       jr    $2                 \n"
464232812Sjmallett                  "       nop                      \n"
465232812Sjmallett                  "       .set pop "
466232812Sjmallett                  :: [addr] "r"(reset_addr)
467232812Sjmallett                  : "$2");
468232812Sjmallett
469232812Sjmallett    /*Should never reach here*/
470232812Sjmallett    while (1) ;
471232812Sjmallett
472215976Sjmallett}
473215976Sjmallett
474215976Sjmallett/*
475215976Sjmallett * We need a separate sync operation from cvmx_coremask_barrier_sync() to
476215976Sjmallett * avoid a deadlock on state.lock, since the application itself maybe doing a
477215976Sjmallett * cvmx_coremask_barrier_sync().
478215976Sjmallett */
479215976Sjmallettstatic void __cvmx_app_hotplug_sync(void)
480215976Sjmallett{
481215976Sjmallett    static CVMX_SHARED volatile uint32_t sync_coremask = 0;
482215976Sjmallett    cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get();
483215976Sjmallett
484215976Sjmallett    cvmx_spinlock_lock(&cvmx_app_hotplug_sync_lock);
485215976Sjmallett
486215976Sjmallett    sync_coremask |= cvmx_coremask_core(cvmx_get_core_num());
487215976Sjmallett
488215976Sjmallett    cvmx_spinlock_unlock(&cvmx_app_hotplug_sync_lock);
489215976Sjmallett
490215976Sjmallett    while (sync_coremask != sys_info_ptr->core_mask);
491232812Sjmallett
492232812Sjmallett    cvmx_spinlock_lock(&cvmx_app_hotplug_sync_lock);
493232812Sjmallett    sync_coremask = 0;
494232812Sjmallett    cvmx_spinlock_unlock(&cvmx_app_hotplug_sync_lock);
495232812Sjmallett
496232812Sjmallett
497215976Sjmallett}
498215976Sjmallett
499215976Sjmallett#endif /* CVMX_BUILD_FOR_LINUX_USER */
500215976Sjmallett
501215976Sjmallett/**
502232812Sjmallett*  Returns 1 if the running core is being hotplugged, else it returns 0.
503232812Sjmallett*/
504232812Sjmallettint is_core_being_hot_plugged(void)
505215976Sjmallett{
506232812Sjmallett
507232812Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_USER
508232812Sjmallett    if (!cvmx_app_hotplug_info_ptr) return 0;
509232812Sjmallett    if (cvmx_app_hotplug_info_ptr->hplugged_cores &
510232812Sjmallett        (1ull << cvmx_get_core_num()))
511232812Sjmallett        return 1;
512232812Sjmallett    return 0;
513232812Sjmallett#else
514232812Sjmallett    return 0;
515232812Sjmallett#endif
516232812Sjmallett}
517232812Sjmallett
518232812Sjmallettstatic cvmx_app_hotplug_global_t *cvmx_app_get_hotplug_global_ptr(void)
519232812Sjmallett{
520215976Sjmallett    const struct cvmx_bootmem_named_block_desc *block_desc;
521215976Sjmallett    cvmx_app_hotplug_global_t *hgp;
522215976Sjmallett
523232812Sjmallett    if(hotplug_global_ptr != 0) return hotplug_global_ptr;
524232812Sjmallett
525215976Sjmallett    block_desc = cvmx_bootmem_find_named_block(CVMX_APP_HOTPLUG_INFO_REGION_NAME);
526215976Sjmallett    if (!block_desc)
527215976Sjmallett    {
528215976Sjmallett        printf("ERROR: Hotplug info region is not setup\n");
529215976Sjmallett        return NULL;
530215976Sjmallett    }
531215976Sjmallett    else
532215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_USER
533215976Sjmallett    {
534215976Sjmallett        size_t pg_sz = sysconf(_SC_PAGESIZE), size;
535215976Sjmallett        off_t offset;
536215976Sjmallett        char *vaddr;
537215976Sjmallett        int fd;
538215976Sjmallett
539215976Sjmallett        if ((fd = open("/dev/mem", O_RDWR)) == -1) {
540215976Sjmallett            perror("open");
541215976Sjmallett            return NULL;
542215976Sjmallett        }
543215976Sjmallett
544215976Sjmallett        /*
545215976Sjmallett         * We need to mmap() this memory, since this was allocated from the
546215976Sjmallett         * kernel bootup code and does not reside in the RESERVE32 region.
547215976Sjmallett         */
548215976Sjmallett        size = CVMX_APP_HOTPLUG_INFO_REGION_SIZE + pg_sz-1;
549215976Sjmallett        offset = block_desc->base_addr & ~(pg_sz-1);
550232812Sjmallett        if ((vaddr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset))
551232812Sjmallett	    == MAP_FAILED)
552215976Sjmallett        {
553215976Sjmallett            perror("mmap");
554215976Sjmallett            return NULL;
555215976Sjmallett        }
556215976Sjmallett
557215976Sjmallett        hgp = (cvmx_app_hotplug_global_t *)(vaddr + ( block_desc->base_addr & (pg_sz-1)));
558215976Sjmallett    }
559215976Sjmallett#else
560232812Sjmallett    hgp = CASTPTR(void, CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS, block_desc->base_addr));
561215976Sjmallett#endif
562232812Sjmallett    hotplug_global_ptr = hgp;
563232812Sjmallett    return hgp;
564215976Sjmallett
565232812Sjmallett}
566215976Sjmallett
567232812Sjmallett/**
568232812Sjmallett * Return the hotplug info structure (cvmx_app_hotplug_info_t) pointer for the
569232812Sjmallett * application running on the given coremask.
570232812Sjmallett *
571232812Sjmallett * @param coremask     Coremask of application.
572232812Sjmallett * @return             Returns hotplug info struct on success, NULL on failure
573232812Sjmallett *
574232812Sjmallett */
575232812Sjmallettcvmx_app_hotplug_info_t* cvmx_app_hotplug_get_info(uint32_t coremask)
576232812Sjmallett{
577232812Sjmallett    cvmx_app_hotplug_info_t *hip;
578232812Sjmallett    cvmx_app_hotplug_global_t *hgp;
579232812Sjmallett    int i;
580232812Sjmallett    int dbg = 0;
581232812Sjmallett
582215976Sjmallett#ifdef DEBUG
583232812Sjmallett    dbg = 1;
584215976Sjmallett#endif
585232812Sjmallett    hgp = cvmx_app_get_hotplug_global_ptr();
586232812Sjmallett    if (!hgp) return NULL;
587232812Sjmallett    hip = hgp->hotplug_info_array;
588215976Sjmallett
589215976Sjmallett    /* Look for the current app's info */
590215976Sjmallett    for (i=0; i<CVMX_APP_HOTPLUG_MAX_APPS; i++)
591215976Sjmallett    {
592215976Sjmallett        if (hip[i].coremask == coremask)
593232812Sjmallett        {
594232812Sjmallett	    if (dbg)
595232812Sjmallett                printf("cvmx_app_hotplug_get_info(): coremask match %d -- coremask 0x%x, valid %d\n", i, (unsigned int)hip[i].coremask, (unsigned int)hip[i].valid);
596232812Sjmallett            return &hip[i];
597232812Sjmallett        }
598232812Sjmallett    }
599232812Sjmallett    return NULL;
600232812Sjmallett}
601232812Sjmallett
602232812Sjmallett/**
603232812Sjmallett * Return the hotplug application index structure for the application running on the
604232812Sjmallett * given coremask.
605232812Sjmallett *
606232812Sjmallett * @param coremask     Coremask of application.
607232812Sjmallett * @return             Returns hotplug application index on success. -1 on failure
608232812Sjmallett *
609232812Sjmallett */
610232812Sjmallettint cvmx_app_hotplug_get_index(uint32_t coremask)
611232812Sjmallett{
612232812Sjmallett    cvmx_app_hotplug_info_t *hip;
613232812Sjmallett    cvmx_app_hotplug_global_t *hgp;
614232812Sjmallett    int i;
615232812Sjmallett    int dbg = 0;
616232812Sjmallett
617215976Sjmallett#ifdef DEBUG
618232812Sjmallett    dbg = 1;
619215976Sjmallett#endif
620232812Sjmallett    hgp = cvmx_app_get_hotplug_global_ptr();
621232812Sjmallett    if (!hgp) return -1;
622232812Sjmallett    hip = hgp->hotplug_info_array;
623215976Sjmallett
624232812Sjmallett    /* Look for the current app's info */
625232812Sjmallett    for (i=0; i<CVMX_APP_HOTPLUG_MAX_APPS; i++)
626232812Sjmallett    {
627232812Sjmallett        if (hip[i].coremask == coremask)
628232812Sjmallett        {
629232812Sjmallett	    if (dbg)
630232812Sjmallett                printf("cvmx_app_hotplug_get_info(): coremask match %d -- coremask 0x%x valid %d\n", i, (unsigned int)hip[i].coremask, (unsigned int)hip[i].valid);
631232812Sjmallett	    return i;
632232812Sjmallett        }
633215976Sjmallett    }
634232812Sjmallett    return -1;
635232812Sjmallett}
636215976Sjmallett
637232812Sjmallettvoid print_hot_plug_info(cvmx_app_hotplug_info_t* hpinfo)
638232812Sjmallett{
639232812Sjmallett    printf("name=%s coremask=%08x hotplugged coremask=%08x valid=%d\n", hpinfo->app_name,
640232812Sjmallett           (unsigned int)hpinfo->coremask, (unsigned int)hpinfo->hotplug_activated_coremask, (unsigned int)hpinfo->valid);
641232812Sjmallett}
642232812Sjmallett
643232812Sjmallett/**
644232812Sjmallett * Return the hotplug info structure (cvmx_app_hotplug_info_t) pointer for the
645232812Sjmallett * application with the specified index.
646232812Sjmallett *
647232812Sjmallett * @param index        index of application.
648232812Sjmallett * @return             Returns hotplug info struct on success, NULL on failure
649232812Sjmallett *
650232812Sjmallett */
651232812Sjmallettcvmx_app_hotplug_info_t* cvmx_app_hotplug_get_info_at_index(int index)
652232812Sjmallett{
653232812Sjmallett    cvmx_app_hotplug_info_t *hip;
654232812Sjmallett    cvmx_app_hotplug_global_t *hgp;
655232812Sjmallett
656232812Sjmallett    hgp = cvmx_app_get_hotplug_global_ptr();
657232812Sjmallett    if (!hgp) return NULL;
658232812Sjmallett    hip = hgp->hotplug_info_array;
659232812Sjmallett
660232812Sjmallett#ifdef DEBUG
661232812Sjmallett    printf("cvmx_app_hotplug_get_info(): hotplug_info phy addr 0x%llx ptr %p\n",
662232812Sjmallett                  block_desc->base_addr, hgp);
663232812Sjmallett#endif
664232812Sjmallett    if (index < CVMX_APP_HOTPLUG_MAX_APPS)
665232812Sjmallett    {
666232812Sjmallett        if (hip[index].valid)
667232812Sjmallett        {
668232812Sjmallett            //print_hot_plug_info( &hip[index] );
669232812Sjmallett            return &hip[index];
670232812Sjmallett        }
671232812Sjmallett    }
672215976Sjmallett    return NULL;
673215976Sjmallett}
674215976Sjmallett
675215976Sjmallett/**
676232812Sjmallett * Determines if SE application at the index specified is hotpluggable.
677232812Sjmallett *
678232812Sjmallett * @param index        index of application.
679232812Sjmallett * @return             Returns -1  on error.
680232812Sjmallett *                     0 -> The application is not hotpluggable
681232812Sjmallett *                     1 -> The application is hotpluggable
682232812Sjmallett*/
683232812Sjmallettint is_app_hotpluggable(int index)
684232812Sjmallett{
685232812Sjmallett    cvmx_app_hotplug_info_t *ai;
686232812Sjmallett
687232812Sjmallett    if (!(ai = cvmx_app_hotplug_get_info_at_index(index)))
688232812Sjmallett    {
689232812Sjmallett        printf("\nERROR: Failed to get hotplug info for app at index=%d\n", index);
690232812Sjmallett        return -1;
691232812Sjmallett    }
692232812Sjmallett    if (ai->hotplug_activated_coremask) return 1;
693232812Sjmallett    return 0;
694232812Sjmallett}
695232812Sjmallett
696232812Sjmallett/**
697215976Sjmallett * This routine sends a shutdown request to a running target application.
698215976Sjmallett *
699215976Sjmallett * @param coremask     Coremask the application is running on.
700215976Sjmallett * @param wait         1 - Wait for shutdown completion
701215976Sjmallett *                     0 - Do not wait
702215976Sjmallett * @return             0 on success, -1 on error
703215976Sjmallett *
704215976Sjmallett */
705215976Sjmallett
706215976Sjmallettint cvmx_app_hotplug_shutdown_request(uint32_t coremask, int wait)
707215976Sjmallett{
708215976Sjmallett    int i;
709215976Sjmallett    cvmx_app_hotplug_info_t *hotplug_info_ptr;
710215976Sjmallett
711215976Sjmallett    if (!(hotplug_info_ptr = cvmx_app_hotplug_get_info(coremask)))
712215976Sjmallett    {
713215976Sjmallett        printf("\nERROR: Failed to get hotplug info for coremask: 0x%x\n", (unsigned int)coremask);
714215976Sjmallett        return -1;
715215976Sjmallett    }
716232812Sjmallett    hotplug_info_ptr->shutdown_cores = coremask;
717215976Sjmallett    if (!hotplug_info_ptr->shutdown_callback)
718215976Sjmallett    {
719215976Sjmallett        printf("\nERROR: Target application has not registered for hotplug!\n");
720215976Sjmallett        return -1;
721215976Sjmallett    }
722215976Sjmallett
723215976Sjmallett    if (hotplug_info_ptr->hotplug_activated_coremask != coremask)
724215976Sjmallett    {
725215976Sjmallett        printf("\nERROR: Not all application cores have activated hotplug\n");
726215976Sjmallett        return -1;
727215976Sjmallett    }
728215976Sjmallett
729215976Sjmallett    /* Send IPIs to all application cores to request shutdown */
730215976Sjmallett    for (i=0; i<CVMX_MAX_CORES; i++) {
731232812Sjmallett            if (coremask & (1ull<<i))
732232812Sjmallett                cvmx_write_csr(CVMX_CIU_MBOX_SETX(i), 1);
733215976Sjmallett    }
734215976Sjmallett
735215976Sjmallett    if (wait)
736215976Sjmallett    {
737215976Sjmallett        while (!hotplug_info_ptr->shutdown_done);
738215976Sjmallett
739215976Sjmallett        /* Clean up the hotplug info region for this application */
740215976Sjmallett        bzero(hotplug_info_ptr, sizeof(*hotplug_info_ptr));
741215976Sjmallett    }
742215976Sjmallett
743215976Sjmallett    return 0;
744215976Sjmallett}
745232812Sjmallett
746232812Sjmallett
747232812Sjmallett
748232812Sjmallett/**
749232812Sjmallett * This routine invokes the invoked the cores_added callbacks.
750232812Sjmallett */
751232812Sjmallettint cvmx_app_hotplug_call_add_cores_callback(int index)
752232812Sjmallett{
753232812Sjmallett    cvmx_app_hotplug_info_t *ai;
754232812Sjmallett    int i;
755232812Sjmallett    if (!(ai = cvmx_app_hotplug_get_info_at_index(index)))
756232812Sjmallett    {
757232812Sjmallett        printf("\nERROR: Failed to get hotplug info for app at index=%d\n", index);
758232812Sjmallett        return -1;
759232812Sjmallett    }
760232812Sjmallett   /* Send IPIs to all application cores to request add_cores callback*/
761232812Sjmallett    for (i=0; i<CVMX_MAX_CORES; i++) {
762232812Sjmallett            if (ai->coremask & (1ull<<i))
763232812Sjmallett                cvmx_write_csr(CVMX_CIU_MBOX_SETX(i), 4);
764232812Sjmallett    }
765232812Sjmallett    return 0;
766232812Sjmallett}
767232812Sjmallett
768232812Sjmallett/**
769232812Sjmallett * This routine sends a request to a running target application
770232812Sjmallett * to unplug a specified set cores
771232812Sjmallett * @param index        is the index of the target application
772232812Sjmallett * @param coremask     Coremask of the cores to be unplugged from the app.
773232812Sjmallett * @param wait         1 - Wait for shutdown completion
774232812Sjmallett *                     0 - Do not wait
775232812Sjmallett * @return             0 on success, -1 on error
776232812Sjmallett *
777232812Sjmallett */
778232812Sjmallettint cvmx_app_hotplug_unplug_cores(int index, uint32_t coremask, int wait)
779232812Sjmallett{
780232812Sjmallett    cvmx_app_hotplug_info_t *ai;
781232812Sjmallett    int i;
782232812Sjmallett
783232812Sjmallett    if (!(ai = cvmx_app_hotplug_get_info_at_index(index)))
784232812Sjmallett    {
785232812Sjmallett        printf("\nERROR: Failed to get hotplug info for app at index=%d\n", index);
786232812Sjmallett        return -1;
787232812Sjmallett    }
788232812Sjmallett    ai->unplug_cores = coremask;
789232812Sjmallett#if 0
790232812Sjmallett    if (!ai->shutdown_callback)
791232812Sjmallett    {
792232812Sjmallett        printf("\nERROR: Target application has not registered for hotplug!\n");
793232812Sjmallett        return -1;
794232812Sjmallett    }
795232812Sjmallett#endif
796232812Sjmallett    if ( (ai->coremask | coremask ) != ai->coremask)
797232812Sjmallett    {
798232812Sjmallett        printf("\nERROR: Not all cores requested are a part of the app "
799232812Sjmallett               "r=%08x:%08x\n", (unsigned int)coremask, (unsigned int)ai->coremask);
800232812Sjmallett        return -1;
801232812Sjmallett    }
802232812Sjmallett    if (ai->coremask == coremask)
803232812Sjmallett    {
804232812Sjmallett        printf("\nERROR: Trying to remove all cores in app. "
805232812Sjmallett               "r=%08x:%08x\n", (unsigned int)coremask, (unsigned int)ai->coremask);
806232812Sjmallett        return -1;
807232812Sjmallett    }
808232812Sjmallett    /* Send IPIs to all application cores to request unplug/remove_cores
809232812Sjmallett       callback */
810232812Sjmallett    for (i=0; i<CVMX_MAX_CORES; i++) {
811232812Sjmallett            if (ai->coremask & (1ull<<i))
812232812Sjmallett                cvmx_write_csr(CVMX_CIU_MBOX_SETX(i), 2);
813232812Sjmallett    }
814232812Sjmallett
815232812Sjmallett#if 0
816232812Sjmallett    if (wait)
817232812Sjmallett    {
818232812Sjmallett        while (!ai->shutdown_done);
819232812Sjmallett
820232812Sjmallett        /* Clean up the hotplug info region for this application */
821232812Sjmallett        bzero(ai, sizeof(*ai));
822232812Sjmallett    }
823232812Sjmallett#endif
824232812Sjmallett    return 0;
825232812Sjmallett}
826232812Sjmallett
827232812Sjmallett/**
828232812Sjmallett * Returns 1 if any app is currently being currently booted , hotplugged or
829232812Sjmallett * shutdown. Only one app can be under a boot, hotplug or shutdown condition.
830232812Sjmallett * Before booting an app this methods should be used to check whether boot or
831232812Sjmallett * shutdown activity is in progress and proceed with the boot or shutdown only
832232812Sjmallett * when there is no other activity.
833232812Sjmallett *
834232812Sjmallett */
835232812Sjmallettint is_app_under_boot_or_shutdown(void)
836232812Sjmallett{
837232812Sjmallett    int ret=0;
838232812Sjmallett    cvmx_app_hotplug_global_t *hgp;
839232812Sjmallett
840232812Sjmallett    hgp = cvmx_app_get_hotplug_global_ptr();
841232812Sjmallett    cvmx_spinlock_lock(&hgp->hotplug_global_lock);
842232812Sjmallett    if (hgp->app_under_boot || hgp->app_under_shutdown) ret=1;
843232812Sjmallett    cvmx_spinlock_unlock(&hgp->hotplug_global_lock);
844232812Sjmallett    return ret;
845232812Sjmallett
846232812Sjmallett}
847232812Sjmallett
848232812Sjmallett/**
849232812Sjmallett * Sets or clear the app_under_boot value. This when set signifies that an app
850232812Sjmallett * is being currently booted or hotplugged with a new core.
851232812Sjmallett *
852232812Sjmallett *
853232812Sjmallett * @param val     sets the app_under_boot to the specified value. This should be
854232812Sjmallett *                set to 1 while app any is being booted and cleared after the
855232812Sjmallett *                application has booted up.
856232812Sjmallett *
857232812Sjmallett */
858232812Sjmallettvoid set_app_unber_boot(int val)
859232812Sjmallett{
860232812Sjmallett    cvmx_app_hotplug_global_t *hgp;
861232812Sjmallett
862232812Sjmallett    hgp = cvmx_app_get_hotplug_global_ptr();
863232812Sjmallett    cvmx_spinlock_lock(&hgp->hotplug_global_lock);
864232812Sjmallett    hgp->app_under_boot = val;
865232812Sjmallett    cvmx_spinlock_unlock(&hgp->hotplug_global_lock);
866232812Sjmallett}
867232812Sjmallett
868232812Sjmallett/**
869232812Sjmallett * Sets or clear the app_under_shutdown value. This when set signifies that an
870232812Sjmallett * app is being currently shutdown or some cores of an app are being shutdown.
871232812Sjmallett *
872232812Sjmallett * @param val     sets the app_under_shutdown to the specified value. This
873232812Sjmallett *                should be set to 1 while any app is being shutdown and cleared
874232812Sjmallett *                after the shutdown of the app is complete.
875232812Sjmallett *
876232812Sjmallett */
877232812Sjmallettvoid set_app_under_shutdown(int val)
878232812Sjmallett{
879232812Sjmallett    cvmx_app_hotplug_global_t *hgp;
880232812Sjmallett
881232812Sjmallett    hgp = cvmx_app_get_hotplug_global_ptr();
882232812Sjmallett    cvmx_spinlock_lock(&hgp->hotplug_global_lock);
883232812Sjmallett    hgp->app_under_shutdown = val;
884232812Sjmallett    cvmx_spinlock_unlock(&hgp->hotplug_global_lock);
885232812Sjmallett}
886