1 /***********************license start***************
2 * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * * Neither the name of Cavium Networks nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
23 * This Software, including technical data, may be subject to U.S. export control
24 * laws, including the U.S. Export Administration Act and its associated
25 * regulations, and may be subject to export or import regulations in other
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
43 * Provides APIs for applications to register for hotplug. It also provides
44 * APIs for requesting shutdown of a running target application.
46 * <hr>$Revision: $<hr>
49 #include "cvmx-app-hotplug.h"
50 #include "cvmx-spinlock.h"
54 #ifndef CVMX_BUILD_FOR_LINUX_USER
56 static CVMX_SHARED cvmx_spinlock_t cvmx_app_hotplug_sync_lock = { CVMX_SPINLOCK_UNLOCKED_VAL };
57 static CVMX_SHARED cvmx_spinlock_t cvmx_app_hotplug_lock = { CVMX_SPINLOCK_UNLOCKED_VAL };
58 static CVMX_SHARED cvmx_app_hotplug_info_t *cvmx_app_hotplug_info_ptr = NULL;
60 static void __cvmx_app_hotplug_shutdown(int irq_number, uint64_t registers[32], void *user_arg);
61 static void __cvmx_app_hotplug_sync(void);
62 static void __cvmx_app_hotplug_reset(void);
65 * This routine registers an application for hotplug. It installs a handler for
66 * any incoming shutdown request. It also registers a callback routine from the
67 * application. This callback is invoked when the application receives a
68 * shutdown notification.
70 * This routine only needs to be called once per application.
72 * @param fn Callback routine from the application.
73 * @param arg Argument to the application callback routine.
74 * @return Return 0 on success, -1 on failure
77 int cvmx_app_hotplug_register(void(*fn)(void*), void* arg)
79 /* Find the list of applications launched by bootoct utility. */
81 if (!(cvmx_app_hotplug_info_ptr = cvmx_app_hotplug_get_info(cvmx_sysinfo_get()->core_mask)))
83 /* Application not launched by bootoct? */
84 printf("ERROR: cmvx_app_hotplug_register() failed\n");
88 /* Register the callback */
89 cvmx_app_hotplug_info_ptr->data = CAST64(arg);
90 cvmx_app_hotplug_info_ptr->shutdown_callback = CAST64(fn);
93 cvmx_dprintf("cvmx_app_hotplug_register(): coremask 0x%x valid %d\n",
94 cvmx_app_hotplug_info_ptr->coremask, cvmx_app_hotplug_info_ptr->valid);
97 cvmx_interrupt_register(CVMX_IRQ_MBOX0, __cvmx_app_hotplug_shutdown, NULL);
103 * Activate the current application core for receiving hotplug shutdown requests.
105 * This routine makes sure that each core belonging to the application is enabled
106 * to receive the shutdown notification and also provides a barrier sync to make
107 * sure that all cores are ready.
109 int cvmx_app_hotplug_activate(void)
111 /* Make sure all application cores are activating */
112 __cvmx_app_hotplug_sync();
114 cvmx_spinlock_lock(&cvmx_app_hotplug_lock);
116 if (!cvmx_app_hotplug_info_ptr)
118 cvmx_spinlock_unlock(&cvmx_app_hotplug_lock);
119 printf("ERROR: This application is not registered for hotplug\n");
123 /* Enable the interrupt before we mark the core as activated */
124 cvmx_interrupt_unmask_irq(CVMX_IRQ_MBOX0);
126 cvmx_app_hotplug_info_ptr->hotplug_activated_coremask |= (1<<cvmx_get_core_num());
129 cvmx_dprintf("cvmx_app_hotplug_activate(): coremask 0x%x valid %d sizeof %d\n",
130 cvmx_app_hotplug_info_ptr->coremask, cvmx_app_hotplug_info_ptr->valid,
131 sizeof(*cvmx_app_hotplug_info_ptr));
134 cvmx_spinlock_unlock(&cvmx_app_hotplug_lock);
140 * This routine is only required if cvmx_app_hotplug_shutdown_request() was called
141 * with wait=0. This routine waits for the application shutdown to complete.
143 * @param coremask Coremask the application is running on.
144 * @return 0 on success, -1 on error
147 int cvmx_app_hotplug_shutdown_complete(uint32_t coremask)
149 cvmx_app_hotplug_info_t *hotplug_info_ptr;
151 if (!(hotplug_info_ptr = cvmx_app_hotplug_get_info(coremask)))
153 printf("\nERROR: Failed to get hotplug info for coremask: 0x%x\n", (unsigned int)coremask);
157 while(!hotplug_info_ptr->shutdown_done);
159 /* Clean up the hotplug info region for this app */
160 bzero(hotplug_info_ptr, sizeof(*hotplug_info_ptr));
166 * Disable recognition of any incoming shutdown request.
169 void cvmx_app_hotplug_shutdown_disable(void)
171 cvmx_interrupt_mask_irq(CVMX_IRQ_MBOX0);
175 * Re-enable recognition of incoming shutdown requests.
178 void cvmx_app_hotplug_shutdown_enable(void)
180 cvmx_interrupt_unmask_irq(CVMX_IRQ_MBOX0);
184 * ISR for the incoming shutdown request interrupt.
186 static void __cvmx_app_hotplug_shutdown(int irq_number, uint64_t registers[32], void *user_arg)
188 cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get();
191 cvmx_interrupt_mask_irq(CVMX_IRQ_MBOX0);
193 /* Clear the interrupt */
194 cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 1);
196 /* Make sure the write above completes */
197 cvmx_read_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()));
199 if (!cvmx_app_hotplug_info_ptr)
201 printf("ERROR: Application is not registered for hotplug!\n");
205 if (cvmx_app_hotplug_info_ptr->hotplug_activated_coremask != sys_info_ptr->core_mask)
207 printf("ERROR: Shutdown requested when not all app cores have activated hotplug\n"
208 "Application coremask: 0x%x Hotplug coremask: 0x%x\n", (unsigned int)sys_info_ptr->core_mask,
209 (unsigned int)cvmx_app_hotplug_info_ptr->hotplug_activated_coremask);
213 /* Call the application's own callback function */
214 ((void(*)(void*))(long)cvmx_app_hotplug_info_ptr->shutdown_callback)(CASTPTR(void *, cvmx_app_hotplug_info_ptr->data));
216 __cvmx_app_hotplug_sync();
218 if (cvmx_coremask_first_core(sys_info_ptr->core_mask))
220 bzero(cvmx_app_hotplug_info_ptr, sizeof(*cvmx_app_hotplug_info_ptr));
222 cvmx_dprintf("__cvmx_app_hotplug_shutdown(): setting shutdown done! \n");
224 cvmx_app_hotplug_info_ptr->shutdown_done = 1;
227 flags = cvmx_interrupt_disable_save();
229 __cvmx_app_hotplug_sync();
232 __cvmx_app_hotplug_reset();
236 * Reset the core. We just jump back to the reset vector for now.
238 void __cvmx_app_hotplug_reset(void)
240 /* Code from SecondaryCoreLoop from bootloader, sleep until we recieve
255 * We need a separate sync operation from cvmx_coremask_barrier_sync() to
256 * avoid a deadlock on state.lock, since the application itself maybe doing a
257 * cvmx_coremask_barrier_sync().
259 static void __cvmx_app_hotplug_sync(void)
261 static CVMX_SHARED volatile uint32_t sync_coremask = 0;
262 cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get();
264 cvmx_spinlock_lock(&cvmx_app_hotplug_sync_lock);
266 sync_coremask |= cvmx_coremask_core(cvmx_get_core_num());
268 cvmx_spinlock_unlock(&cvmx_app_hotplug_sync_lock);
270 while (sync_coremask != sys_info_ptr->core_mask);
273 #endif /* CVMX_BUILD_FOR_LINUX_USER */
276 * Return the hotplug info structure (cvmx_app_hotplug_info_t) pointer for the
277 * application running on the given coremask.
279 * @param coremask Coremask of application.
280 * @return Returns hotplug info struct on success, NULL on failure
283 cvmx_app_hotplug_info_t* cvmx_app_hotplug_get_info(uint32_t coremask)
285 const struct cvmx_bootmem_named_block_desc *block_desc;
286 cvmx_app_hotplug_info_t *hip;
287 cvmx_app_hotplug_global_t *hgp;
290 block_desc = cvmx_bootmem_find_named_block(CVMX_APP_HOTPLUG_INFO_REGION_NAME);
294 printf("ERROR: Hotplug info region is not setup\n");
299 #ifdef CVMX_BUILD_FOR_LINUX_USER
301 size_t pg_sz = sysconf(_SC_PAGESIZE), size;
306 if ((fd = open("/dev/mem", O_RDWR)) == -1) {
312 * We need to mmap() this memory, since this was allocated from the
313 * kernel bootup code and does not reside in the RESERVE32 region.
315 size = CVMX_APP_HOTPLUG_INFO_REGION_SIZE + pg_sz-1;
316 offset = block_desc->base_addr & ~(pg_sz-1);
317 if ((vaddr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset)) == MAP_FAILED)
323 hgp = (cvmx_app_hotplug_global_t *)(vaddr + ( block_desc->base_addr & (pg_sz-1)));
326 hgp = cvmx_phys_to_ptr(block_desc->base_addr);
329 hip = hgp->hotplug_info_array;
332 cvmx_dprintf("cvmx_app_hotplug_get_info(): hotplug_info phy addr 0x%llx ptr %p\n",
333 block_desc->base_addr, hgp);
336 /* Look for the current app's info */
338 for (i=0; i<CVMX_APP_HOTPLUG_MAX_APPS; i++)
340 if (hip[i].coremask == coremask)
343 cvmx_dprintf("cvmx_app_hotplug_get_info(): coremask match %d -- coremask 0x%x valid %d\n",
344 i, hip[i].coremask, hip[i].valid);
355 * This routine sends a shutdown request to a running target application.
357 * @param coremask Coremask the application is running on.
358 * @param wait 1 - Wait for shutdown completion
360 * @return 0 on success, -1 on error
364 int cvmx_app_hotplug_shutdown_request(uint32_t coremask, int wait)
367 cvmx_app_hotplug_info_t *hotplug_info_ptr;
369 if (!(hotplug_info_ptr = cvmx_app_hotplug_get_info(coremask)))
371 printf("\nERROR: Failed to get hotplug info for coremask: 0x%x\n", (unsigned int)coremask);
375 if (!hotplug_info_ptr->shutdown_callback)
377 printf("\nERROR: Target application has not registered for hotplug!\n");
381 if (hotplug_info_ptr->hotplug_activated_coremask != coremask)
383 printf("\nERROR: Not all application cores have activated hotplug\n");
387 /* Send IPIs to all application cores to request shutdown */
388 for (i=0; i<CVMX_MAX_CORES; i++) {
389 if (coremask & (1<<i))
390 cvmx_write_csr(CVMX_CIU_MBOX_SETX(i), 1);
395 while (!hotplug_info_ptr->shutdown_done);
397 /* Clean up the hotplug info region for this application */
398 bzero(hotplug_info_ptr, sizeof(*hotplug_info_ptr));