diff options
author | William Bryan <wilbryan@us.ibm.com> | 2016-04-18 17:07:34 -0500 |
---|---|---|
committer | William A. Bryan <wilbryan@us.ibm.com> | 2016-06-13 19:18:11 -0400 |
commit | a12f5be3e904bf5bb7aabb978f5e4d0cf1e8b969 (patch) | |
tree | 08e5fe4298b301d7441bbb4d450432651aefc5e6 /src/ssx/occhw | |
parent | dd417235fda3a7086940b974780193e51370367c (diff) | |
download | talos-occ-a12f5be3e904bf5bb7aabb978f5e4d0cf1e8b969.tar.gz talos-occ-a12f5be3e904bf5bb7aabb978f5e4d0cf1e8b969.zip |
Update SSX to latest in EKB
RTC: 132999
Change-Id: I29478c074e3086e0bf09b402d55782e03cb1f787
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/23394
Tested-by: FSP CI Jenkins
Reviewed-by: Wael El-Essawy <welessa@us.ibm.com>
Diffstat (limited to 'src/ssx/occhw')
-rw-r--r-- | src/ssx/occhw/Makefile | 2 | ||||
-rw-r--r-- | src/ssx/occhw/occhw.h | 43 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_async.c | 309 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_async.h | 186 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_async_gpe.c | 53 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_async_ocb.c | 478 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_async_pba.c | 472 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_cache.S | 2 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_core.h | 2 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_id.c | 53 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_id.h | 85 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_init.c | 176 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_irq.h | 31 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_irq_init.c | 58 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_ocb.c | 84 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_ocb.h | 22 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_pba.c | 125 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_pba.h | 66 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_scom.c | 181 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_scom.h | 24 | ||||
-rw-r--r-- | src/ssx/occhw/occhw_sramctl.h | 2 | ||||
-rw-r--r-- | src/ssx/occhw/ssx_port.h | 2 | ||||
-rw-r--r-- | src/ssx/occhw/ssxocchwfiles.mk | 2 |
23 files changed, 1452 insertions, 1006 deletions
diff --git a/src/ssx/occhw/Makefile b/src/ssx/occhw/Makefile index c16da5b..45101df 100644 --- a/src/ssx/occhw/Makefile +++ b/src/ssx/occhw/Makefile @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2015 +# Contributors Listed Below - COPYRIGHT 2015,2016 # [+] International Business Machines Corp. # # diff --git a/src/ssx/occhw/occhw.h b/src/ssx/occhw/occhw.h index c0f11df..fdaf97c 100644 --- a/src/ssx/occhw/occhw.h +++ b/src/ssx/occhw/occhw.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -35,12 +35,12 @@ /// \brief The OCCHW environment for SSX. // This is a 'circular' reference in SSX, but included here to simplify PGAS -// programming. +// programming. #ifndef HWMACRO_OCC -#define HWMACRO_OCC -#include "ppc405.h" -#endif + #define HWMACRO_OCC + #include "ppc405.h" +#endif // Can't include this here due to ordering issues. It's included in // ppc405_irq.h. @@ -83,7 +83,7 @@ /// The final 128MB of memory (the SRAM) is mapped both I- and /// D-cacheable. The other 7 high-memory regions aliased by the SRAM remain /// uncacheable, however SRAM alias region 29 is marked write-through. -/// +/// /// Low memory addresses (direct-map Mainstore via PBA) are I-cacheable /// but not D-cacheable to improve predicatability of execution times. /// However, we should not execute from mainstore after initialization. @@ -95,27 +95,27 @@ /// @{ #ifndef PPC405_ICCR_INITIAL -#define PPC405_ICCR_INITIAL 0xff000001 + #define PPC405_ICCR_INITIAL 0xff000001 #endif #ifndef PPC405_DCCR_INITIAL -#define PPC405_DCCR_INITIAL 0x00000001 + #define PPC405_DCCR_INITIAL 0x00000001 #endif #ifndef PPC405_DCWR_INITIAL -#define PPC405_DCWR_INITIAL 0x00000004 + #define PPC405_DCWR_INITIAL 0x00000004 #endif #ifndef PPC405_SGR_INITIAL -#define PPC405_SGR_INITIAL 0x00ff0000 + #define PPC405_SGR_INITIAL 0x00ff0000 #endif #ifndef PPC405_SU0R_INITIAL -#define PPC405_SU0R_INITIAL 0x00000000 + #define PPC405_SU0R_INITIAL 0x00000000 #endif #ifndef PPC405_SLER_INITIAL -#define PPC405_SLER_INITIAL 0x00000000 + #define PPC405_SLER_INITIAL 0x00000000 #endif /// @} @@ -157,7 +157,7 @@ #ifndef __ASSEMBLER__ -/// \page noncacheable_support Non-cacheable modes for OCCHW +/// \page noncacheable_support Non-cacheable modes for OCCHW /// /// In order to support evaluation of cache management strategies on /// performance, DMA buffers read/written by DMA devices can be declared as @@ -181,7 +181,7 @@ #ifndef NONCACHEABLE_SUPPORT -#define NONCACHEABLE_SUPPORT 0 + #define NONCACHEABLE_SUPPORT 0 #endif @@ -263,11 +263,11 @@ /// Flush/invalidate a region of memory #if NONCACHEABLE_SUPPORT -#define FLUSH(p, n) do {} while (0) -#define INVALIDATE(p, n) do {} while (0) + #define FLUSH(p, n) do {} while (0) + #define INVALIDATE(p, n) do {} while (0) #else -#define FLUSH(p, n) do {dcache_flush((p), (n));} while (0) -#define INVALIDATE(p, n) do {dcache_invalidate((p), (n));} while (0) + #define FLUSH(p, n) do {dcache_flush((p), (n));} while (0) + #define INVALIDATE(p, n) do {dcache_invalidate((p), (n));} while (0) #endif /* NONCACHEABLE_SUPPORT */ @@ -287,7 +287,8 @@ /// This type definition is considered a required definition for a port of /// SSX. -typedef struct { +typedef struct +{ char bogus[9]; } SsxLinkerSymbol; @@ -341,7 +342,7 @@ extern Ppc405MmuMap G_applet1_mmu_map; // 31 | 0xF8000000 - 0xffffffff (overlaps SRAM) #define USE_GENERIC_DCACHE_FLUSH_ALL 0 -#define OCCHW_FLUSH_ZERO_ADDRESS 0x20000000 -#define OCCHW_FLUSH_ZERO_DCCR 0x08000000 +#define OCCHW_FLUSH_ZERO_ADDRESS 0x40000000 +#define OCCHW_FLUSH_ZERO_DCCR 0x00800000 #endif /* __OCCHW_H__ */ diff --git a/src/ssx/occhw/occhw_async.c b/src/ssx/occhw/occhw_async.c index ae3273b..3efac8e 100644 --- a/src/ssx/occhw/occhw_async.c +++ b/src/ssx/occhw/occhw_async.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -109,7 +109,7 @@ /// and any thread pending on request completion has been maxde runnable. /// /// Normally the application should see the request state (\a request->state) -/// ASYNC_REQUEST_STATE_COMPLETE and a callback return code +/// ASYNC_REQUEST_STATE_COMPLETE and a callback return code /// (\a request=->callback_rc) of 0 which indicates that the job and callback /// both completed normally. If the request did not complete normally it /// could be due to one of several reasons. For further analysis the request @@ -163,7 +163,7 @@ static SsxDeque G_async_callback_queue; SsxDeque G_ipc_deferred_queue; //////////////////////////////////////////////////////////////////////////// -// FFDC +// FFDC //////////////////////////////////////////////////////////////////////////// /// Collect FFDC for the PLB (OCI) arbiter @@ -175,7 +175,7 @@ SsxDeque G_ipc_deferred_queue; /// Note: The PEAR and PESR hold error information for all OCI masters /// _except_ the OCC ICU and DCU. ICU and DCU errors are in the STO_PESR and /// STO_PEAR. Currently there is no need to collect those DCRs for 'async' -/// errors. +/// errors. void oci_ffdc(OciFfdc* ffdc, int master_id) @@ -209,11 +209,13 @@ oci_ffdc(OciFfdc* ffdc, int master_id) // captured the first time the request is run on the device. static inline int -async_request_run(AsyncRequest *request) +async_request_run(AsyncRequest* request) { - if (request->state != ASYNC_REQUEST_STATE_RUNNING) { + if (request->state != ASYNC_REQUEST_STATE_RUNNING) + { request->start_time = ssx_timebase_get(); } + request->state = ASYNC_REQUEST_STATE_RUNNING; return request->run_method(request); } @@ -229,7 +231,7 @@ async_request_run(AsyncRequest *request) // AsyncQueue objects. int -async_queue_create(AsyncQueue *queue, AsyncEngine engine) +async_queue_create(AsyncQueue* queue, AsyncEngine engine) { ssx_deque_sentinel_create(&(queue->deque)); queue->current = 0; @@ -244,7 +246,7 @@ async_queue_create(AsyncQueue *queue, AsyncEngine engine) // and async_request_deque(). static void -async_request_complete(AsyncRequest *request) +async_request_complete(AsyncRequest* request) { SsxMachineContext ctx; AsyncRequestCallback callback; @@ -256,19 +258,25 @@ async_request_complete(AsyncRequest *request) // Note that 'completed' here means only that the callback is complete. callback = request->callback; - if (!callback) { + + if (!callback) + { completed = 1; - } else if ((request->options & ASYNC_CALLBACK_IMMEDIATE) || - ((request->options & ASYNC_CALLBACK_NONCRITICAL) && - !__ssx_kernel_context_critical_interrupt())) { + } + else if ((request->options & ASYNC_CALLBACK_IMMEDIATE) || + ((request->options & ASYNC_CALLBACK_NONCRITICAL) && + !__ssx_kernel_context_critical_interrupt())) + { request->state = ASYNC_REQUEST_STATE_CALLBACK_RUNNING; request->callback_rc = callback(request->arg); completed = 1; - } else { + } + else + { request->state = ASYNC_REQUEST_STATE_CALLBACK_QUEUED; completed = 0; @@ -278,22 +286,29 @@ async_request_complete(AsyncRequest *request) // If the callback completed then we go ahead and cancel any timeout // and/or wake the thread if possible. In critical interrupt contexts // we always have to defer these operations, so we may lose 'complete' - // status. + // status. - if (completed && + if (completed && ((request->timeout != SSX_WAIT_FOREVER) || - (request->options & ASYNC_REQUEST_BLOCKING))) { + (request->options & ASYNC_REQUEST_BLOCKING))) + { - if (__ssx_kernel_context_critical_interrupt()) { + if (__ssx_kernel_context_critical_interrupt()) + { request->state = ASYNC_REQUEST_STATE_POSTPROCESSING; completed = 0; - } else { - if (request->timeout != SSX_WAIT_FOREVER) { + } + else + { + if (request->timeout != SSX_WAIT_FOREVER) + { ssx_timer_cancel(&(request->timer)); } - if (request->options & ASYNC_REQUEST_BLOCKING) { + + if (request->options & ASYNC_REQUEST_BLOCKING) + { ssx_semaphore_post(&(request->sem)); } } @@ -303,18 +318,24 @@ async_request_complete(AsyncRequest *request) // A truly completed job gets its completion state here. Otherwise we // have to schedule the deferred postprocessing. - if (completed) { - + if (completed) + { + request->state = request->completion_state; - } else { + } + else + { ssx_critical_section_enter(SSX_CRITICAL, &ctx); - if (request->options & ASYNC_CALLBACK_PRIORITY) { + if (request->options & ASYNC_CALLBACK_PRIORITY) + { ssx_deque_push_front(&G_async_callback_queue, &(request->deque)); - } else { + } + else + { ssx_deque_push_back(&G_async_callback_queue, &(request->deque)); } @@ -346,30 +367,35 @@ async_request_complete(AsyncRequest *request) // interrupts for that queue. void -async_handler(AsyncQueue *queue) +async_handler(AsyncQueue* queue) { - AsyncRequest *finished, *current; + AsyncRequest* finished, *current; int rc; // This loop is repeated as long as any job started in a loop completes // immediately. - do { + do + { // This API may be called on an idle queue, which indicates that we // should simply start the job on the head of the queue. Otherwise // save a pointer to the job that just finished and update its // end_time. - if (queue->state == ASYNC_QUEUE_STATE_IDLE) { + if (queue->state == ASYNC_QUEUE_STATE_IDLE) + { finished = 0; - } else { + } + else + { - finished = (AsyncRequest *)(queue->current); + finished = (AsyncRequest*)(queue->current); - if (SSX_ERROR_CHECK_KERNEL && (finished == 0)) { + if (SSX_ERROR_CHECK_KERNEL && (finished == 0)) + { SSX_PANIC(ASYNC_PHANTOM_INTERRUPT); } @@ -380,22 +406,28 @@ async_handler(AsyncQueue *queue) // If the queue is in an error state we will not schedule any further // jobs on this queue. Otherwise we start the next job running on the - // engine. + // engine. - if (queue->state == ASYNC_QUEUE_STATE_ERROR) { + if (queue->state == ASYNC_QUEUE_STATE_ERROR) + { queue->current = 0; rc = 0; - } else { + } + else + { - current = (AsyncRequest *)ssx_deque_pop_front(&(queue->deque)); + current = (AsyncRequest*)ssx_deque_pop_front(&(queue->deque)); queue->current = current; - if (current) { + if (current) + { queue->state = ASYNC_QUEUE_STATE_RUNNING; rc = async_request_run(current); - } else { + } + else + { queue->state = ASYNC_QUEUE_STATE_IDLE; rc = 0; } @@ -407,12 +439,14 @@ async_handler(AsyncQueue *queue) // next loop (it would have given an rc == // -ASYNC_REQUEST_COMPLETE). Otherwise complete the request. - if (finished != 0) { + if (finished != 0) + { async_request_complete(finished); } - } while (rc == -ASYNC_REQUEST_COMPLETE); + } + while (rc == -ASYNC_REQUEST_COMPLETE); } @@ -443,8 +477,8 @@ async_handler(AsyncQueue *queue) /// way at entry. /// /// \retval -ASYNC_REQUEST_NOT_COMPLETE This code is returned for requests that -/// do not complete successfully, but only if ASYNC_REQUEST_BLOCKING is -/// specified. The caller will need to examine the request state if necessary +/// do not complete successfully, but only if ASYNC_REQUEST_BLOCKING is +/// specified. The caller will need to examine the request state if necessary /// to determine whether the request failed, was cancelled or timed out. /// /// \todo Consider making the critical section priority depend on the device @@ -453,44 +487,56 @@ async_handler(AsyncQueue *queue) /// section. int -async_request_schedule(AsyncRequest *request) +async_request_schedule(AsyncRequest* request) { SsxMachineContext ctx = SSX_THREAD_MACHINE_CONTEXT_DEFAULT; // For GCC - AsyncQueue *queue; + AsyncQueue* queue; int rc; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(request == 0, ASYNC_INVALID_OBJECT_SCHEDULE); } rc = 0; ssx_critical_section_enter(SSX_CRITICAL, &ctx); - do { + do + { // Check to insure the request is idle (which check must be done in // the critical section), then start any required timeout. - if (SSX_ERROR_CHECK_API) { - if (!async_request_is_idle(request)) { + if (SSX_ERROR_CHECK_API) + { + if (!async_request_is_idle(request)) + { rc = -ASYNC_REQUEST_NOT_IDLE; break; } } - if (request->timeout != SSX_WAIT_FOREVER) { + if (request->timeout != SSX_WAIT_FOREVER) + { rc = ssx_timer_schedule(&(request->timer), request->timeout, 0); - if (rc) break; + + if (rc) + { + break; + } } - + // Enqueue the request and initialize the request state. queue = request->queue; - if (request->options & ASYNC_REQUEST_PRIORITY) { + if (request->options & ASYNC_REQUEST_PRIORITY) + { ssx_deque_push_front(&(queue->deque), &(request->deque)); - } else { + } + else + { ssx_deque_push_back(&(queue->deque), &(request->deque)); } @@ -502,21 +548,29 @@ async_request_schedule(AsyncRequest *request) // If the queue is idle, call the async_handler() to start the job. // Then block the calling thread if required. - if (queue->state == ASYNC_QUEUE_STATE_IDLE) { + if (queue->state == ASYNC_QUEUE_STATE_IDLE) + { async_handler(queue); } - if (request->options & ASYNC_REQUEST_BLOCKING) { + if (request->options & ASYNC_REQUEST_BLOCKING) + { rc = ssx_semaphore_pend(&(request->sem), SSX_WAIT_FOREVER); - if (rc) break; - if (!async_request_completed(request)) { + if (rc) + { + break; + } + + if (!async_request_completed(request)) + { rc = -ASYNC_REQUEST_NOT_COMPLETE; break; } } - } while (0); + } + while (0); ssx_critical_section_exit(&ctx); @@ -538,19 +592,23 @@ async_request_schedule(AsyncRequest *request) void async_error_handler(AsyncQueue* queue, uint8_t completion_state) { - AsyncRequest *finished; + AsyncRequest* finished; - finished = (AsyncRequest *)(queue->current); + finished = (AsyncRequest*)(queue->current); - if (SSX_ERROR_CHECK_KERNEL && (finished == 0)) { + if (SSX_ERROR_CHECK_KERNEL && (finished == 0)) + { SSX_PANIC(ASYNC_PHANTOM_ERROR); } - if (finished->error_method) { - if (finished->error_method(finished)) { + if (finished->error_method) + { + if (finished->error_method(finished)) + { queue->state = ASYNC_QUEUE_STATE_ERROR; } } + finished->abort_state = finished->state; finished->completion_state = completion_state; async_handler(queue); @@ -580,7 +638,7 @@ async_request_dequeue(AsyncRequest* request, uint8_t completion_state) // Time out an AsyncRequest // // This is an internal API, the timer callback used to time out long-running -// AsyncRequest. +// AsyncRequest. // // This timer callback must run in an SSX_CRITICAL critical section to // guarantee atomic access to the AsyncRequest object. @@ -588,7 +646,7 @@ async_request_dequeue(AsyncRequest* request, uint8_t completion_state) static void async_timeout(void* arg) { - AsyncRequest *request = (AsyncRequest*)arg; + AsyncRequest* request = (AsyncRequest*)arg; SsxMachineContext ctx; ssx_critical_section_enter(SSX_CRITICAL, &ctx); @@ -596,7 +654,8 @@ async_timeout(void* arg) // The behavior at timeout depends on the mode. We'll handle the cases // from easiest to hardest. - if (request->state & ASYNC_REQUEST_CALLBACK_GROUP) { + if (request->state & ASYNC_REQUEST_CALLBACK_GROUP) + { // If the request has already queued or is running the callback (which // could happen due to interrupt interleaving) then the request is @@ -604,24 +663,30 @@ async_timeout(void* arg) // ssx_timer_cancel() to cancel the timer. So there's nothing to do. - } else if (request->state & ASYNC_REQUEST_IDLE_GROUP) { + } + else if (request->state & ASYNC_REQUEST_IDLE_GROUP) + { // If the request is idle we panic - This can't happen as it would // indicate that the timer was not cancelled when the request - // finished. + // finished. SSX_PANIC(ASYNC_TIMEOUT_BUG); - } else if (request->state & ASYNC_REQUEST_QUEUED_GROUP) { + } + else if (request->state & ASYNC_REQUEST_QUEUED_GROUP) + { // If the request is still in the queue then we can simply cancel it, // which includes running the callback. - async_request_dequeue(request, ASYNC_REQUEST_STATE_TIMED_OUT); + async_request_dequeue(request, ASYNC_REQUEST_STATE_TIMED_OUT); - } else if (request->state & ASYNC_REQUEST_RUNNING_GROUP) { + } + else if (request->state & ASYNC_REQUEST_RUNNING_GROUP) + { // If the request is running on the hardware, then we need to call // the async_error_handler() to remove the job and restart the @@ -630,7 +695,9 @@ async_timeout(void* arg) async_error_handler(request->queue, ASYNC_REQUEST_STATE_TIMED_OUT); - } else { + } + else + { SSX_PANIC(ASYNC_INVALID_STATE); @@ -646,7 +713,7 @@ async_timeout(void* arg) // API does some error checking, and any errors will be returned by the // higher-level call. // -// \retval -ASYNC_INVALID_OBJECT_REQUEST The \a request or \a queue was +// \retval -ASYNC_INVALID_OBJECT_REQUEST The \a request or \a queue was /// null (0). // // \retval -ASYNC_INVALID_OPTIONS The \a options argument contains invalid @@ -658,23 +725,24 @@ async_timeout(void* arg) // non-NULL callback, but no protocol for running the callback was specified. int -async_request_create(AsyncRequest *request, - AsyncQueue *queue, +async_request_create(AsyncRequest* request, + AsyncQueue* queue, AsyncRunMethod run_method, AsyncErrorMethod error_method, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options) { - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF((request == 0) || (queue == 0), - ASYNC_INVALID_OBJECT_REQUEST); + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((request == 0) || (queue == 0), + ASYNC_INVALID_OBJECT_REQUEST); SSX_ERROR_IF((options & ~ASYNC_GENERIC_OPTIONS) || (__builtin_popcount(options & ASYNC_CALLBACK_OPTIONS) > 1), ASYNC_INVALID_OPTIONS); SSX_ERROR_IF(run_method == 0, ASYNC_INVALID_ARGUMENT); - SSX_ERROR_IF((callback != 0) && + SSX_ERROR_IF((callback != 0) && ((options & ASYNC_CALLBACK_OPTIONS) == 0), ASYNC_CALLBACK_PROTOCOL_UNSPECIFIED); } @@ -688,12 +756,14 @@ async_request_create(AsyncRequest *request, request->callback = callback; request->arg = arg; request->options = options; - - if (request->timeout != SSX_WAIT_FOREVER) { + + if (request->timeout != SSX_WAIT_FOREVER) + { ssx_timer_create(&(request->timer), async_timeout, (void*)request); } - if (options & ASYNC_REQUEST_BLOCKING) { + if (options & ASYNC_REQUEST_BLOCKING) + { ssx_semaphore_create(&(request->sem), 0, 1); } @@ -713,7 +783,7 @@ async_request_create(AsyncRequest *request, /// request, or NULL (0) is this data is not required. /// /// \retval 0 The request contains valid timestamps and they have been -/// returned. +/// returned. /// /// \retval -ASYNC_INVALID_TIMESTAMPS The caller's timestamps have been /// updated, but the timestamps are fully or partially invalid. This could be @@ -733,17 +803,23 @@ async_request_timestamps_get(AsyncRequest* request, ssx_critical_section_enter(SSX_CRITICAL, &ctx); - if (start_time) { + if (start_time) + { *start_time = request->start_time; } - if (end_time) { + + if (end_time) + { *end_time = request->end_time; } if ((request->state & ASYNC_REQUEST_IDLE_GROUP) && - (request->state != ASYNC_REQUEST_STATE_INITIALIZED)) { + (request->state != ASYNC_REQUEST_STATE_INITIALIZED)) + { rc = 0; - } else { + } + else + { rc = -ASYNC_INVALID_TIMESTAMPS; } @@ -761,7 +837,7 @@ async_request_timestamps_get(AsyncRequest* request, /// start time) computed from the timestamps of \a request. /// /// \retval 0 The request contains valid timestamps and they have been -/// returned. +/// returned. /// /// \retval -ASYNC_INVALID_TIMESTAMPS The latancy has been computed but may be /// invalid. This could be due to several reasons: @@ -785,7 +861,7 @@ async_request_latency(AsyncRequest* request, SsxTimebase* latency) // Dump an AsyncRequest #if 0 void -async_request_printk(AsyncRequest *request) +async_request_printk(AsyncRequest* request) { printk("----------------------------------------\n"); printk("-- AsyncRequest @ %p\n", request); @@ -848,50 +924,60 @@ SSX_IRQ_FAST2FULL(async_callback_handler, async_callback_handler_full); void async_request_finalize(AsyncRequest* request) { - if (request->state == ASYNC_REQUEST_STATE_CALLBACK_QUEUED) { + if (request->state == ASYNC_REQUEST_STATE_CALLBACK_QUEUED) + { request->state = ASYNC_REQUEST_STATE_CALLBACK_RUNNING; - if (request->options & ASYNC_CALLBACK_DEFERRED) { + if (request->options & ASYNC_CALLBACK_DEFERRED) + { ssx_interrupt_preemption_enable(); request->callback_rc = request->callback(request->arg); - } else { + } + else + { request->callback_rc = request->callback(request->arg); ssx_interrupt_preemption_enable(); } + ssx_interrupt_preemption_disable(); } request->state = request->completion_state; - if (request->timeout != SSX_WAIT_FOREVER) { + if (request->timeout != SSX_WAIT_FOREVER) + { ssx_timer_cancel(&(request->timer)); } - if (request->options & ASYNC_REQUEST_BLOCKING) { + if (request->options & ASYNC_REQUEST_BLOCKING) + { ssx_semaphore_post(&(request->sem)); } } void -async_callback_handler_full(void *arg, SsxIrqId irq, int priority) +async_callback_handler_full(void* arg, SsxIrqId irq, int priority) { SsxMachineContext ctx; - AsyncRequest *request; - ipc_msg_t *msg; + AsyncRequest* request; + ipc_msg_t* msg; ssx_irq_disable(irq); //Check for any async callbacks first - do { + do + { ssx_critical_section_enter(SSX_CRITICAL, &ctx); - request = (AsyncRequest *)ssx_deque_pop_front(&G_async_callback_queue); - if (!request) { + request = (AsyncRequest*)ssx_deque_pop_front(&G_async_callback_queue); + + if (!request) + { break; } @@ -899,29 +985,34 @@ async_callback_handler_full(void *arg, SsxIrqId irq, int priority) async_request_finalize(request); - } while (1); + } + while (1); ssx_critical_section_exit(&ctx); //Next, check for any deferred IPC messages - do { + do + { ssx_critical_section_enter(SSX_CRITICAL, &ctx); - msg = (ipc_msg_t *)ssx_deque_pop_front(&G_ipc_deferred_queue); - if (!msg) { + msg = (ipc_msg_t*)ssx_deque_pop_front(&G_ipc_deferred_queue); + + if (!msg) + { ssx_irq_status_clear(irq); break; } ssx_critical_section_exit(&ctx); -void ipc_process_msg(ipc_msg_t* msg); + void ipc_process_msg(ipc_msg_t* msg); //handle the command or response message in a noncritical context ipc_process_msg(msg); - } while (1); + } + while (1); ssx_critical_section_exit(&ctx); ssx_irq_enable(irq); @@ -942,7 +1033,7 @@ void ipc_process_msg(ipc_msg_t* msg); void async_edge_handler_setup(SsxIrqHandler handler, - void *arg, + void* arg, SsxIrqId irq, int priority) { @@ -957,7 +1048,7 @@ async_edge_handler_setup(SsxIrqHandler handler, void async_level_handler_setup(SsxIrqHandler handler, - void *arg, + void* arg, SsxIrqId irq, int priority, int polarity) diff --git a/src/ssx/occhw/occhw_async.h b/src/ssx/occhw/occhw_async.h index be2996f..2c3e842 100644 --- a/src/ssx/occhw/occhw_async.h +++ b/src/ssx/occhw/occhw_async.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -93,7 +93,7 @@ #ifndef __ASSEMBLER__ -typedef uint8_t AsyncEngine; + typedef uint8_t AsyncEngine; #endif /* __ASSEMBLER__ */ @@ -113,7 +113,8 @@ typedef uint8_t AsyncEngine; /// master on the OCI (SLW/GPE/OCB/PBA). Note that OCI errors from the 405 /// core will cause an immediate machine check exception. -typedef struct { +typedef struct +{ /// PLB arbiter Error Address Register /// @@ -236,11 +237,11 @@ oci_ffdc(OciFfdc* ffdc, int master_id); struct AsyncRequest; struct AsyncQueue; -typedef int (*AsyncRunMethod)(struct AsyncRequest *request); +typedef int (*AsyncRunMethod)(struct AsyncRequest* request); -typedef int (*AsyncErrorMethod)(struct AsyncRequest *request); +typedef int (*AsyncErrorMethod)(struct AsyncRequest* request); -typedef int (*AsyncRequestCallback)(void *); +typedef int (*AsyncRequestCallback)(void*); /// A generic request for the asynchronous request drivers /// @@ -266,7 +267,8 @@ typedef int (*AsyncRequestCallback)(void *); /// requests. If the \a error_method returns a non-0 code then the error is /// considered fatal and the queue stops. -typedef struct AsyncRequest { +typedef struct AsyncRequest +{ /// Generic queue management - the "base class" SsxDeque deque; @@ -297,7 +299,7 @@ typedef struct AsyncRequest { SsxTimer timer; /// The engine queue the request is/was scheduled on - struct AsyncQueue *queue; + struct AsyncQueue* queue; /// The "virtual" run method for the class AsyncRunMethod run_method; @@ -314,7 +316,7 @@ typedef struct AsyncRequest { AsyncRequestCallback callback; /// The argument of the callback - void *arg; + void* arg; /// The timeout value /// @@ -367,13 +369,13 @@ typedef struct AsyncRequest { int -async_request_create(AsyncRequest *request, - struct AsyncQueue *queue, +async_request_create(AsyncRequest* request, + struct AsyncQueue* queue, AsyncRunMethod run_method, AsyncErrorMethod error_method, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options); void @@ -395,7 +397,7 @@ async_request_finalize(AsyncRequest* request); /// \retval 1 The request is idle static inline int -async_request_is_idle(AsyncRequest *request) +async_request_is_idle(AsyncRequest* request) { return (request->state & ASYNC_REQUEST_IDLE_GROUP) != 0; } @@ -415,7 +417,7 @@ async_request_is_idle(AsyncRequest *request) /// \retval 1 The request has completed successfully. static inline int -async_request_completed(AsyncRequest *request) +async_request_completed(AsyncRequest* request) { return (request->state == ASYNC_REQUEST_STATE_COMPLETE); } @@ -431,7 +433,7 @@ async_request_latency(AsyncRequest* request, SsxTimebase* latency); void -async_request_printk(AsyncRequest *request); +async_request_printk(AsyncRequest* request); #endif /* __ASSEMBLER__ */ @@ -462,7 +464,8 @@ async_request_printk(AsyncRequest *request); /// high-priority jobs will run in the reverse order from which they were /// enqueued. -typedef struct AsyncQueue { +typedef struct AsyncQueue +{ /// The sentinel of the request queue SsxDeque deque; @@ -502,13 +505,13 @@ async_error_handler(AsyncQueue* queue, uint8_t completion_state); void async_edge_handler_setup(SsxIrqHandler handler, - void *arg, + void* arg, SsxIrqId irq, int priority); void async_level_handler_setup(SsxIrqHandler handler, - void *arg, + void* arg, SsxIrqId irq, int priority, int polarity); @@ -528,7 +531,8 @@ async_callbacks_initialize(SsxIrqId irq); struct GpeQueue; /// GPE FFDC -typedef struct { +typedef struct +{ uint32_t func_id; int32_t ipc_rc; int xir_dump_rc; @@ -546,7 +550,8 @@ typedef struct { /// e.g., to do ping-pong buffer management. None of the other fields should /// be directly modified by the application. -typedef struct { +typedef struct +{ /// The generic request AsyncRequest request; @@ -571,20 +576,20 @@ gpe_error_method(AsyncRequest* request); int gpe_request_create(GpeRequest* request, - struct GpeQueue* queue, - ipc_func_enum_t func_id, - void* cmd_data, - SsxInterval timeout, - AsyncRequestCallback callback, - void *arg, - int options); + struct GpeQueue* queue, + ipc_func_enum_t func_id, + void* cmd_data, + SsxInterval timeout, + AsyncRequestCallback callback, + void* arg, + int options); /// See async_request_schedule() for documentation. static inline int gpe_request_schedule(GpeRequest* request) { - return async_request_schedule((AsyncRequest *)request); + return async_request_schedule((AsyncRequest*)request); } //////////////////////////////////////////////////////////////////////////// @@ -597,7 +602,8 @@ gpe_request_schedule(GpeRequest* request) /// A GPE queue consists of a generic AsyncQueue to manage jobs on the /// engine. -typedef struct GpeQueue { +typedef struct GpeQueue +{ /// The generic request queue - the "base class" AsyncQueue queue; @@ -606,14 +612,14 @@ typedef struct GpeQueue { uint8_t ipc_target_id; /// Pointer to an IPC command message - ipc_async_cmd_t *ipc_cmd; + ipc_async_cmd_t* ipc_cmd; } GpeQueue; int -gpe_queue_create(GpeQueue *queue, - int engine); +gpe_queue_create(GpeQueue* queue, + int engine); #endif /* ASSEMBLER */ @@ -629,7 +635,8 @@ gpe_queue_create(GpeQueue *queue, /// structure are embedded in higher-level structures for the PBA bridge, BCE /// engines, and PBAX mechanism. -typedef struct { +typedef struct +{ /// FFDC from the PLB (OCI) arbiter OciFfdc oci_ffdc; @@ -674,7 +681,8 @@ typedef struct { /// direct bridge operations after OCC initialization. This structure extends /// the common PBA FFDC with information on how the slaves were programmed. -typedef struct { +typedef struct +{ /// Common FFDC PbaCommonFfdc common; @@ -694,7 +702,8 @@ typedef struct { /// Similar to the way the drivers are coded, the BCDE register forms are used /// to declare the structures. -typedef struct { +typedef struct +{ /// Common FFDC PbaCommonFfdc common; @@ -716,7 +725,8 @@ typedef struct { /// FFDC collected for PBAX send errors -typedef struct { +typedef struct +{ /// Common FFDC PbaCommonFfdc common; @@ -735,7 +745,8 @@ typedef struct { /// FFDC collected for PBAX receive errors -typedef struct { +typedef struct +{ /// Common FFDC PbaCommonFfdc common; @@ -757,7 +768,8 @@ typedef struct { /// A single global structure containing FFDC for all PBA functions -typedef struct { +typedef struct +{ /// FFDC for the generic bridge PbaBridgeFfdc bridge; @@ -770,10 +782,10 @@ typedef struct { /// FFDC for PBAX send PbaxSendFfdc pbax_send; - + /// FFDC for PBAX receive PbaxReceiveFfdc pbax_receive; - + } PbaUnitFfdc; #endif // __ASSEMBLER__ @@ -796,7 +808,8 @@ struct BceQueue; /// through the channel, the software layer allows any amount of data to be /// moved as a single request. -typedef struct { +typedef struct +{ /// The generic request AsyncRequest request; @@ -840,14 +853,14 @@ typedef struct { } BceRequest; int -bce_request_create(BceRequest *request, - struct BceQueue *queue, +bce_request_create(BceRequest* request, + struct BceQueue* queue, uint32_t bridge_address, uint32_t oci_address, size_t bytes, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options); #endif /* __ASSEMBLER__ */ @@ -874,7 +887,8 @@ bce_request_create(BceRequest *request, /// jobs on the engine and the PBA engine id. The BCDE and BCUE can use the /// same driver because their control interfaces are identical. -typedef struct BceQueue { +typedef struct BceQueue +{ /// The generic request queue AsyncQueue queue; @@ -886,12 +900,12 @@ typedef struct BceQueue { int -bce_queue_create(BceQueue *queue, +bce_queue_create(BceQueue* queue, int engine); int -bce_request_schedule(BceRequest *request); +bce_request_schedule(BceRequest* request); #endif /* __ASSEMBLER__ */ @@ -933,7 +947,8 @@ struct PbaxQueue; /// buffer size. For free-form communications an aggressive read protocol must /// be used. -typedef struct { +typedef struct +{ /// The generic request AsyncRequest request; @@ -942,7 +957,7 @@ typedef struct { /// /// This field is not modified by the drivers. The application may modify /// this field any time the PbaxRequest is idle. - uint64_t *data; + uint64_t* data; /// Number of bytes to move, which must be a multiple of 8. /// @@ -964,18 +979,18 @@ typedef struct { int -pbax_request_create(PbaxRequest *request, - struct PbaxQueue *queue, - uint64_t *data, +pbax_request_create(PbaxRequest* request, + struct PbaxQueue* queue, + uint64_t* data, size_t bytes, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options); int -pbax_request_schedule(PbaxRequest *request); +pbax_request_schedule(PbaxRequest* request); #endif /* __ASSEMBLER__ */ @@ -1004,7 +1019,8 @@ extern const SsxAddress pba_xshincn[]; /// A PBAX circular buffer queue consists of a generic AsyncQueue to manage /// jobs on the engine, a pointer to the data area and the PBAX engine id. -typedef struct PbaxQueue { +typedef struct PbaxQueue +{ /// The generic request queue AsyncQueue queue; @@ -1013,7 +1029,7 @@ typedef struct PbaxQueue { /// /// This data area must satisfy stringent alignment constraints; See the /// documentation for PbaxRequest. - uint64_t *cq_base; + uint64_t* cq_base; /// The number of 8-byte entries in the queue. /// @@ -1039,17 +1055,17 @@ typedef struct PbaxQueue { int -pbax_queue_create(PbaxQueue *queue, +pbax_queue_create(PbaxQueue* queue, int engine, - uint64_t *cq_base, + uint64_t* cq_base, size_t cq_entries, int protocol); int -pbax_queue_disable(PbaxQueue *queue); +pbax_queue_disable(PbaxQueue* queue); int -pbax_queue_enable(PbaxQueue *queue); +pbax_queue_enable(PbaxQueue* queue); int pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read); @@ -1069,7 +1085,7 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read); /// reasonably attributed to an OCB channel under the control of OCC, and 2) /// general errors signalled by the OCB direct bridge. Due to the myriad ways /// that OCB channels can be used the FFDC for OCB direct bridge errors is -/// stored globally rather than with particular requests or queues. +/// stored globally rather than with particular requests or queues. /// /// The OcbFfdc includes the PLB arbiter PEARL and PESR register state. /// This state is only collected if the error status indicates an OCI timeout @@ -1079,12 +1095,13 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read); /// then disable the channel since any further communication through the /// channel must be considered compromised. -typedef struct { +typedef struct +{ /// FFDC from the OCI (PLB) arbiter OciFfdc oci_ffdc; - /// A copy of the OCB OCC_LFIR register at the time of the error + /// A copy of the OCB OCC_LFIR register at the time of the error ocb_occlfir_t fir; /// A copy of the OCB Control/Status register for the channel at the time @@ -1127,7 +1144,8 @@ typedef struct { /// /// Contains FFDC structures for each channel and the direct bridge -typedef struct { +typedef struct +{ OcbFfdc channel[OCB_INDIRECT_CHANNELS]; OcbFfdc bridge; @@ -1178,14 +1196,15 @@ struct OcbQueue; /// partner has received the data, but simply that the data has been queued /// for reception and the caller may reuse/refill the data buffer if required. -typedef struct { +typedef struct +{ /// The generic request AsyncRequest request; /// Initial pointer to the data to be moved for write data, or the /// data area to hold read data. This field is not modified by the drivers. - uint64_t *data; + uint64_t* data; /// Number of bytes to move. This field is not modified by the drivers. size_t bytes; @@ -1201,18 +1220,18 @@ typedef struct { int -ocb_request_create(OcbRequest *request, - struct OcbQueue *queue, - uint64_t *data, +ocb_request_create(OcbRequest* request, + struct OcbQueue* queue, + uint64_t* data, size_t bytes, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options); int -ocb_request_schedule(OcbRequest *request); +ocb_request_schedule(OcbRequest* request); #endif /* __ASSEMBLER__ */ @@ -1225,7 +1244,7 @@ ocb_request_schedule(OcbRequest *request); // occhw_async.c - these constants are used as array indices. The code also // assumes this ordering for the access of G_ocb_ocbsesn[], and for // determining whether the engine is a PUSH or PULL queue. -// Note: push/pull queues for channel 3 have been deleted +// Note: push/pull queues for channel 3 have been deleted #define OCB_ENGINE_PUSH0 0 #define OCB_ENGINE_PULL0 1 @@ -1245,13 +1264,14 @@ ocb_request_schedule(OcbRequest *request); /// A OCB circular buffer queue consists of a generic AsyncQueue to manage /// jobs on the engine, a pointer to the data area and the OCB engine id. -typedef struct OcbQueue { +typedef struct OcbQueue +{ /// The generic request queue AsyncQueue queue; /// The base of the circular queue data area - must be 8-byte aligned - uint64_t *cq_base; + uint64_t* cq_base; /// The length of the queue in terms of the number of 8-byte entries in /// the queue. @@ -1272,9 +1292,9 @@ typedef struct OcbQueue { int -ocb_queue_create(OcbQueue *queue, +ocb_queue_create(OcbQueue* queue, int engine, - uint64_t *cq_base, + uint64_t* cq_base, size_t cq_length, int protocol); @@ -1476,7 +1496,7 @@ extern PbaxQueue G_pbax_read_queue[]; #define _PBAX_ALIGN_(length) \ (((length) <= 4) ? 32 : \ (((length) <= 8) ? 64 : \ - (((length) <= 16) ? 128 : 256))) + (((length) <= 16) ? 128 : 256))) #define PBAX_CQ_READ_BUFFER(buffer, length) \ uint64_t buffer[length] \ @@ -1490,20 +1510,20 @@ extern uint64_t G_pbax_read1_buffer[]; // Initialization APIs void -async_gpe_initialize(GpeQueue *queue, int engine); +async_gpe_initialize(GpeQueue* queue, int engine); void -async_bce_initialize(BceQueue *queue, int engine, SsxIrqId irq); +async_bce_initialize(BceQueue* queue, int engine, SsxIrqId irq); void -async_ocb_initialize(OcbQueue *queue, int engine, - uint64_t *buffer, size_t length, int protocol); +async_ocb_initialize(OcbQueue* queue, int engine, + uint64_t* buffer, size_t length, int protocol); void -async_pbax_initialize(PbaxQueue *queue, int engine, SsxIrqId irq, - uint64_t *buffer, size_t length, int protocol); +async_pbax_initialize(PbaxQueue* queue, int engine, SsxIrqId irq, + uint64_t* buffer, size_t length, int protocol); void diff --git a/src/ssx/occhw/occhw_async_gpe.c b/src/ssx/occhw/occhw_async_gpe.c index 524411d..b9835eb 100644 --- a/src/ssx/occhw/occhw_async_gpe.c +++ b/src/ssx/occhw/occhw_async_gpe.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -66,13 +66,14 @@ ipc_async_cmd_t G_async_ipc_cmd[ASYNC_NUM_GPE_QUEUES] SECTION_ATTRIBUTE(".noncac /// /// \retval -ASYNC_INVALID_OBJECT_PORE_QUEUE The \a queue was NULL (0). /// -/// \retval -ASYNC_INVALID_ENGINE_GPE The \a engine is not a (valid) +/// \retval -ASYNC_INVALID_ENGINE_GPE The \a engine is not a (valid) /// GPE engine. int -gpe_queue_create(GpeQueue *queue, int engine) +gpe_queue_create(GpeQueue* queue, int engine) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_GPE_QUEUE); SSX_ERROR_IF(!(engine & ASYNC_ENGINE_GPE), ASYNC_INVALID_ENGINE_GPE); SSX_ERROR_IF((ASYNC_ENG2GPE(engine) >= ASYNC_NUM_GPE_QUEUES), ASYNC_INVALID_ENGINE_GPE); @@ -105,14 +106,14 @@ gpe_async_handler(ipc_msg_t* rsp, void* arg) if(rsp->ipc_rc != IPC_RC_SUCCESS) { //calls gpe_error_method before calling async_handler - async_error_handler((AsyncQueue *)arg, ASYNC_REQUEST_STATE_FAILED); + async_error_handler((AsyncQueue*)arg, ASYNC_REQUEST_STATE_FAILED); } else { //handle async callbacks and process the next gpe request in the queue //(if any) - async_handler((AsyncQueue *) arg); + async_handler((AsyncQueue*) arg); } } @@ -149,7 +150,7 @@ gpe_async_handler(ipc_msg_t* rsp, void* arg) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_OBJECT_GPE_REQUEST The \a request was NULL (0) +/// \retval -ASYNC_INVALID_OBJECT_GPE_REQUEST The \a request was NULL (0) /// or the \a queue was NULL (0) or not a GpeQueue. /// /// \retval IPC_RC_INVALID_FUNC_ID The func_id has an invalid target id @@ -159,20 +160,21 @@ gpe_async_handler(ipc_msg_t* rsp, void* arg) /// call. int -gpe_request_create(GpeRequest *request, - GpeQueue *queue, +gpe_request_create(GpeRequest* request, + GpeQueue* queue, ipc_func_enum_t func_id, void* cmd_data, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options) { - AsyncQueue *async_queue = (AsyncQueue *)queue; + AsyncQueue* async_queue = (AsyncQueue*)queue; uint32_t targeted_func_id; int rc; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(!(async_queue->engine & ASYNC_ENGINE_GPE), ASYNC_INVALID_OBJECT_GPE_REQUEST); } @@ -186,6 +188,7 @@ gpe_request_create(GpeRequest *request, callback, arg, options); + if(!rc) { @@ -203,7 +206,7 @@ gpe_request_create(GpeRequest *request, //single target function IDs already have a target targeted_func_id = func_id; } - + //check that target id of the command matches the target id //of the queue. if (IPC_GET_TARGET_ID(targeted_func_id) != queue->ipc_target_id) @@ -230,13 +233,13 @@ gpe_request_create(GpeRequest *request, // // This routine sends an async_request to a GPE. // - + int -gpe_run_method(AsyncRequest *async_request) +gpe_run_method(AsyncRequest* async_request) { - GpeQueue *queue = (GpeQueue*)(async_request->queue); - GpeRequest *request = (GpeRequest*)async_request; - ipc_async_cmd_t *ipc_cmd = queue->ipc_cmd; + GpeQueue* queue = (GpeQueue*)(async_request->queue); + GpeRequest* request = (GpeRequest*)async_request; + ipc_async_cmd_t* ipc_cmd = queue->ipc_cmd; int rc; //Initialize the IPC command message @@ -277,21 +280,21 @@ gpe_run_method(AsyncRequest *async_request) int -gpe_error_method(AsyncRequest *async_request) +gpe_error_method(AsyncRequest* async_request) { - GpeQueue *queue = (GpeQueue*)(async_request->queue); - GpeRequest *request = (GpeRequest*)async_request; + GpeQueue* queue = (GpeQueue*)(async_request->queue); + GpeRequest* request = (GpeRequest*)async_request; // Collect data that could explain why a GPE command // couldn't be sent or timed out on the response and save it // in the ffdc fields - + //retrieve IPC data request->ffdc.func_id = queue->ipc_cmd->cmd.func_id.word32; request->ffdc.ipc_rc = queue->ipc_cmd->cmd.ipc_rc; - + //retrieve XIR data - request->ffdc.xir_dump_rc = + request->ffdc.xir_dump_rc = occhw_xir_dump(queue->ipc_target_id, &request->ffdc.xir_dump); return 0; @@ -303,7 +306,7 @@ gpe_error_method(AsyncRequest *async_request) //////////////////////////////////////////////////////////////////////////// void -async_gpe_initialize(GpeQueue *queue,int engine) +async_gpe_initialize(GpeQueue* queue, int engine) { gpe_queue_create(queue, engine); } diff --git a/src/ssx/occhw/occhw_async_ocb.c b/src/ssx/occhw/occhw_async_ocb.c index 1a0abef..9000c53 100644 --- a/src/ssx/occhw/occhw_async_ocb.c +++ b/src/ssx/occhw/occhw_async_ocb.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -45,16 +45,16 @@ OcbQueue G_ocb_write_queue[OCB_INDIRECT_CHANNELS]; #if OCB_READ0_LENGTH % CACHE_LINE_SIZE -#error "OCB read buffer 0 alignment error" + #error "OCB read buffer 0 alignment error" #endif #if OCB_READ1_LENGTH % CACHE_LINE_SIZE -#error "OCB read buffer 1 alignment error" + #error "OCB read buffer 1 alignment error" #endif #if OCB_READ2_LENGTH % CACHE_LINE_SIZE -#error "OCB read buffer 2 alignment error" + #error "OCB read buffer 2 alignment error" #endif #if OCB_READ3_LENGTH % CACHE_LINE_SIZE -#error "OCB read buffer 3 alignment error" + #error "OCB read buffer 3 alignment error" #endif // OCB circular queue write buffers must be 8-byte aligned per hardware @@ -94,33 +94,39 @@ OCB_CQ_WRITE_BUFFER(G_ocb_write3_buffer, OCB_WRITE3_LENGTH); /// OCB Stream Push/Pull Control/Status Register addresses static const SsxAddress G_ocb_ocbsxcsn[OCB_ENGINES] = - {OCB_OCBSHCS0, OCB_OCBSLCS0, - OCB_OCBSHCS1, OCB_OCBSLCS1, - OCB_OCBSHCS2, OCB_OCBSLCS2, - OCB_OCBSHCS3, OCB_OCBSLCS3}; +{ + OCB_OCBSHCS0, OCB_OCBSLCS0, + OCB_OCBSHCS1, OCB_OCBSLCS1, + OCB_OCBSHCS2, OCB_OCBSLCS2, + OCB_OCBSHCS3, OCB_OCBSLCS3 +}; /// OCB Stream Push/Pull Base Register addresses static const SsxAddress G_ocb_ocbsxbrn[OCB_ENGINES] = - {OCB_OCBSHBR0, OCB_OCBSLBR0, - OCB_OCBSHBR1, OCB_OCBSLBR1, - OCB_OCBSHBR2, OCB_OCBSLBR2, - OCB_OCBSHBR3, OCB_OCBSLBR3}; +{ + OCB_OCBSHBR0, OCB_OCBSLBR0, + OCB_OCBSHBR1, OCB_OCBSLBR1, + OCB_OCBSHBR2, OCB_OCBSLBR2, + OCB_OCBSHBR3, OCB_OCBSLBR3 +}; /// OCB Stream Push/Pull Increment Register addresses static const SsxAddress G_ocb_ocbsxin[OCB_ENGINES] = - {OCB_OCBSHI0, OCB_OCBSLI0, - OCB_OCBSHI1, OCB_OCBSLI1, - OCB_OCBSHI2, OCB_OCBSLI2, - OCB_OCBSHI3, OCB_OCBSLI3}; +{ + OCB_OCBSHI0, OCB_OCBSLI0, + OCB_OCBSHI1, OCB_OCBSLI1, + OCB_OCBSHI2, OCB_OCBSLI2, + OCB_OCBSHI3, OCB_OCBSLI3 +}; /// OCB Stream Error Status; There is only one register per OCB channel const SsxAddress G_ocb_ocbsesn[OCB_ENGINES / 2] = - {OCB_OCBSES0, OCB_OCBSES1, OCB_OCBSES2, OCB_OCBSES3}; +{OCB_OCBSES0, OCB_OCBSES1, OCB_OCBSES2, OCB_OCBSES3}; //////////////////////////////////////////////////////////////////////////// @@ -153,19 +159,26 @@ ocb_ffdc(int channel) ocb_ocbshcsn_t ocbshcsn; ocb_ocbslcsn_t ocbslcsn; - if (channel < 0) { + if (channel < 0) + { ffdc = &(G_ocb_ffdc.bridge); - } else { + } + else + { ffdc = &(G_ocb_ffdc.channel[channel]); } - if (ffdc->error == 0) { - - if (channel < 0) { + if (ffdc->error == 0) + { + + if (channel < 0) + { memset(ffdc, 0, sizeof(OcbFfdc)); - } else { + } + else + { getscom(OCB_OCBCSRN(channel), &(ffdc->csr.value)); @@ -199,7 +212,7 @@ ocb_ffdc(int channel) /// \param buf The caller's data buffer to receive the read data /// /// \param bytes The maximum number of bytes to read. This value must be an -/// even multiple of 8, as this API always reads multiples of 8 bytes. +/// even multiple of 8, as this API always reads multiples of 8 bytes. /// /// \param read The number of bytes actually copied from the device buffer to /// the caller's buffer. This may be returned as any value from 0 to \a @@ -209,7 +222,7 @@ ocb_ffdc(int channel) /// queue data area to the caller's data area, with the side effect of /// advancing the hardware queue pointers. ocb_read() does not implement /// locking, critical sections or any other type of synchronization for access -/// to the OCB queue data - that is the responsibility of the caller. +/// to the OCB queue data - that is the responsibility of the caller. /// /// ocb_read() may return an error code. This may indicate a preexisting /// error in the queue, or may be an error resulting from the current read. @@ -217,34 +230,37 @@ ocb_ffdc(int channel) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_ARGUMENT_OCB_READ The number of \a bytes is not +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_READ The number of \a bytes is not /// an even multiple of 8. /// -/// \retval -ASYNC_OCB_ERROR_READ_OLD or -ASYNC_OCB_ERROR_READ_NEW This code +/// \retval -ASYNC_OCB_ERROR_READ_OLD or -ASYNC_OCB_ERROR_READ_NEW This code /// indicates an error associated with the OCB channel represented by the queue. int -ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read) +ocb_read(OcbQueue* queue, void* buf, size_t bytes, size_t* read) { ocb_ocbshcsn_t csr; ocb_ocbsesn_t ses; unsigned qlen, read_ptr, write_ptr, to_read; - uint64_t *pcq, *pbuf; + uint64_t* pcq, *pbuf; int rc; - do { + do + { rc = 0; *read = 0; // If pre-existing errors exist then immediately abort the read. - if (G_ocb_ffdc.channel[queue->engine / 2].error) { + if (G_ocb_ffdc.channel[queue->engine / 2].error) + { rc = -ASYNC_OCB_ERROR_READ_OLD; break; } - if (bytes % 8) { + if (bytes % 8) + { rc = -ASYNC_INVALID_ARGUMENT_OCB_READ; break; } @@ -262,17 +278,26 @@ ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read) qlen = csr.fields.push_length + 1; read_ptr = csr.fields.push_read_ptr; - if (csr.fields.push_empty) { + if (csr.fields.push_empty) + { break; - } else if (csr.fields.push_full) { + } + else if (csr.fields.push_full) + { to_read = qlen; - } else { + } + else + { write_ptr = csr.fields.push_write_ptr; - if (read_ptr > write_ptr) { + + if (read_ptr > write_ptr) + { to_read = qlen - (read_ptr - write_ptr); - } else { + } + else + { to_read = write_ptr - read_ptr; } } @@ -288,12 +313,17 @@ ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read) // copied from the queue. pbuf = (uint64_t*)buf; - while (bytes && to_read--) { + + while (bytes && to_read--) + { read_ptr++; - if (read_ptr == qlen) { + + if (read_ptr == qlen) + { read_ptr = 0; } + pcq = queue->cq_base + read_ptr; dcache_invalidate_line(pcq); @@ -303,12 +333,15 @@ ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read) bytes -= 8; *read += 8; } - } while (0); + } + while (0); // Check for underflow errors. If found, collect FFDC. ses.value = in32(G_ocb_ocbsesn[queue->engine / 2]); - if (ses.fields.push_read_underflow) { + + if (ses.fields.push_read_underflow) + { ocb_ffdc(queue->engine / 2); rc = -ASYNC_OCB_ERROR_READ_NEW; } @@ -324,7 +357,7 @@ ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read) /// \param buf The caller's data buffer containing the write data /// /// \param bytes The maximum number of bytes to write. This value must be an -/// even multiple of 8, as this API always writes multiples of 8 bytes. +/// even multiple of 8, as this API always writes multiples of 8 bytes. /// /// \param written The number of bytes actually copied from the caller's buffer to /// the device buffer. This may be returned as any value from 0 to \a @@ -342,34 +375,37 @@ ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_ARGUMENT_OCB_WRITE The number of \a bytes is not +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_WRITE The number of \a bytes is not /// an even multiple of 8. /// -/// \retval -ASYNC_OCB_ERROR_WRITE_OLD or -ASYNC_OCB_ERROR_WRITE_NEW This code +/// \retval -ASYNC_OCB_ERROR_WRITE_OLD or -ASYNC_OCB_ERROR_WRITE_NEW This code /// indicates an error associated with the OCB channel represented by the queue. int -ocb_write(OcbQueue *queue, void* buf, size_t bytes, size_t* written) +ocb_write(OcbQueue* queue, void* buf, size_t bytes, size_t* written) { ocb_ocbslcsn_t csr; ocb_ocbsesn_t ses; unsigned qlen, read_ptr, write_ptr, free; - uint64_t *pcq, *pbuf; + uint64_t* pcq, *pbuf; int rc; - do { + do + { rc = 0; *written = 0; // Pre-existing errors immediately abort the read. - if (G_ocb_ffdc.channel[queue->engine / 2].error) { + if (G_ocb_ffdc.channel[queue->engine / 2].error) + { rc = -ASYNC_OCB_ERROR_WRITE_OLD; break; } - if (bytes % 8) { + if (bytes % 8) + { rc = -ASYNC_INVALID_ARGUMENT_OCB_WRITE; break; } @@ -386,17 +422,25 @@ ocb_write(OcbQueue *queue, void* buf, size_t bytes, size_t* written) qlen = csr.fields.pull_length + 1; write_ptr = csr.fields.pull_write_ptr; - if (csr.fields.pull_full) { + if (csr.fields.pull_full) + { break; } - if (csr.fields.pull_empty) { + if (csr.fields.pull_empty) + { free = qlen; - } else { + } + else + { read_ptr = csr.fields.pull_read_ptr; - if (write_ptr > read_ptr) { + + if (write_ptr > read_ptr) + { free = qlen - (write_ptr - read_ptr); - } else { + } + else + { free = read_ptr - write_ptr; } } @@ -411,12 +455,17 @@ ocb_write(OcbQueue *queue, void* buf, size_t bytes, size_t* written) // copied into the queue. pbuf = (uint64_t*)buf; - while (bytes && free--) { + + while (bytes && free--) + { write_ptr++; - if (write_ptr == qlen) { + + if (write_ptr == qlen) + { write_ptr = 0; } + pcq = queue->cq_base + write_ptr; *pcq = *pbuf++; @@ -426,12 +475,15 @@ ocb_write(OcbQueue *queue, void* buf, size_t bytes, size_t* written) bytes -= 8; *written += 8; } - } while (0); + } + while (0); // Check for overflow. If found, collect FFDC. ses.value = in32(G_ocb_ocbsesn[queue->engine / 2]); - if (ses.fields.pull_write_overflow) { + + if (ses.fields.pull_write_overflow) + { ocb_ffdc(queue->engine / 2); rc = -ASYNC_OCB_ERROR_WRITE_NEW; } @@ -443,21 +495,25 @@ ocb_write(OcbQueue *queue, void* buf, size_t bytes, size_t* written) // This is the internal 'run method' for reading through an OCB circular // queue. The run method simply enables the IRQ. The interrupt handler reads // data from the queue and leaves the interrupt enabled until the read is -// satisfied. +// satisfied. static int -ocb_read_method(AsyncRequest *async_request) +ocb_read_method(AsyncRequest* async_request) { - OcbRequest *request = (OcbRequest*)async_request; - OcbQueue *queue = (OcbQueue*)(async_request->queue); + OcbRequest* request = (OcbRequest*)async_request; + OcbQueue* queue = (OcbQueue*)(async_request->queue); int rc; - if (request->bytes == 0) { + if (request->bytes == 0) + { rc = -ASYNC_REQUEST_COMPLETE; - } else { + } + else + { ssx_irq_enable(queue->irq); rc = 0; } + return rc; } @@ -468,18 +524,22 @@ ocb_read_method(AsyncRequest *async_request) // satisfied. static int -ocb_write_method(AsyncRequest *async_request) +ocb_write_method(AsyncRequest* async_request) { - OcbRequest *request = (OcbRequest *)async_request; - OcbQueue *queue = (OcbQueue*)(async_request->queue); + OcbRequest* request = (OcbRequest*)async_request; + OcbQueue* queue = (OcbQueue*)(async_request->queue); int rc; - if (request->bytes == 0) { + if (request->bytes == 0) + { rc = -ASYNC_REQUEST_COMPLETE; - } else { + } + else + { ssx_irq_enable(queue->irq); rc = 0; } + return rc; } @@ -490,13 +550,13 @@ ocb_write_method(AsyncRequest *async_request) // the request. static int -ocb_async_error_method(AsyncRequest *request) +ocb_async_error_method(AsyncRequest* request) { - OcbQueue *queue = (OcbQueue*)(request->queue); + OcbQueue* queue = (OcbQueue*)(request->queue); ocb_ffdc(queue->engine / 2); return -1; } - + /// Create a request for an OCB circular queue /// @@ -536,27 +596,28 @@ ocb_async_error_method(AsyncRequest *request) /// \retval -ASYNC_INVALID_OBJECT_OCB_REQUEST The \a request or \a queue were NULL (0), or /// the \a queue is not an initialized OcbQueue. /// -/// \retval -ASYNC_INVALID_ARGUMENT_OCB_REQUEST The \a data pointer is +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_REQUEST The \a data pointer is /// NULL (0), or the number of bytes is not a multiple of 8. /// /// See async_request_create() for other errors that may be returned by this /// call. int -ocb_request_create(OcbRequest *request, - OcbQueue *queue, - uint64_t *data, +ocb_request_create(OcbRequest* request, + OcbQueue* queue, + uint64_t* data, size_t bytes, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options) { int rc; AsyncRunMethod run_method = 0; // Make GCC Happy - AsyncQueue *async_queue = (AsyncQueue *)queue; + AsyncQueue* async_queue = (AsyncQueue*)queue; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((request == 0) || (queue == 0) || !(async_queue->engine & ASYNC_ENGINE_OCB), @@ -566,21 +627,22 @@ ocb_request_create(OcbRequest *request, ASYNC_INVALID_ARGUMENT_OCB_REQUEST); } - switch (async_queue->engine) { - - case ASYNC_ENGINE_OCB_PULL0: - case ASYNC_ENGINE_OCB_PULL1: - case ASYNC_ENGINE_OCB_PULL2: - case ASYNC_ENGINE_OCB_PULL3: - run_method = ocb_write_method; - break; - - case ASYNC_ENGINE_OCB_PUSH0: - case ASYNC_ENGINE_OCB_PUSH1: - case ASYNC_ENGINE_OCB_PUSH2: - case ASYNC_ENGINE_OCB_PUSH3: - run_method = ocb_read_method; - break; + switch (async_queue->engine) + { + + case ASYNC_ENGINE_OCB_PULL0: + case ASYNC_ENGINE_OCB_PULL1: + case ASYNC_ENGINE_OCB_PULL2: + case ASYNC_ENGINE_OCB_PULL3: + run_method = ocb_write_method; + break; + + case ASYNC_ENGINE_OCB_PUSH0: + case ASYNC_ENGINE_OCB_PUSH1: + case ASYNC_ENGINE_OCB_PUSH2: + case ASYNC_ENGINE_OCB_PUSH3: + run_method = ocb_read_method; + break; } rc = async_request_create(&(request->request), @@ -610,22 +672,23 @@ ocb_request_create(OcbRequest *request, /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_ARGUMENT_OCB_SCHEDULE The number of \a bytes +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_SCHEDULE The number of \a bytes /// currently requested is not a multiple of 8. /// /// See async_request_schedule() for documentation of other errors int -ocb_request_schedule(OcbRequest *request) +ocb_request_schedule(OcbRequest* request) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((request->bytes % 8), ASYNC_INVALID_ARGUMENT_OCB_SCHEDULE); } request->current = request->data; request->remaining = request->bytes; - return async_request_schedule((AsyncRequest *)request); + return async_request_schedule((AsyncRequest*)request); } @@ -650,7 +713,7 @@ ocb_request_schedule(OcbRequest *request) /// buffer. The base register is also set up. void -ocb_read_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) +ocb_read_engine_reset(OcbQueue* queue, size_t cq_length, int protocol) { ocb_ocbshcsn_t cs; @@ -673,9 +736,12 @@ ocb_read_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) // Reprogram and reenable/reset the queue - if (protocol == OCB_INTERRUPT_PROTOCOL_LAZY) { + if (protocol == OCB_INTERRUPT_PROTOCOL_LAZY) + { cs.fields.push_intr_action = OCB_INTR_ACTION_FULL; - } else { + } + else + { cs.fields.push_intr_action = OCB_INTR_ACTION_NOT_EMPTY; } @@ -703,7 +769,7 @@ ocb_read_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) /// buffer. The base register is also set up. void -ocb_write_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) +ocb_write_engine_reset(OcbQueue* queue, size_t cq_length, int protocol) { ocb_ocbslcsn_t cs; @@ -726,9 +792,12 @@ ocb_write_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) // Reprogram and reenable/reset the queue - if (protocol == OCB_INTERRUPT_PROTOCOL_LAZY) { + if (protocol == OCB_INTERRUPT_PROTOCOL_LAZY) + { cs.fields.pull_intr_action = OCB_INTR_ACTION_EMPTY; - } else { + } + else + { cs.fields.pull_intr_action = OCB_INTR_ACTION_NOT_FULL; } @@ -765,7 +834,7 @@ ocb_write_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) /// /// \retval -ASYNC_INVALID_OBJECT_OCB_QUEUE The \a queue was NULL (0). /// -/// \retval -ASYNC_INVALID_ARGUMENT_OCB_QUEUE The \a cq_base is not properly +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_QUEUE The \a cq_base is not properly /// aligned, or the \a cq_length is invalid, or the \a protocol is invalid. /// /// \retval -ASYNC_INVALID_ENGINE_OCB The \a engine is not an OCB engine. @@ -773,16 +842,17 @@ ocb_write_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) /// Other errors may be returned by async_queue_create(). int -ocb_queue_create(OcbQueue *queue, +ocb_queue_create(OcbQueue* queue, int engine, - uint64_t *cq_base, + uint64_t* cq_base, size_t cq_length, int protocol) { - AsyncQueue *async_queue = (AsyncQueue *)queue; + AsyncQueue* async_queue = (AsyncQueue*)queue; int align_mask = 0; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_OCB_QUEUE); SSX_ERROR_IF((cq_length < OCB_PUSH_PULL_LENGTH_MIN) || (cq_length > OCB_PUSH_PULL_LENGTH_MAX) || @@ -794,72 +864,75 @@ ocb_queue_create(OcbQueue *queue, queue->cq_base = cq_base; queue->cq_length = cq_length; - switch (engine) { + switch (engine) + { // These are the read engines from OCC's perspective. - case ASYNC_ENGINE_OCB_PUSH0: - queue->irq = OCCHW_IRQ_STRM0_PUSH; - queue->engine = OCB_ENGINE_PUSH0; - goto read_engine; - - case ASYNC_ENGINE_OCB_PUSH1: - queue->irq = OCCHW_IRQ_STRM1_PUSH; - queue->engine = OCB_ENGINE_PUSH1; - goto read_engine; - - case ASYNC_ENGINE_OCB_PUSH2: - queue->irq = OCCHW_IRQ_STRM2_PUSH; - queue->engine = OCB_ENGINE_PUSH2; - goto read_engine; - - case ASYNC_ENGINE_OCB_PUSH3: - queue->irq = OCCHW_IRQ_STRM3_PUSH; - queue->engine = OCB_ENGINE_PUSH3; - goto read_engine; - - read_engine: - align_mask = CACHE_LINE_SIZE - 1; - async_queue_create(async_queue, engine); - ocb_read_engine_reset(queue, cq_length, protocol); - break; + case ASYNC_ENGINE_OCB_PUSH0: + queue->irq = OCCHW_IRQ_STRM0_PUSH; + queue->engine = OCB_ENGINE_PUSH0; + goto read_engine; + + case ASYNC_ENGINE_OCB_PUSH1: + queue->irq = OCCHW_IRQ_STRM1_PUSH; + queue->engine = OCB_ENGINE_PUSH1; + goto read_engine; + + case ASYNC_ENGINE_OCB_PUSH2: + queue->irq = OCCHW_IRQ_STRM2_PUSH; + queue->engine = OCB_ENGINE_PUSH2; + goto read_engine; + + case ASYNC_ENGINE_OCB_PUSH3: + queue->irq = OCCHW_IRQ_STRM3_PUSH; + queue->engine = OCB_ENGINE_PUSH3; + goto read_engine; + + read_engine: + align_mask = CACHE_LINE_SIZE - 1; + async_queue_create(async_queue, engine); + ocb_read_engine_reset(queue, cq_length, protocol); + break; // These are the write engines from OCC's perspective. - case ASYNC_ENGINE_OCB_PULL0: - queue->irq = OCCHW_IRQ_STRM0_PULL; - queue->engine = OCB_ENGINE_PULL0; - goto write_engine; - - case ASYNC_ENGINE_OCB_PULL1: - queue->irq = OCCHW_IRQ_STRM1_PULL; - queue->engine = OCB_ENGINE_PULL1; - goto write_engine; - - case ASYNC_ENGINE_OCB_PULL2: - queue->irq = OCCHW_IRQ_STRM2_PULL; - queue->engine = OCB_ENGINE_PULL2; - goto write_engine; - - case ASYNC_ENGINE_OCB_PULL3: - queue->irq = OCCHW_IRQ_STRM3_PULL; - queue->engine = OCB_ENGINE_PULL3; - goto write_engine; - - write_engine: - align_mask = 8 - 1; - async_queue_create(async_queue, engine); - ocb_write_engine_reset(queue, cq_length, protocol); - break; - - default: - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF(1, ASYNC_INVALID_ENGINE_OCB); - } + case ASYNC_ENGINE_OCB_PULL0: + queue->irq = OCCHW_IRQ_STRM0_PULL; + queue->engine = OCB_ENGINE_PULL0; + goto write_engine; + + case ASYNC_ENGINE_OCB_PULL1: + queue->irq = OCCHW_IRQ_STRM1_PULL; + queue->engine = OCB_ENGINE_PULL1; + goto write_engine; + + case ASYNC_ENGINE_OCB_PULL2: + queue->irq = OCCHW_IRQ_STRM2_PULL; + queue->engine = OCB_ENGINE_PULL2; + goto write_engine; + + case ASYNC_ENGINE_OCB_PULL3: + queue->irq = OCCHW_IRQ_STRM3_PULL; + queue->engine = OCB_ENGINE_PULL3; + goto write_engine; + + write_engine: + align_mask = 8 - 1; + async_queue_create(async_queue, engine); + ocb_write_engine_reset(queue, cq_length, protocol); + break; + + default: + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF(1, ASYNC_INVALID_ENGINE_OCB); + } } - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF(((uint32_t)cq_base & align_mask) != 0, + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF(((uint32_t)cq_base & align_mask) != 0, ASYNC_INVALID_ARGUMENT_OCB_QUEUE2); } @@ -883,35 +956,44 @@ ocb_queue_create(OcbQueue *queue, SSX_IRQ_FAST2FULL(ocb_async_handler, ocb_async_handler_full); void -ocb_async_handler_full(void *arg, SsxIrqId irq, int priority) +ocb_async_handler_full(void* arg, SsxIrqId irq, int priority) { - AsyncQueue *async_queue = (AsyncQueue*)arg; - OcbQueue *queue = (OcbQueue*)async_queue; - OcbRequest *request = (OcbRequest*)(async_queue->current); + AsyncQueue* async_queue = (AsyncQueue*)arg; + OcbQueue* queue = (OcbQueue*)async_queue; + OcbRequest* request = (OcbRequest*)(async_queue->current); size_t processed; int rc; - if (SSX_ERROR_CHECK_KERNEL && (request == 0)) { + if (SSX_ERROR_CHECK_KERNEL && (request == 0)) + { SSX_PANIC(ASYNC_PHANTOM_INTERRUPT_OCB); } - if (queue->engine % 2) { + if (queue->engine % 2) + { rc = ocb_write(queue, request->current, request->remaining, &processed); - } else { + } + else + { rc = ocb_read(queue, request->current, request->remaining, &processed); } - if (rc) { + if (rc) + { ssx_irq_disable(queue->irq); async_error_handler(async_queue, ASYNC_REQUEST_STATE_FAILED); - } else if (processed == request->remaining) { + } + else if (processed == request->remaining) + { ssx_irq_disable(queue->irq); async_handler(async_queue); - } else { + } + else + { request->current += (processed / 8); request->remaining -= processed; @@ -938,7 +1020,7 @@ ocb_async_handler_full(void *arg, SsxIrqId irq, int priority) SSX_IRQ_FAST2FULL(ocb_error_handler, ocb_error_handler_full); void -ocb_error_handler_full(void *arg, SsxIrqId irq, int priority) +ocb_error_handler_full(void* arg, SsxIrqId irq, int priority) { ocb_occlfir_t fir; ocb_occlfir_t fir_temp; @@ -948,23 +1030,34 @@ ocb_error_handler_full(void *arg, SsxIrqId irq, int priority) ssx_irq_status_clear(irq); getscom(OCB_OCCLFIR, &(fir.value)); - + fir_temp.value = 0; - fir_temp.fields.ocb_idc0_error = 1; - for (channel = 0; channel < OCB_INDIRECT_CHANNELS; channel++) { - if (fir.value & (fir_temp.value >> channel)) { + fir_temp.fields.ocb_idc0_error = 1; + + for (channel = 0; channel < OCB_INDIRECT_CHANNELS; channel++) + { + if (fir.value & (fir_temp.value >> channel)) + { queue = (AsyncQueue*)(&(G_ocb_read_queue[channel])); - if (queue->state == ASYNC_QUEUE_STATE_RUNNING) { + + if (queue->state == ASYNC_QUEUE_STATE_RUNNING) + { async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); - } else { + } + else + { ocb_ffdc(channel); } - + queue = (AsyncQueue*)(&(G_ocb_write_queue[channel])); - if (queue->state == ASYNC_QUEUE_STATE_RUNNING) { + + if (queue->state == ASYNC_QUEUE_STATE_RUNNING) + { async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); - } else { + } + else + { ocb_ffdc(channel); } } @@ -974,7 +1067,8 @@ ocb_error_handler_full(void *arg, SsxIrqId irq, int priority) fir.fields.ocb_db_oci_read_data_parity | fir.fields.ocb_db_oci_slave_error | fir.fields.ocb_pib_addr_parity_err | - fir.fields.ocb_db_pib_data_parity_err) { + fir.fields.ocb_db_pib_data_parity_err) + { ocb_ffdc(-1); } @@ -986,12 +1080,12 @@ ocb_error_handler_full(void *arg, SsxIrqId irq, int priority) //////////////////////////////////////////////////////////////////////////// void -async_ocb_initialize(OcbQueue *queue, int engine, - uint64_t *buffer, size_t length, int protocol) +async_ocb_initialize(OcbQueue* queue, int engine, + uint64_t* buffer, size_t length, int protocol) { ocb_queue_create(queue, engine, buffer, length, protocol); async_level_handler_setup(ocb_async_handler, - (void *)queue, + (void*)queue, queue->irq, SSX_NONCRITICAL, SSX_IRQ_POLARITY_ACTIVE_HIGH); diff --git a/src/ssx/occhw/occhw_async_pba.c b/src/ssx/occhw/occhw_async_pba.c index b4bc8fb..0ce0c27 100644 --- a/src/ssx/occhw/occhw_async_pba.c +++ b/src/ssx/occhw/occhw_async_pba.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -67,35 +67,35 @@ PBAX_CQ_READ_BUFFER(G_pbax_read1_buffer, PBAX_READ1_LENGTH); /// PBA BCDE/BCUE PowerBus BAR[0..31] static const SsxAddress G_bce_pbadr[BCE_ENGINES] = - {PBA_BCDE_PBADR, PBA_BCUE_PBADR}; +{PBA_BCDE_PBADR, PBA_BCUE_PBADR}; /// PBA BCDE/BCUE OCI BAR static const SsxAddress G_bce_ocibar[BCE_ENGINES] = - {PBA_BCDE_OCIBAR, PBA_BCUE_OCIBAR}; +{PBA_BCDE_OCIBAR, PBA_BCUE_OCIBAR}; /// PBA BCDE/BCUE SET register static const SsxAddress G_bce_set[BCE_ENGINES] = - {PBA_BCDE_SET, PBA_BCUE_SET}; +{PBA_BCDE_SET, PBA_BCUE_SET}; /// PBA BCDE/BCUE Control register static const SsxAddress G_bce_ctl[BCE_ENGINES] = - {PBA_BCDE_CTL, PBA_BCUE_CTL}; +{PBA_BCDE_CTL, PBA_BCUE_CTL}; /// PBA BCDE/BCUE Status register static const SsxAddress G_bce_stat[BCE_ENGINES] = - {PBA_BCDE_STAT, PBA_BCUE_STAT}; +{PBA_BCDE_STAT, PBA_BCUE_STAT}; /// PBAX Push Queue Control/Status Register addresses static const SsxAddress G_pba_xshcsn[PBAX_ENGINES] = - {PBA_XSHCS0, PBA_XSHCS1}; +{PBA_XSHCS0, PBA_XSHCS1}; /// PBAX Push Queue Base Register addresses static const SsxAddress G_pba_xshbrn[PBAX_ENGINES] = - {PBA_XSHBR0, PBA_XSHBR1}; +{PBA_XSHBR0, PBA_XSHBR1}; /// PBAX Push Queue Increment Register addresses static const SsxAddress G_pba_xshincn[PBAX_ENGINES] = - {PBA_XSHINC0, PBA_XSHINC1}; +{PBA_XSHINC0, PBA_XSHINC1}; //////////////////////////////////////////////////////////////////////////// @@ -120,21 +120,25 @@ pba_common_ffdc(PbaCommonFfdc* ffdc) { int i; - if (ffdc->error == 0) { + if (ffdc->error == 0) + { oci_ffdc(&(ffdc->oci_ffdc), OCI_MASTER_ID_PBA); ffdc->mode.value = in64(PBA_MODE); - - for (i = 0; i < PBA_READ_BUFFERS; i++) { + + for (i = 0; i < PBA_READ_BUFFERS; i++) + { getscom(PBA_RBUFVALN(i), &(ffdc->rbufval[i].value)); } - for (i = 0; i < PBA_WRITE_BUFFERS; i++) { + for (i = 0; i < PBA_WRITE_BUFFERS; i++) + { getscom(PBA_WBUFVALN(i), &(ffdc->wbufval[i].value)); } - for (i = 0; i < PBA_BARS; i++) { + for (i = 0; i < PBA_BARS; i++) + { getscom(PBA_BARN(i), &(ffdc->bar[i].value)); getscom(PBA_BARMSKN(i), &(ffdc->barmsk[i].value)); } @@ -159,13 +163,15 @@ pba_bridge_ffdc(PbaBridgeFfdc* ffdc) { int i; - if (ffdc->common.error == 0) { + if (ffdc->common.error == 0) + { pba_common_ffdc(&(ffdc->common)); ffdc->slvrst.value = in64(PBA_SLVRST); - for (i = 0; i > PBA_SLAVES; i++) { + for (i = 0; i > PBA_SLAVES; i++) + { ffdc->slvctl[i].value = in64(PBA_SLVCTLN(i)); } } @@ -179,7 +185,8 @@ pba_bridge_ffdc(PbaBridgeFfdc* ffdc) static void bce_ffdc(BceFfdc* ffdc, int engine) { - if (ffdc->common.error == 0) { + if (ffdc->common.error == 0) + { pba_common_ffdc(&(ffdc->common)); @@ -196,10 +203,11 @@ bce_ffdc(BceFfdc* ffdc, int engine) static void pbax_send_ffdc(PbaxSendFfdc* ffdc) { - if (ffdc->common.error == 0) { + if (ffdc->common.error == 0) + { pba_common_ffdc(&(ffdc->common)); - + ffdc->xcfg.value = in64(PBA_XCFG); ffdc->xsndtx.value = in64(PBA_XSNDTX); ffdc->xsndstat.value = in64(PBA_XSNDSTAT); @@ -217,14 +225,16 @@ pbax_receive_ffdc(PbaxReceiveFfdc* ffdc) { int i; - if (ffdc->common.error == 0) { + if (ffdc->common.error == 0) + { pba_common_ffdc(&(ffdc->common)); - + ffdc->xcfg.value = in64(PBA_XCFG); ffdc->xrcvstat.value = in64(PBA_XRCVSTAT); - - for (i = 0; i < PBAX_ENGINES; i++) { + + for (i = 0; i < PBAX_ENGINES; i++) + { ffdc->xshbrn[i].value = in64(PBA_XSHBRN(i)); ffdc->xshcsn[i].value = in64(PBA_XSHCSN(i)); } @@ -262,10 +272,10 @@ pbax_receive_ffdc(PbaxReceiveFfdc* ffdc) // register layout structures, but they work for BCUE as well. static int -bce_async_run_method(AsyncRequest *async_request) +bce_async_run_method(AsyncRequest* async_request) { - BceQueue *queue = (BceQueue *)(async_request->queue); - BceRequest *request = (BceRequest *)async_request; + BceQueue* queue = (BceQueue*)(async_request->queue); + BceRequest* request = (BceRequest*)async_request; int rc, engine; pba_bcde_pbadr_t pbadr; pba_bcde_set_t set; @@ -273,11 +283,14 @@ bce_async_run_method(AsyncRequest *async_request) size_t to_write; - if (request->remaining == 0) { + if (request->remaining == 0) + { rc = -ASYNC_REQUEST_COMPLETE; - } else { + } + else + { to_write = MIN(request->remaining, PBA_BCE_SIZE_MAX); @@ -314,7 +327,9 @@ bce_async_run_method(AsyncRequest *async_request) // Update the work remaining to be done. request->remaining -= to_write; - if (request->remaining != 0) { + + if (request->remaining != 0) + { request->next_bridge_address += to_write; request->next_oci_address += to_write; } @@ -333,19 +348,22 @@ bce_async_run_method(AsyncRequest *async_request) // whether to restart the queue. static int -bce_async_error_method(AsyncRequest *request) +bce_async_error_method(AsyncRequest* request) { - BceQueue *queue = (BceQueue*)(request->queue); + BceQueue* queue = (BceQueue*)(request->queue); int engine = queue->engine; - if (engine == BCE_ENGINE_BCDE) { + if (engine == BCE_ENGINE_BCDE) + { - bce_ffdc(&(G_pba_ffdc.bcde), engine); + bce_ffdc(&(G_pba_ffdc.bcde), engine); out32(PBA_BCDE_CTL, PBA_BCDE_CTL_STOP >> 32); - } else { + } + else + { - bce_ffdc(&(G_pba_ffdc.bcue), engine); + bce_ffdc(&(G_pba_ffdc.bcue), engine); out32(PBA_BCUE_CTL, PBA_BCUE_CTL_STOP >> 32); } @@ -396,28 +414,29 @@ bce_async_error_method(AsyncRequest *request) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_OBJECT_BCE_REQUEST The \a request was NULL (0), +/// \retval -ASYNC_INVALID_OBJECT_BCE_REQUEST The \a request was NULL (0), /// or the \a queue was NULL (0) or not a BceQueue. /// /// See async_request_create() for other errors that may be returned by this /// call. int -bce_request_create(BceRequest *request, - BceQueue *queue, +bce_request_create(BceRequest* request, + BceQueue* queue, uint32_t bridge_address, uint32_t oci_address, size_t bytes, SsxInterval timeout, AsyncRequestCallback callback, - void *arg, + void* arg, int options) { int rc; - AsyncQueue *async_queue = (AsyncQueue *)queue; + AsyncQueue* async_queue = (AsyncQueue*)queue; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((request == 0) || (queue == 0) || !(async_queue->engine & ASYNC_ENGINE_BCE), @@ -463,30 +482,34 @@ bce_request_create(BceRequest *request, /// \retval -ASYNC_INVALID_ENGINE_BCE The \a engine is not a PBA engine. int -bce_queue_create(BceQueue *queue, +bce_queue_create(BceQueue* queue, int engine) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_BCE_QUEUE); } - switch (engine) { + switch (engine) + { - case ASYNC_ENGINE_BCDE: - async_queue_create(&(queue->queue), engine); - queue->engine = BCE_ENGINE_BCDE; - break; + case ASYNC_ENGINE_BCDE: + async_queue_create(&(queue->queue), engine); + queue->engine = BCE_ENGINE_BCDE; + break; - case ASYNC_ENGINE_BCUE: - async_queue_create(&(queue->queue), engine); - queue->engine = BCE_ENGINE_BCUE; - break; + case ASYNC_ENGINE_BCUE: + async_queue_create(&(queue->queue), engine); + queue->engine = BCE_ENGINE_BCUE; + break; - default: - if (SSX_ERROR_CHECK_API) { - SSX_ERROR(ASYNC_INVALID_ENGINE_BCE); - } - break; + default: + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR(ASYNC_INVALID_ENGINE_BCE); + } + + break; } return 0; @@ -502,16 +525,17 @@ bce_queue_create(BceQueue *queue, /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_ARGUMENT_BCE_SCHEDULE Either the \a bridge_address +/// \retval -ASYNC_INVALID_ARGUMENT_BCE_SCHEDULE Either the \a bridge_address /// is not 128-byte aligned, or the OCI address is not 128-byte aligned, or the /// number of bytes is not a multiple of 128. /// /// See async_request_schedule() for documentation of other errors int -bce_request_schedule(BceRequest *request) +bce_request_schedule(BceRequest* request) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((request->bridge_address % POWERBUS_CACHE_LINE_SIZE) || (request->oci_address % POWERBUS_CACHE_LINE_SIZE) || (request->bytes % POWERBUS_CACHE_LINE_SIZE), @@ -522,7 +546,7 @@ bce_request_schedule(BceRequest *request) request->next_oci_address = request->oci_address; request->remaining = request->bytes; - return async_request_schedule((AsyncRequest *)request); + return async_request_schedule((AsyncRequest*)request); } @@ -538,19 +562,21 @@ bce_request_schedule(BceRequest *request) SSX_IRQ_FAST2FULL(bce_async_handler, bce_async_handler_full); void -bce_async_handler_full(void *arg, SsxIrqId irq, int priority) +bce_async_handler_full(void* arg, SsxIrqId irq, int priority) { - AsyncQueue *async_queue = (AsyncQueue *)arg; - AsyncRequest *async_current = (AsyncRequest *)async_queue->current; - BceQueue *queue = (BceQueue *)async_queue; + AsyncQueue* async_queue = (AsyncQueue*)arg; + AsyncRequest* async_current = (AsyncRequest*)async_queue->current; + BceQueue* queue = (BceQueue*)async_queue; out32(G_bce_ctl[queue->engine], 0); - if (SSX_ERROR_CHECK_KERNEL && (async_current == 0)) { + if (SSX_ERROR_CHECK_KERNEL && (async_current == 0)) + { SSX_PANIC(ASYNC_PHANTOM_INTERRUPT_BCE); } - if (async_current->run_method(async_current) == -ASYNC_REQUEST_COMPLETE) { + if (async_current->run_method(async_current) == -ASYNC_REQUEST_COMPLETE) + { async_handler(async_queue); } } @@ -577,10 +603,10 @@ bce_async_handler_full(void *arg, SsxIrqId irq, int priority) /// queue data area to the caller's data area, with the side effect of /// advancing the hardware queue pointers. pbax_read() does not implement /// locking, critical sections or any other type of synchronization for access -/// to the PBAX queue data. +/// to the PBAX queue data. /// -/// pbax_read() returns the error code -ASYNC_PBAX_ERROR_OLD or -/// -ASYNC_PBAX_ERROR_NEW if PBAX receive error status is asserted. +/// pbax_read() returns the error code -ASYNC_PBAX_ERROR_OLD or +/// -ASYNC_PBAX_ERROR_NEW if PBAX receive error status is asserted. /// The error return code may be disjoint from the actual /// read: If data is available it may be copied to the caller's buffer, but /// this data should always be considered corrupted in the event of an error @@ -588,7 +614,7 @@ bce_async_handler_full(void *arg, SsxIrqId irq, int priority) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_READ The number of \a bytes is not +/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_READ The number of \a bytes is not /// an even multiple of 8. /// /// \retval -ASYNC_PBAX_ERROR_OLD The PBA shows pre-existing error status @@ -605,10 +631,11 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read) pba_xshcsn_t csr; pba_xrcvstat_t rsr; unsigned qlen, read_ptr, write_ptr, to_read; - uint64_t *pcq, *pbuf; + uint64_t* pcq, *pbuf; int rc; - do { + do + { rc = 0; *read = 0; @@ -616,13 +643,16 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read) // If pre-existing errors exist then immediately abort the read. rsr.words.high_order = in32(PBA_XRCVSTAT); - if (rsr.fields.rcv_error) { + + if (rsr.fields.rcv_error) + { pbax_receive_ffdc(&(G_pba_ffdc.pbax_receive)); rc = -ASYNC_PBAX_ERROR_OLD; break; } - if (bytes % 8) { + if (bytes % 8) + { rc = -ASYNC_INVALID_ARGUMENT_PBAX_READ; break; } @@ -639,17 +669,26 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read) qlen = csr.fields.push_length + 1; read_ptr = csr.fields.push_read_ptr; - if (csr.fields.push_empty) { + if (csr.fields.push_empty) + { break; - } else if (csr.fields.push_full) { + } + else if (csr.fields.push_full) + { to_read = qlen; - } else { + } + else + { write_ptr = csr.fields.push_write_ptr; - if (read_ptr > write_ptr) { + + if (read_ptr > write_ptr) + { to_read = qlen - (read_ptr - write_ptr); - } else { + } + else + { to_read = write_ptr - read_ptr; } } @@ -664,27 +703,35 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read) // copied from the queue. pbuf = (uint64_t*) buf; - while (bytes && to_read--) { + + while (bytes && to_read--) + { read_ptr++; - if (read_ptr == qlen) { + + if (read_ptr == qlen) + { read_ptr = 0; } + pcq = queue->cq_base + read_ptr; dcache_invalidate_line(pcq); *pbuf++ = *pcq; - out32(G_pba_xshincn[queue->engine], 0); + out32(G_pba_xshincn[queue->engine], 0); bytes -= 8; *read += 8; } - } while(0); + } + while(0); // Check for errors that occurred during the read rsr.words.high_order = in32(PBA_XRCVSTAT); - if (rsr.fields.rcv_error) { + + if (rsr.fields.rcv_error) + { pbax_receive_ffdc(&(G_pba_ffdc.pbax_receive)); rc = -ASYNC_PBAX_ERROR_NEW; } @@ -699,18 +746,22 @@ pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read) // satisfied. int -pbax_read_method(AsyncRequest *async_request) +pbax_read_method(AsyncRequest* async_request) { - PbaxRequest *request = (PbaxRequest*)async_request; - PbaxQueue *queue = (PbaxQueue*)(async_request->queue); + PbaxRequest* request = (PbaxRequest*)async_request; + PbaxQueue* queue = (PbaxQueue*)(async_request->queue); int rc; - if (request->bytes == 0) { + if (request->bytes == 0) + { rc = -ASYNC_REQUEST_COMPLETE; - } else { + } + else + { ssx_irq_enable(queue->irq); rc = 0; } + return rc; } @@ -720,12 +771,12 @@ pbax_read_method(AsyncRequest *async_request) // Collect FFDC. static int -pbax_async_error_method(AsyncRequest *request) +pbax_async_error_method(AsyncRequest* request) { pbax_receive_ffdc(&(G_pba_ffdc.pbax_receive)); return -1; } - + /// Create a request for a PBAX read queue /// @@ -761,10 +812,10 @@ pbax_async_error_method(AsyncRequest *request) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_OBJECT_PBAX_REQUEST The \a request or \a queue +/// \retval -ASYNC_INVALID_OBJECT_PBAX_REQUEST The \a request or \a queue /// were NULL (0), or the \a queue is not an initialized PbaxQueue. /// -/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_REQUEST The \a data pointer is +/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_REQUEST The \a data pointer is /// NULL (0), or the number of bytes is not a multiple of 8. /// /// See async_request_create() for other errors that may be returned by this @@ -783,7 +834,8 @@ pbax_request_create(PbaxRequest* request, int rc; AsyncQueue* async_queue = (AsyncQueue*)queue; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((request == 0) || (queue == 0) || !(async_queue->engine & ASYNC_ENGINE_PBAX), @@ -817,22 +869,23 @@ pbax_request_create(PbaxRequest* request, /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE The number of \a bytes +/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE The number of \a bytes /// currently requested is not a multiple of 8. /// /// See async_request_schedule() for documentation of other errors int -pbax_request_schedule(PbaxRequest *request) +pbax_request_schedule(PbaxRequest* request) { - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF((request->bytes % 8),ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE); + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((request->bytes % 8), ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE); } request->current = request->data; request->remaining = request->bytes; - return async_request_schedule((AsyncRequest *)request); + return async_request_schedule((AsyncRequest*)request); } @@ -846,19 +899,20 @@ pbax_request_schedule(PbaxRequest *request) /// /// Disable the PBAX recieve mechanism for a particular PBAX receive queue. /// Interrupts are disabled, and any data managed by the queue is effectively -/// lost. +/// lost. /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_OBJECT_PBAX_DISABLE The \a queue is NULL (0) -/// or otherwise invalid. +/// \retval -ASYNC_INVALID_OBJECT_PBAX_DISABLE The \a queue is NULL (0) +/// or otherwise invalid. int -pbax_queue_disable(PbaxQueue *queue) +pbax_queue_disable(PbaxQueue* queue) { pba_xshcsn_t cs; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_PBAX_DISABLE); } @@ -882,18 +936,19 @@ pbax_queue_disable(PbaxQueue *queue) /// /// \retval 0 Success /// -/// \retval -ASYNC_INVALID_OBJECT_PBAX_DISABLE The \a queue is NULL (0) -/// or otherwise invalid. +/// \retval -ASYNC_INVALID_OBJECT_PBAX_DISABLE The \a queue is NULL (0) +/// or otherwise invalid. int -pbax_queue_enable(PbaxQueue *queue) +pbax_queue_enable(PbaxQueue* queue) { int rc; pba_xshcsn_t cs; rc = pbax_queue_disable(queue); - if (!rc) { + if (!rc) + { // Reinitialize the data buffer base address register and // reprogram/re-enable the queue. @@ -902,9 +957,12 @@ pbax_queue_enable(PbaxQueue *queue) cs.value = 0; - if (queue->protocol == PBAX_INTERRUPT_PROTOCOL_LAZY) { + if (queue->protocol == PBAX_INTERRUPT_PROTOCOL_LAZY) + { cs.fields.push_intr_action = PBAX_INTR_ACTION_FULL; - } else { + } + else + { cs.fields.push_intr_action = PBAX_INTR_ACTION_NOT_EMPTY; } @@ -913,6 +971,7 @@ pbax_queue_enable(PbaxQueue *queue) out32(G_pba_xshcsn[queue->engine], cs.words.high_order); } + return 0; } @@ -944,7 +1003,7 @@ pbax_queue_enable(PbaxQueue *queue) /// /// \retval -ASYNC_INVALID_OBJECT_PBAX_QUEUE The \a queue was NULL (0). /// -/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_QUEUE The \a cq_base is not properly +/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_QUEUE The \a cq_base is not properly /// aligned, or the \a cq_length is invalid, or the \a protocol is invalid. /// /// \retval -ASYNC_INVALID_ENGINE_PBAX The \a engine is not an PBAX engine. @@ -952,18 +1011,19 @@ pbax_queue_enable(PbaxQueue *queue) /// Other errors may be returned by async_queue_create(). int -pbax_queue_create(PbaxQueue *queue, +pbax_queue_create(PbaxQueue* queue, int engine, - uint64_t *cq_base, + uint64_t* cq_base, size_t cq_entries, int protocol) { - AsyncQueue *async_queue = (AsyncQueue *)queue; + AsyncQueue* async_queue = (AsyncQueue*)queue; - if (SSX_ERROR_CHECK_API) { - uint32_t align_mask = - POW2_32(MAX(CEILING_LOG2(cq_entries * 8), - LOG_CACHE_LINE_SIZE)) - 1; + if (SSX_ERROR_CHECK_API) + { + uint32_t align_mask = + POW2_32(MAX(CEILING_LOG2(cq_entries * 8), + LOG_CACHE_LINE_SIZE)) - 1; SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_PBAX_QUEUE); SSX_ERROR_IF((((uint32_t)(cq_base) & align_mask) != 0) || @@ -978,22 +1038,24 @@ pbax_queue_create(PbaxQueue *queue, queue->cq_entries = cq_entries; queue->protocol = protocol; - switch (engine) { + switch (engine) + { - case ASYNC_ENGINE_PBAX_PUSH0: - queue->irq = OCCHW_IRQ_PBAX_OCC_PUSH0; - queue->engine = PBAX_ENGINE_PUSH0; - break; + case ASYNC_ENGINE_PBAX_PUSH0: + queue->irq = OCCHW_IRQ_PBAX_OCC_PUSH0; + queue->engine = PBAX_ENGINE_PUSH0; + break; - case ASYNC_ENGINE_PBAX_PUSH1: - queue->irq = OCCHW_IRQ_PBAX_OCC_PUSH1; - queue->engine = PBAX_ENGINE_PUSH1; - break; + case ASYNC_ENGINE_PBAX_PUSH1: + queue->irq = OCCHW_IRQ_PBAX_OCC_PUSH1; + queue->engine = PBAX_ENGINE_PUSH1; + break; - default: - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF(1, ASYNC_INVALID_ENGINE_PBAX); - } + default: + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF(1, ASYNC_INVALID_ENGINE_PBAX); + } } async_queue_create(async_queue, engine); @@ -1019,7 +1081,7 @@ pbax_queue_create(PbaxQueue *queue, SSX_IRQ_FAST2FULL(pbax_async_handler, pbax_async_handler_full); void -pbax_async_handler_full(void *arg, SsxIrqId irq, int priority) +pbax_async_handler_full(void* arg, SsxIrqId irq, int priority) { AsyncQueue* async_queue = (AsyncQueue*)arg; PbaxQueue* queue = (PbaxQueue*)async_queue; @@ -1027,23 +1089,29 @@ pbax_async_handler_full(void *arg, SsxIrqId irq, int priority) size_t read; int rc; - if (SSX_ERROR_CHECK_KERNEL && (request == 0)) { + if (SSX_ERROR_CHECK_KERNEL && (request == 0)) + { SSX_PANIC(ASYNC_PHANTOM_INTERRUPT_PBAX); } rc = pbax_read(queue, request->current, request->remaining, &read); - if (rc) { + if (rc) + { ssx_irq_disable(queue->irq); async_error_handler(async_queue, ASYNC_REQUEST_STATE_FAILED); - } else if (read == request->remaining) { + } + else if (read == request->remaining) + { ssx_irq_disable(queue->irq); async_handler(async_queue); - } else { + } + else + { request->current += (read / 8); request->remaining -= read; @@ -1090,7 +1158,7 @@ pbax_async_handler_full(void *arg, SsxIrqId irq, int priority) SSX_IRQ_FAST2FULL(pba_error_handler, pba_error_handler_full); void -pba_error_handler_full(void *arg, SsxIrqId irq, int priority) +pba_error_handler_full(void* arg, SsxIrqId irq, int priority) { pba_fir_t fir; pba_bcde_stat_t bcde_stat; @@ -1109,27 +1177,38 @@ pba_error_handler_full(void *arg, SsxIrqId irq, int priority) xrcvstat.words.high_order = in32(PBA_XRCVSTAT); queue = (AsyncQueue*)(&G_pba_bcde_queue); + if (bcde_stat.fields.error && - (queue->state == ASYNC_QUEUE_STATE_RUNNING)) { + (queue->state == ASYNC_QUEUE_STATE_RUNNING)) + { async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); } queue = (AsyncQueue*)(&G_pba_bcue_queue); - if (bcue_stat.fields.error && - (queue->state == ASYNC_QUEUE_STATE_RUNNING)) { + + if (bcue_stat.fields.error && + (queue->state == ASYNC_QUEUE_STATE_RUNNING)) + { async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); } - if (xsndstat.fields.snd_error) { + if (xsndstat.fields.snd_error) + { pbax_send_ffdc(&G_pba_ffdc.pbax_send); } - if (xrcvstat.fields.rcv_error) { - for (channel = 0; channel < PBAX_CHANNELS; channel++) { + if (xrcvstat.fields.rcv_error) + { + for (channel = 0; channel < PBAX_CHANNELS; channel++) + { queue = (AsyncQueue*)(&G_pbax_read_queue[channel]); - if (queue->state == ASYNC_REQUEST_STATE_RUNNING) { + + if (queue->state == ASYNC_REQUEST_STATE_RUNNING) + { async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); - } else { + } + else + { pbax_receive_ffdc(&G_pba_ffdc.pbax_receive); } } @@ -1138,52 +1217,53 @@ pba_error_handler_full(void *arg, SsxIrqId irq, int priority) // Any FIR bits not already attributable to previously handled errors are // assumed to be due to the generic bridge. - if (fir.value & + if (fir.value & ( - PBA_FIR_OCI_APAR_ERR || - PBA_FIR_PB_RDADRERR_FW || - PBA_FIR_PB_RDDATATO_FW || - PBA_FIR_PB_SUE_FW || - PBA_FIR_PB_UE_FW || - PBA_FIR_PB_CE_FW || - PBA_FIR_OCI_SLAVE_INIT || - PBA_FIR_OCI_WRPAR_ERR || - PBA_FIR_OCI_REREQTO || - PBA_FIR_PB_UNEXPCRESP || - PBA_FIR_PB_UNEXPDATA || - PBA_FIR_PB_PARITY_ERR || - PBA_FIR_PB_WRADRERR_FW || - PBA_FIR_PB_BADCRESP || - PBA_FIR_PB_ACKDEAD_FW || - PBA_FIR_PB_CRESPTO || - // PBA_FIR_BCUE_SETUP_ERR || - // PBA_FIR_BCUE_PB_ACK_DEAD || - // PBA_FIR_BCUE_PB_ADRERR || - // PBA_FIR_BCUE_OCI_DATAERR || - // PBA_FIR_BCDE_SETUP_ERR || - // PBA_FIR_BCDE_PB_ACK_DEAD || - // PBA_FIR_BCDE_PB_ADRERR || - // PBA_FIR_BCDE_RDDATATO_ERR || - // PBA_FIR_BCDE_SUE_ERR || - // PBA_FIR_BCDE_UE_ERR || - // PBA_FIR_BCDE_CE || - // PBA_FIR_BCDE_OCI_DATAERR || - PBA_FIR_INTERNAL_ERR || - PBA_FIR_ILLEGAL_CACHE_OP || - PBA_FIR_OCI_BAD_REG_ADDR || - // PBA_FIR_AXPUSH_WRERR || - // PBA_FIR_AXRCV_DLO_ERR || - // PBA_FIR_AXRCV_DLO_TO || - // PBA_FIR_AXRCV_RSVDATA_TO || - // PBA_FIR_AXFLOW_ERR || - // PBA_FIR_AXSND_DHI_RTYTO || - // PBA_FIR_AXSND_DLO_RTYTO || - // PBA_FIR_AXSND_RSVTO || - // PBA_FIR_AXSND_RSVERR || - PBA_FIR_FIR_PARITY_ERR || - PBA_FIR_FIR_PARITY_ERR2 - ) - ) { + PBA_FIR_OCI_APAR_ERR || + PBA_FIR_PB_RDADRERR_FW || + PBA_FIR_PB_RDDATATO_FW || + PBA_FIR_PB_SUE_FW || + PBA_FIR_PB_UE_FW || + PBA_FIR_PB_CE_FW || + PBA_FIR_OCI_SLAVE_INIT || + PBA_FIR_OCI_WRPAR_ERR || + PBA_FIR_OCI_REREQTO || + PBA_FIR_PB_UNEXPCRESP || + PBA_FIR_PB_UNEXPDATA || + PBA_FIR_PB_PARITY_ERR || + PBA_FIR_PB_WRADRERR_FW || + PBA_FIR_PB_BADCRESP || + PBA_FIR_PB_ACKDEAD_FW || + PBA_FIR_PB_CRESPTO || + // PBA_FIR_BCUE_SETUP_ERR || + // PBA_FIR_BCUE_PB_ACK_DEAD || + // PBA_FIR_BCUE_PB_ADRERR || + // PBA_FIR_BCUE_OCI_DATAERR || + // PBA_FIR_BCDE_SETUP_ERR || + // PBA_FIR_BCDE_PB_ACK_DEAD || + // PBA_FIR_BCDE_PB_ADRERR || + // PBA_FIR_BCDE_RDDATATO_ERR || + // PBA_FIR_BCDE_SUE_ERR || + // PBA_FIR_BCDE_UE_ERR || + // PBA_FIR_BCDE_CE || + // PBA_FIR_BCDE_OCI_DATAERR || + PBA_FIR_INTERNAL_ERR || + PBA_FIR_ILLEGAL_CACHE_OP || + PBA_FIR_OCI_BAD_REG_ADDR || + // PBA_FIR_AXPUSH_WRERR || + // PBA_FIR_AXRCV_DLO_ERR || + // PBA_FIR_AXRCV_DLO_TO || + // PBA_FIR_AXRCV_RSVDATA_TO || + // PBA_FIR_AXFLOW_ERR || + // PBA_FIR_AXSND_DHI_RTYTO || + // PBA_FIR_AXSND_DLO_RTYTO || + // PBA_FIR_AXSND_RSVTO || + // PBA_FIR_AXSND_RSVERR || + PBA_FIR_FIR_PARITY_ERR || + PBA_FIR_FIR_PARITY_ERR2 + ) + ) + { pba_bridge_ffdc(&(G_pba_ffdc.bridge)); } @@ -1195,11 +1275,11 @@ pba_error_handler_full(void *arg, SsxIrqId irq, int priority) //////////////////////////////////////////////////////////////////////////// void -async_bce_initialize(BceQueue *queue, int engine, SsxIrqId irq) +async_bce_initialize(BceQueue* queue, int engine, SsxIrqId irq) { bce_queue_create(queue, engine); async_level_handler_setup(bce_async_handler, - (void *)queue, + (void*)queue, irq, SSX_CRITICAL, SSX_IRQ_POLARITY_ACTIVE_HIGH); @@ -1208,13 +1288,13 @@ async_bce_initialize(BceQueue *queue, int engine, SsxIrqId irq) void -async_pbax_initialize(PbaxQueue *queue, int engine, SsxIrqId irq, - uint64_t *buffer, size_t length, int protocol) +async_pbax_initialize(PbaxQueue* queue, int engine, SsxIrqId irq, + uint64_t* buffer, size_t length, int protocol) { pbax_queue_create(queue, engine, buffer, length, protocol); pbax_queue_enable(queue); async_level_handler_setup(pbax_async_handler, - (void *)queue, + (void*)queue, irq, SSX_NONCRITICAL, SSX_IRQ_POLARITY_ACTIVE_HIGH); diff --git a/src/ssx/occhw/occhw_cache.S b/src/ssx/occhw/occhw_cache.S index 052021b..1a7a05b 100644 --- a/src/ssx/occhw/occhw_cache.S +++ b/src/ssx/occhw/occhw_cache.S @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/occhw/occhw_core.h b/src/ssx/occhw/occhw_core.h index b576e40..c483f6f 100644 --- a/src/ssx/occhw/occhw_core.h +++ b/src/ssx/occhw/occhw_core.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/occhw/occhw_id.c b/src/ssx/occhw/occhw_id.c index ab6f5bc..816ae0c 100644 --- a/src/ssx/occhw/occhw_id.c +++ b/src/ssx/occhw/occhw_id.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -80,7 +80,7 @@ cfam_id(void) return G_cfam_id; } -uint8_t +uint8_t cfam_chip_type(void) { return G_cfam_chip_type; @@ -101,7 +101,7 @@ cfam_ec_level(void) // Note: Ex-chiplets start at chiplet 16 and are left-justified in the // ChipConfig. - + ChipConfig G_chip_configuration SECTION_ATTRIBUTE(".noncacheable") = 0; uint64_t G_core_configuration SECTION_ATTRIBUTE(".noncacheable") = 0; @@ -115,29 +115,44 @@ uint64_t G_core_configuration SECTION_ATTRIBUTE(".noncacheable") = 0; void _occhw_get_chip_configuration(void) { - if (SIMICS_ENVIRONMENT) { + if (SIMICS_ENVIRONMENT) + { pmc_core_deconfiguration_reg_t pcdr; pcdr.value = in32(PMC_CORE_DECONFIGURATION_REG); - G_chip_configuration = - ~((uint64_t)(pcdr.fields.core_chiplet_deconf_vector) << 48); + G_chip_configuration = + ~((uint64_t)(pcdr.fields.core_chiplet_deconf_vector) << 48); - } else { + } + else + { uint64_t select, configuration; int rc; - + rc = getscom(0x000f0008, &select); /* TP CHIPLET SELECT */ - if (rc) SSX_PANIC(OCCHW_ID_SCOM_ERROR_SELECT); - if (select != 0) SSX_PANIC(OCCHW_ID_SELECT_ERROR); - - rc = getscom(MC_ADDRESS(0x000f0012, - MC_GROUP_EX_CORE, - PCB_MULTICAST_SELECT), + + if (rc) + { + SSX_PANIC(OCCHW_ID_SCOM_ERROR_SELECT); + } + + if (select != 0) + { + SSX_PANIC(OCCHW_ID_SELECT_ERROR); + } + + rc = getscom(MC_ADDRESS(0x000f0012, + MC_GROUP_EX_CORE, + PCB_MULTICAST_SELECT), &configuration); - if (rc) SSX_PANIC(OCCHW_ID_SCOM_ERROR_CONFIG); - + + if (rc) + { + SSX_PANIC(OCCHW_ID_SCOM_ERROR_CONFIG); + } + G_chip_configuration = (configuration << 16) & 0xffff000000000000ull; } @@ -150,8 +165,8 @@ uint32_t core_configuration(void) return G_core_configuration >> 32; } - - - + + + diff --git a/src/ssx/occhw/occhw_id.h b/src/ssx/occhw/occhw_id.h index d591f6a..d9c2b56 100644 --- a/src/ssx/occhw/occhw_id.h +++ b/src/ssx/occhw/occhw_id.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -54,7 +54,7 @@ /// For example, to identify a chip as Murano DD1.0, one could use either /// method shown below: /// -/// \code +/// \code /// /// if (cfam_id() == CFAM_CHIP_ID_MURANO_10) { ... } /// @@ -72,50 +72,50 @@ #ifndef __ASSEMBLER__ -#include <stdint.h> -#include "tpc_firmware_registers.h" + #include <stdint.h> + #include "tpc_firmware_registers.h" -/// Get TPC device identification (internal API, called once from __occhw_setup(). -void -_occhw_get_ids(void); + /// Get TPC device identification (internal API, called once from __occhw_setup(). + void + _occhw_get_ids(void); -/// Get the TPC Node Id -uint8_t node_id(void); + /// Get the TPC Node Id + uint8_t node_id(void); -/// Get the TPC Chip Id -uint8_t chip_id(void); + /// Get the TPC Chip Id + uint8_t chip_id(void); -/// Get the CFAM Chip Id -/// -/// \returns A 32-bit value to be compared against the enumeration of known -/// CFAM ids. See \ref cfam_chip_ids. -uint32_t cfam_id(void); + /// Get the CFAM Chip Id + /// + /// \returns A 32-bit value to be compared against the enumeration of known + /// CFAM ids. See \ref cfam_chip_ids. + uint32_t cfam_id(void); -/// Get the CFAM Chip Type -/// -/// \returns An 8-bit value to be compared against the enumeration of known -/// CFAM chip types. See \ref cfam_chip_types. -uint8_t cfam_chip_type(void); + /// Get the CFAM Chip Type + /// + /// \returns An 8-bit value to be compared against the enumeration of known + /// CFAM chip types. See \ref cfam_chip_types. + uint8_t cfam_chip_type(void); -/// Get the CFAM Chip EC Level -/// -/// \returns An 8-bit value; The high-order nibble is the major EC level and -/// the low-order nibble is the minor EC level. Fore example a value of 0x21 -/// indicates DD 2.1. -uint8_t cfam_ec_level(void); + /// Get the CFAM Chip EC Level + /// + /// \returns An 8-bit value; The high-order nibble is the major EC level and + /// the low-order nibble is the minor EC level. Fore example a value of 0x21 + /// indicates DD 2.1. + uint8_t cfam_ec_level(void); -/// Compute the chip configuration (internal API, called once from __occhw_setup(). -void -_occhw_get_chip_configuration(void); + /// Compute the chip configuration (internal API, called once from __occhw_setup(). + void + _occhw_get_chip_configuration(void); -/// Get the core configuration -/// -/// The return value is a 32 bit integer with big-endian bits set to indicate -/// valid cores. -uint32_t -core_configuration(void); + /// Get the core configuration + /// + /// The return value is a 32 bit integer with big-endian bits set to indicate + /// valid cores. + uint32_t + core_configuration(void); #endif // __ASSEMBLER__ @@ -138,9 +138,9 @@ core_configuration(void); /// \defgroup cfam_chip_ids CFAM Chip Ids (Including Centaur) /// /// The CFAM Chip ID is a 32-bit value that uniquely identfies a chip and its -/// EC level. +/// EC level. /// -/// The reference: +/// The reference: /// /// - https://eclipz.pok.ibm.com/sys/ras/docs/cfam_ids.txt /// @@ -175,9 +175,11 @@ core_configuration(void); /// The CFAM ID as a set of fields -typedef union { +typedef union +{ #ifdef _BIG_ENDIAN - struct { + struct + { uint32_t majorEc : 4; uint32_t location : 4; uint32_t minorEc : 4; @@ -185,7 +187,8 @@ typedef union { uint32_t vendor : 12; }; #else - struct { + struct + { uint32_t vendor : 12; uint32_t chipType : 8; uint32_t minorEc : 4; diff --git a/src/ssx/occhw/occhw_init.c b/src/ssx/occhw/occhw_init.c index bbb67bd..0ac9805 100644 --- a/src/ssx/occhw/occhw_init.c +++ b/src/ssx/occhw/occhw_init.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -43,8 +43,8 @@ #include "string_stream.h" #if USE_RTX_IO -// This file is not avilable to OCC FW builds -#include "rtx_stdio.h" + // This file is not avilable to OCC FW builds + #include "rtx_stdio.h" #endif // We need to make sure that the PLB arbiter is set up correctly to obtain @@ -101,29 +101,30 @@ plb_arbiter_setup() // defined on cacheable data sections. #ifdef CACHE_INHIBIT_ALL -#define CACHE_INHIBIT_TEXT 1 -#define CACHE_INHIBIT_DATA 1 + #define CACHE_INHIBIT_TEXT 1 + #define CACHE_INHIBIT_DATA 1 #endif #if CACHE_INHIBIT_TEXT -#define TEXT_CACHEABILITY_FLAG TLBLO_I + #define TEXT_CACHEABILITY_FLAG TLBLO_I #else -#define TEXT_CACHEABILITY_FLAG 0 + #define TEXT_CACHEABILITY_FLAG 0 #endif #if CACHE_INHIBIT_DATA -#define DATA_CACHEABILITY_FLAG TLBLO_I -#define WRITETHROUGH_FLAG 0 + #define DATA_CACHEABILITY_FLAG TLBLO_I + #define WRITETHROUGH_FLAG 0 #else -#define DATA_CACHEABILITY_FLAG 0 -#define WRITETHROUGH_FLAG TLBLO_W + #define DATA_CACHEABILITY_FLAG 0 + #define WRITETHROUGH_FLAG TLBLO_W #endif // This structure contains all of the fields necessary to create a MMU // mapping. -typedef struct { +typedef struct +{ SsxAddress base; size_t size; uint32_t tlbhi_flags; @@ -136,58 +137,64 @@ typedef struct { // mappings may be later modified. Ppc405MmuMap G_ex_free_mmu_map; -Ppc405MmuMap G_applet0_mmu_map; -Ppc405MmuMap G_applet1_mmu_map; - -static const MmuRegion mmu_regions[] = { - - {(SsxAddress)&_TEXT0_SECTION_BASE, - (size_t)&_TEXT0_SECTION_SIZE, - 0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0} , - - {(SsxAddress)&_TEXT1_SECTION_BASE, - (size_t)&_TEXT1_SECTION_SIZE, - 0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0} , - - {(SsxAddress)&_RODATA_SECTION_BASE, - (size_t)&_RODATA_SECTION_SIZE, - 0, DATA_CACHEABILITY_FLAG, 0} , - - {(SsxAddress)&_NONCACHEABLE_RO_SECTION_BASE, - (size_t)&_NONCACHEABLE_RO_SECTION_SIZE, - 0, TLBLO_I, 0} , - - {(SsxAddress)&_NONCACHEABLE_SECTION_BASE, - (size_t)&_NONCACHEABLE_SECTION_SIZE, - 0, TLBLO_I | TLBLO_WR, 0} , - - {(SsxAddress)&_WRITETHROUGH_SECTION_BASE, - (size_t)&_WRITETHROUGH_SECTION_SIZE, - 0, DATA_CACHEABILITY_FLAG | WRITETHROUGH_FLAG | TLBLO_WR, 0} , - - {(SsxAddress)&_DATA_SECTION_BASE, - (size_t)&_DATA_SECTION_SIZE, - 0, DATA_CACHEABILITY_FLAG | TLBLO_WR, 0} , - - {(SsxAddress)&_EX_FREE_SECTION_BASE, - (size_t)&_EX_FREE_SECTION_SIZE, - 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_EX | TLBLO_WR, - &G_ex_free_mmu_map}, - -/* - {(SsxAddress)&_APPLET0_SECTION_BASE, - (size_t)&_APPLET0_SECTION_SIZE, - 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_WR | TLBLO_EX, - &G_applet0_mmu_map}, - - {(SsxAddress)&_APPLET1_SECTION_BASE, - (size_t)&_APPLET1_SECTION_SIZE, - 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_WR | TLBLO_EX, - &G_applet1_mmu_map}, -*/ - {(SsxAddress)OCI_REGISTER_SPACE_BASE, - (size_t)OCI_REGISTER_SPACE_SIZE, - 0, TLBLO_WR | TLBLO_I | TLBLO_G, 0} , + +static const MmuRegion mmu_regions[] = +{ + + { + (SsxAddress)& _TEXT0_SECTION_BASE, + (size_t)& _TEXT0_SECTION_SIZE, + 0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0 + } , + + { + (SsxAddress)& _TEXT1_SECTION_BASE, + (size_t)& _TEXT1_SECTION_SIZE, + 0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0 + } , + + { + (SsxAddress)& _RODATA_SECTION_BASE, + (size_t)& _RODATA_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG, 0 + } , + + { + (SsxAddress)& _NONCACHEABLE_RO_SECTION_BASE, + (size_t)& _NONCACHEABLE_RO_SECTION_SIZE, + 0, TLBLO_I, 0 + } , + + { + (SsxAddress)& _NONCACHEABLE_SECTION_BASE, + (size_t)& _NONCACHEABLE_SECTION_SIZE, + 0, TLBLO_I | TLBLO_WR, 0 + } , + + { + (SsxAddress)& _WRITETHROUGH_SECTION_BASE, + (size_t)& _WRITETHROUGH_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG | WRITETHROUGH_FLAG | TLBLO_WR, 0 + } , + + { + (SsxAddress)& _DATA_SECTION_BASE, + (size_t)& _DATA_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG | TLBLO_WR, 0 + } , + + { + (SsxAddress)& _EX_FREE_SECTION_BASE, + (size_t)& _EX_FREE_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_EX | TLBLO_WR, + &G_ex_free_mmu_map + }, + + { + (SsxAddress)OCI_REGISTER_SPACE_BASE, + (size_t)OCI_REGISTER_SPACE_SIZE, + 0, TLBLO_WR | TLBLO_I | TLBLO_G, 0 + } , }; /// OCCHW MMU setup @@ -208,8 +215,11 @@ occhw_mmu_setup() ppc405_mmu_reset(); regions = sizeof(mmu_regions) / sizeof(MmuRegion); - for (i = 0; i < regions; i++) { - if (mmu_regions[i].size != 0) { + + for (i = 0; i < regions; i++) + { + if (mmu_regions[i].size != 0) + { ppc405_mmu_map(mmu_regions[i].base, mmu_regions[i].base, mmu_regions[i].size, @@ -261,19 +271,19 @@ io_setup() SSXOUT_TRACE_BUFFER_SIZE, SSX_FILE_OP_LOCK_CRITICAL); - stdout = (FILE *)(&G_ssxout); - stderr = (FILE *)(&G_ssxout); - ssxout = (FILE *)(&G_ssxout); + stdout = (FILE*)(&G_ssxout); + stderr = (FILE*)(&G_ssxout); + ssxout = (FILE*)(&G_ssxout); #elif USE_EPM_IO linear_stream_create(&G_ssxout, &G_ssxout_buffer, - SSXOUT_TRACE_BUFFER_SIZE, - SSX_FILE_OP_LOCK_CRITICAL); + SSXOUT_TRACE_BUFFER_SIZE, + SSX_FILE_OP_LOCK_CRITICAL); - stdout = (FILE *)(&G_ssxout); - stderr = (FILE *)(&G_ssxout); - ssxout = (FILE *)(&G_ssxout); + stdout = (FILE*)(&G_ssxout); + stderr = (FILE*)(&G_ssxout); + ssxout = (FILE*)(&G_ssxout); #elif USE_RTX_IO @@ -281,10 +291,10 @@ io_setup() rtx_stdout_create(&rtx_stdout); rtx_stderr_create(&rtx_stderr); - stdin = (FILE *)(&rtx_stdin); - stdout = (FILE *)(&rtx_stdout); - stderr = (FILE *)(&rtx_stderr); - ssxout = (FILE *)(&rtx_stdout); + stdin = (FILE*)(&rtx_stdin); + stdout = (FILE*)(&rtx_stdout); + stderr = (FILE*)(&rtx_stderr); + ssxout = (FILE*)(&rtx_stdout); printf("Initialize the RTX stdio.\n"); printf("RTX stdin is not implemented.\n"); @@ -295,10 +305,10 @@ io_setup() simics_stdout_create(&simics_stdout); simics_stderr_create(&simics_stderr); - stdin = (FILE *)(&simics_stdin); - stdout = (FILE *)(&simics_stdout); - stderr = (FILE *)(&simics_stderr); - ssxout = (FILE *)(&simics_stdout); + stdin = (FILE*)(&simics_stdin); + stdout = (FILE*)(&simics_stdout); + stderr = (FILE*)(&simics_stderr); + ssxout = (FILE*)(&simics_stdout); printf("Initialize the Simics stdio.\n"); @@ -390,7 +400,7 @@ __occhw_setup() // Setup requires SCOM, which requires a timeout. Therefore we need to set // up a default timebase frequency, which may be overridden during - // ssx_initialize(). + // ssx_initialize(). __ssx_timebase_frequency_hz = 600000000; __ssx_timebase_frequency_khz = 600000; diff --git a/src/ssx/occhw/occhw_irq.h b/src/ssx/occhw/occhw_irq.h index b5c25c0..aea8b41 100644 --- a/src/ssx/occhw/occhw_irq.h +++ b/src/ssx/occhw/occhw_irq.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -52,7 +52,7 @@ #ifndef __ASSEMBLER__ -/// Enable an interrupt by clearing the mask bit. +/// Enable an interrupt by clearing the mask bit. UNLESS__PPC405_IRQ_CORE_C__(extern) inline void @@ -99,9 +99,12 @@ UNLESS__PPC405_IRQ_CORE_C__(extern) inline void ssx_irq_status_set(SsxIrqId irq, int value) { - if (value) { + if (value) + { out32(OCCHW_OISR_OR(irq), OCCHW_IRQ_MASK32(irq)); - } else { + } + else + { out32(OCCHW_OISR_CLR(irq), OCCHW_IRQ_MASK32(irq)); } } @@ -121,18 +124,18 @@ ssx_irq_debug_set(SsxIrqId irq, int value); /// /// \arg \c rirq A register that holds the \c irq parameter passed to /// the handler from SSX interrupt dispatch. This register is not -/// modified. +/// modified. /// \arg \c rmask A scratch register - At the end of macro execution this /// register contains the 32-bit mask form of the irq. /// /// \arg \c raddr A scratch register - At the end of macro execution this -/// register holds the address of the interrupt +/// register holds the address of the interrupt /// controller facility that implements the action. /// /// \arg \c imm An immediate (0/non-0) value for certain macros. /// /// Forms: -/// +/// /// \b _ssx_irq_enable \a rirq, \a rmask, \a raddr - Enable an \c irq. \n /// \b _ssx_irq_disable \a rirq, \a rmask, \a raddr - Disable an \c irq. \n /// \b _ssx_irq_status_clear \a rirq, \a rmask, \a raddr - Clear \c irq @@ -153,10 +156,11 @@ ssx_irq_debug_set(SsxIrqId irq, int value); // register \c raddr is used as scratch for these computations. Hopefully the // local labels 888 and 999 are unique enough. -// Register names must be compared as strings - e.g., %r0 is not +// Register names must be compared as strings - e.g., %r0 is not // a symbol, it is converted to "0" by the assembler. #ifdef __ASSEMBLER__ +// *INDENT-OFF* .macro .two_unique, ra, rb .ifnc \ra, \rb @@ -192,7 +196,7 @@ ssx_irq_debug_set(SsxIrqId irq, int value); .macro _ssx_irq_enable, rirq:req, rmask:req, raddr:req .three_unique \rirq, \rmask, \raddr - + andi. \raddr, \rirq, 0x20 clrlwi \raddr, \rirq, 27 _occhw_irq_clr_mask \raddr, \rmask @@ -208,7 +212,7 @@ ssx_irq_debug_set(SsxIrqId irq, int value); .macro _ssx_irq_disable, rirq:req, rmask:req, raddr:req .three_unique \rirq, \rmask, \raddr - + andi. \raddr, \rirq, 0x20 clrlwi \raddr, \rirq, 27 _occhw_irq_or_mask \raddr, \rmask @@ -224,7 +228,7 @@ ssx_irq_debug_set(SsxIrqId irq, int value); .macro _ssx_irq_status_clear, rirq:req, rmask:req, raddr:req .three_unique \rirq, \rmask, \raddr - + andi. \raddr, \rirq, 0x20 clrlwi \raddr, \rirq, 27 _occhw_irq_clr_mask \raddr, \rmask @@ -243,7 +247,7 @@ ssx_irq_debug_set(SsxIrqId irq, int value); andi. \raddr, \rirq, 0x20 clrlwi \raddr, \rirq, 27 - + .if \imm _occhw_irq_or_mask \raddr, \rmask bne- 888f @@ -253,7 +257,7 @@ ssx_irq_debug_set(SsxIrqId irq, int value); _stwi \rmask, \raddr, OCB_OISR1_OR .else - + _occhw_irq_clr_mask \raddr, \rmask bne- 888f _stwi \rmask, \raddr, OCB_OISR0_CLR @@ -266,6 +270,7 @@ ssx_irq_debug_set(SsxIrqId irq, int value); eieio .endm +// *INDENT-ON* #endif /* __ASSEMBLER__ */ /// \endcond diff --git a/src/ssx/occhw/occhw_irq_init.c b/src/ssx/occhw/occhw_irq_init.c index da10cda..86e4562 100644 --- a/src/ssx/occhw/occhw_irq_init.c +++ b/src/ssx/occhw/occhw_irq_init.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -52,7 +52,7 @@ /// /// \retval 0 Successful completion /// -/// \retval -SSX_INVALID_ARGUMENT_IRQ_SETUP One or more arguments are invalid, +/// \retval -SSX_INVALID_ARGUMENT_IRQ_SETUP One or more arguments are invalid, /// including an invalid \a irq, or invalid \a polarity or \a trigger parameters. int @@ -62,7 +62,8 @@ ssx_irq_setup(SsxIrqId irq, { SsxMachineContext ctx; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(!OCCHW_IRQ_VALID(irq) || !OCCHW_IRQ_OWNED(irq) || !((polarity == SSX_IRQ_POLARITY_ACTIVE_HIGH) || @@ -74,15 +75,21 @@ ssx_irq_setup(SsxIrqId irq, ssx_critical_section_enter(SSX_CRITICAL, &ctx); - if (polarity == SSX_IRQ_POLARITY_ACTIVE_HIGH) { + if (polarity == SSX_IRQ_POLARITY_ACTIVE_HIGH) + { out32(OCCHW_OIEPR_OR(irq), OCCHW_IRQ_MASK32(irq)); - } else { + } + else + { out32(OCCHW_OIEPR_CLR(irq), OCCHW_IRQ_MASK32(irq)); } - if (trigger == SSX_IRQ_TRIGGER_EDGE_SENSITIVE) { + if (trigger == SSX_IRQ_TRIGGER_EDGE_SENSITIVE) + { out32(OCCHW_OITR_OR(irq), OCCHW_IRQ_MASK32(irq)); - } else { + } + else + { out32(OCCHW_OITR_CLR(irq), OCCHW_IRQ_MASK32(irq)); } @@ -101,19 +108,20 @@ ssx_irq_setup(SsxIrqId irq, /// /// \retval 0 Successful completion /// -/// \retval -SSX_INVALID_ARGUMENT_IRQ_HANDLER One or more arguments are -/// invalid, including an invalid \a irq, a null (0) \a handler, +/// \retval -SSX_INVALID_ARGUMENT_IRQ_HANDLER One or more arguments are +/// invalid, including an invalid \a irq, a null (0) \a handler, /// or invalid \a priority. int ssx_irq_handler_set(SsxIrqId irq, SsxIrqHandler handler, - void *arg, + void* arg, int priority) { SsxMachineContext ctx; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(!OCCHW_IRQ_VALID(irq) || !OCCHW_IRQ_OWNED(irq) || (handler == 0) || @@ -129,9 +137,12 @@ ssx_irq_handler_set(SsxIrqId irq, out32(OCCHW_OIRRB_CLR(irq), OCCHW_IRQ_MASK32(irq)); //Critical priority needs a 1 in OIRRC - if (priority == SSX_CRITICAL) { + if (priority == SSX_CRITICAL) + { out32(OCCHW_OIRRC_OR(irq), OCCHW_IRQ_MASK32(irq)); - } else { + } + else + { out32(OCCHW_OIRRC_CLR(irq), OCCHW_IRQ_MASK32(irq)); } @@ -156,9 +167,12 @@ ssx_irq_debug_set(SsxIrqId irq, int value) //TODO: port this over to using the OIRR instead of the OUDER //ouder = in32(OCCHW_OUDER(irq)); - if (value) { + if (value) + { //out32(OCCHW_OUDER(irq), ouder | OCCHW_IRQ_MASK32(irq)); - } else { + } + else + { //out32(OCCHW_OUDER(irq), ouder & ~OCCHW_IRQ_MASK32(irq)); } @@ -166,15 +180,15 @@ ssx_irq_debug_set(SsxIrqId irq, int value) } - - - - - - - + + + + + + + diff --git a/src/ssx/occhw/occhw_ocb.c b/src/ssx/occhw/occhw_ocb.c index 6188abb..dcc44a2 100644 --- a/src/ssx/occhw/occhw_ocb.c +++ b/src/ssx/occhw/occhw_ocb.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -41,7 +41,7 @@ unsigned int g_ocb_timer_divider = OCB_TIMER_DIVIDER_DEFAULT; /// \param timer A valid OCB timer index /// /// \param auto_reload A non-0 value indicates to run the timer in auto-reload -/// mode. +/// mode. /// /// \param timeout_ns The timeout specified in nanoseconds. The actual timeout /// will be rounded down to the underlying timer tick, with a minimum 1 tick @@ -55,7 +55,7 @@ unsigned int g_ocb_timer_divider = OCB_TIMER_DIVIDER_DEFAULT; /// /// \retval 0 Success /// -/// \retval -OCB_INVALID_ARGUMENT_TIMER Causes include illegal timer +/// \retval -OCB_INVALID_ARGUMENT_TIMER Causes include illegal timer /// numbers and illegal or unrepresntable timeouts. // Note that OCB_TIMER_FREQUENCY_HZ is in the range of 1-2 MHz. @@ -68,16 +68,20 @@ ocb_timer_reset(int timer, ocb_otrn_t otr; int ticks; - //printk("ocb_timer_reset(%d, %d, %d)\n", + //printk("ocb_timer_reset(%d, %d, %d)\n", // timer, auto_reload, timeout_ns); - if (timeout_ns != 0) { + if (timeout_ns != 0) + { ticks = MAX(1, timeout_ns / (1000000000 / OCB_TIMER_FREQUENCY_HZ)); - } else { + } + else + { ticks = 0; } - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((timer < 0) || (timer >= OCB_TIMERS) || (timeout_ns < 0) || @@ -103,7 +107,7 @@ ocb_timer_reset(int timer, /// \param timer A valid OCB timer index /// /// \param auto_reload A non-0 value indicates to run the timer in auto-reload -/// mode. +/// mode. /// /// \param timeout_ns The timeout specified in nanoseconds. The actual timeout /// will rounded down to the underlying timer tick, with a minimum 1 tick @@ -116,32 +120,32 @@ ocb_timer_reset(int timer, /// \param arg The private argument of the interrupt handler /// /// \param priority The SSX/PPC405 interrupt priority to assign to the -/// interrupt. +/// interrupt. /// /// This API sets up and starts the timer and unmasks the timer /// interrupt. Once set up, the timer can be reset using ocb_timer_reset(). As /// a fine point of the specification, if a timer interrupt is already pending /// when this API is invoked then that interrupt will be cleared. Only the /// next interrupt (corresponding to the new programming) will be serviced by -/// the newly installed handler. +/// the newly installed handler. /// /// Note that the interrupt handler is responsible for clearing the timer /// interrupt status. An API ocb_timer_status_clear() is available for this. /// /// \retval 0 Success /// -/// \retval -OCB_INVALID_ARGUMENT_TIMER Causes include illegal timer +/// \retval -OCB_INVALID_ARGUMENT_TIMER Causes include illegal timer /// numbers and illegal or unrepresntable timeouts. /// /// Other errors may be returned by the underlying calls to SSX routines that /// set up interrupts. int -ocb_timer_setup(int timer, +ocb_timer_setup(int timer, int auto_reload, int timeout_ns, SsxIrqHandler handler, - void *arg, + void* arg, int priority) { int rc; @@ -150,35 +154,38 @@ ocb_timer_setup(int timer, do { //Read Hang Pulse Register 2 to get the log base 2 of the ocb clock divider -- grm -// TEMP : Need Simics to model this +// TEMP/TODO: Cannot do getscom from 405 +// TODO: Need to discuss this getscom and whether it is necessary. // rc = getscom(TPC_HPR2, &l_hpr2.value); + if(rc) { break; } -//David Du: l_hpr2.fields.hang_pulse_reg is typically 9 +//TEMP/TODO: l_hpr2.fields.hang_pulse_reg is typically 9 // g_ocb_timer_divider = 1 << l_hpr2.fields.hang_pulse_reg; g_ocb_timer_divider = 1 << 9; //printk("ocb_timer_setup(%d, %d, %d, %p, %p, %d)\n", // timer, auto_reload, timeout_ns, // handler, arg, priority); - + ssx_irq_disable(OCCHW_IRQ_OCC_TIMER0 + timer); ssx_irq_setup(OCCHW_IRQ_OCC_TIMER0 + timer, - SSX_IRQ_POLARITY_ACTIVE_HIGH, - SSX_IRQ_TRIGGER_LEVEL_SENSITIVE); + SSX_IRQ_POLARITY_ACTIVE_HIGH, + SSX_IRQ_TRIGGER_LEVEL_SENSITIVE); ssx_irq_handler_set(OCCHW_IRQ_OCC_TIMER0 + timer, - handler, - arg, - priority); + handler, + arg, + priority); rc = ocb_timer_reset(timer, auto_reload, timeout_ns); ssx_irq_enable(OCCHW_IRQ_OCC_TIMER0 + timer); - }while(0); + } + while(0); return rc; } @@ -220,7 +227,7 @@ ocb_core_interrupt() /// overwritten with b'11000' /// /// -/// \todo double check SRAM region restriction +/// \todo double check SRAM region restriction /// /// \param channel The indirect channel to use, in the range 0..2. /// @@ -233,7 +240,7 @@ ocb_core_interrupt() /// /// \retval 0 Success /// -/// \retval OCB_INVALID_ARGUMENT_LW_INIT One or more of the parameter +/// \retval OCB_INVALID_ARGUMENT_LW_INIT One or more of the parameter /// restrictions were violated. /// /// \retval OCB_SCOM_ERROR An attempt to write a PBA SCOM register to set up @@ -249,10 +256,11 @@ ocb_linear_window_initialize(int channel, uint32_t base, int log_size) // create mask for checking mask = (0x1ull << log_size) - 1; - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF((channel < 0) || + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((channel < 0) || (channel > 3) || - (log_size < OCB_LW_LOG_SIZE_MIN) || + (log_size < OCB_LW_LOG_SIZE_MIN) || (log_size > OCB_LW_LOG_SIZE_MAX) || ((base & mask) != 0), OCB_INVALID_ARGUMENT_LW_INIT); @@ -287,7 +295,7 @@ ocb_linear_window_initialize(int channel, uint32_t base, int log_size) /// /// \retval 0 Success /// -/// \retval OCB_INVALID_ARGUMENT_LW_DISABLE One or more of the parameter +/// \retval OCB_INVALID_ARGUMENT_LW_DISABLE One or more of the parameter /// restrictions were violated. /// @@ -295,15 +303,16 @@ int ocb_linear_window_disable(int channel) { ocb_ocblwcrn_t ocblwcrn; - - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF((channel < 0) || + + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((channel < 0) || (channel > 3), OCB_INVALID_ARGUMENT_LW_DISABLE); } ocblwcrn.value = in32(OCB_OCBLWCRN(channel)); - // Disable LW mode + // Disable LW mode ocblwcrn.fields.linear_window_enable = 0; out32(OCB_OCBLWCRN(channel), ocblwcrn.value); @@ -323,7 +332,7 @@ ocb_linear_window_disable(int channel) /// Note that this bit is not used for indirect channel 3. /// /// -/// \param allow_untrusted Enable untrusted PIB masters +/// \param allow_untrusted Enable untrusted PIB masters /// access to the indirect channel being configured. If allow_untrusted is /// not enabled and the chip is running in trusted mode, then any untrusted /// PIB master will get an offline return code when attempting to write @@ -331,7 +340,7 @@ ocb_linear_window_disable(int channel) /// /// \retval 0 Success /// -/// \retval OCB_INVALID_ARGUMENT_UNTRUST One or more of the parameter +/// \retval OCB_INVALID_ARGUMENT_UNTRUST One or more of the parameter /// restrictions were violated. /// @@ -344,8 +353,9 @@ ocb_allow_untrusted_initialize(int channel, int allow_untrusted) { ocb_ocbicrn_t ocbicrn; - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF((channel < 0) || + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((channel < 0) || (channel > 2) || (allow_untrusted < 0) || (allow_untrusted > 1), @@ -354,7 +364,7 @@ ocb_allow_untrusted_initialize(int channel, int allow_untrusted) // Configure allow_unsecure_pib_masters bit ocbicrn.fields.allow_unsecure_pib_masters = allow_untrusted; - out32(OCB_OCBICRN(channel), ocbicrn.value); + out32(OCB_OCBICRN(channel), ocbicrn.value); return 0 ; } diff --git a/src/ssx/occhw/occhw_ocb.h b/src/ssx/occhw/occhw_ocb.h index 9a780b4..6e873ce 100644 --- a/src/ssx/occhw/occhw_ocb.h +++ b/src/ssx/occhw/occhw_ocb.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -61,27 +61,27 @@ #ifndef __ASSEMBLER__ -int -ocb_timer_reset(int timer, +int +ocb_timer_reset(int timer, int auto_reload, int timeout_ns); #ifdef OCC int -ocb_timer_setup(int timer, +ocb_timer_setup(int timer, int auto_reload, int timeout_ns, SsxIrqHandler handler, - void *arg, + void* arg, int priority) INIT_SECTION; #else int ocb_timer_setup(int timer, - int auto_reload, - int timeout_ns, - SsxIrqHandler handler, - void *arg, - int priority); + int auto_reload, + int timeout_ns, + SsxIrqHandler handler, + void* arg, + int priority); #endif /// Clear OCB timer status based on the IRQ @@ -106,7 +106,7 @@ ocb_linear_window_disable(int channel); int ocb_allow_untrusted_initialize(int channel, int allow_untrusted); - + #endif /* __ASSEMBLER__ */ diff --git a/src/ssx/occhw/occhw_pba.c b/src/ssx/occhw/occhw_pba.c index 5ba18d5..35344ba 100644 --- a/src/ssx/occhw/occhw_pba.c +++ b/src/ssx/occhw/occhw_pba.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,14 +40,14 @@ // Internal API to set up a PBA BAR -static int +static int pba_bar_set(int idx, uint64_t pb_base, uint8_t pb_scope) { int rc ; pba_barn_t bar ; bar.fields.cmd_scope = pb_scope ; - bar.fields.addr = pb_base >> PBA_LOG_SIZE_MIN ; + bar.fields.addr = pb_base >> PBA_LOG_SIZE_MIN ; rc = putscom(PBA_BARN(idx), bar.value); @@ -93,10 +93,10 @@ pba_barmask_set(int idx, uint64_t mask) /// /// \retval 0 Success /// -/// \retval PBA_INVALID_ARGUMENT_BARSET One or more of the parameter +/// \retval PBA_INVALID_ARGUMENT_BARSET One or more of the parameter /// restrictions were violated. /// -/// \retval PBA_SCOM_ERROR1 or PBA_SCOM_ERROR2 An attempt to write a PBA SCOM +/// \retval PBA_SCOM_ERROR1 or PBA_SCOM_ERROR2 An attempt to write a PBA SCOM /// register to set up the BARs produced a non-zero return code. int @@ -106,21 +106,25 @@ pba_barset_initialize(int idx, uint64_t base, int log_size) mask = (0x1ull << log_size) - 1; - if (SSX_ERROR_CHECK_API) { - SSX_ERROR_IF((idx < 0) || + if (SSX_ERROR_CHECK_API) + { + SSX_ERROR_IF((idx < 0) || (idx > 3) || - (log_size < PBA_LOG_SIZE_MIN) || + (log_size < PBA_LOG_SIZE_MIN) || (log_size > PBA_LOG_SIZE_MAX) || ((base & mask) != 0), PBA_INVALID_ARGUMENT_BARSET); } - if (pba_bar_set(idx, base, PBA_POWERBUS_COMMAND_SCOPE_DEFAULT)) { + if (pba_bar_set(idx, base, PBA_POWERBUS_COMMAND_SCOPE_DEFAULT)) + { SSX_ERROR(PBA_SCOM_ERROR1); } - if (pba_barmask_set(idx, mask)) { + + if (pba_barmask_set(idx, mask)) + { SSX_ERROR(PBA_SCOM_ERROR2); - } + } return 0 ; } @@ -159,7 +163,7 @@ _pba_slave_reset_poll(void* arg, int* done) } -/// Reset a PBA slave with explicit timeout. +/// Reset a PBA slave with explicit timeout. /// /// \param id A PBA slave id in the range 0..3 /// @@ -175,7 +179,7 @@ _pba_slave_reset_poll(void* arg, int* done) /// /// \retval 0 Success /// -/// \retval -PBA_INVALID_ARGUMENT_RESET The slave \a id parameter +/// \retval -PBA_INVALID_ARGUMENT_RESET The slave \a id parameter /// is invalid. /// /// \retval -PBA_SLVRST_TIMED_OUT1 The procedure timed out waiting for the PBA @@ -187,13 +191,16 @@ _pba_slave_reset(int id, SsxInterval timeout, SsxInterval sleep) { int rc, closureRc; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((id < 0) || (id >= PBA_SLAVES), PBA_INVALID_ARGUMENT_RESET); } - + rc = polling(&closureRc, _pba_slave_reset_poll, (void*)id, timeout, sleep); - if (rc == POLLING_TIMEOUT) { + + if (rc == POLLING_TIMEOUT) + { rc = -PBA_SLVRST_TIMED_OUT1; } @@ -213,7 +220,7 @@ _pba_slave_reset(int id, SsxInterval timeout, SsxInterval sleep) /// /// \retval 0 Success /// -/// \retval -SSX_INVALID_ARGUMENT_PBA_RESET The slave \a id parameter is +/// \retval -SSX_INVALID_ARGUMENT_PBA_RESET The slave \a id parameter is /// invalid. /// /// \retval -PBA_SLVRST_TIMED_OUT2 The procedure timed out waiting for the PBA @@ -225,7 +232,9 @@ pba_slave_reset(int id) int rc; rc = _pba_slave_reset(id, PBA_SLAVE_RESET_TIMEOUT, 0); - if (rc) { + + if (rc) + { SSX_ERROR(PBA_SLVRST_TIMED_OUT2); } @@ -253,15 +262,16 @@ pba_slave_reset(int id) /// /// \retval 0 Success /// -/// \retval -PBAX_INVALID_ARGUMENT_CONFIG One of the arguments is -/// not valid for some reason. +/// \retval -PBAX_INVALID_ARGUMENT_CONFIG One of the arguments is +/// not valid for some reason. int pbax_configure(int master, int group, int chip, int group_mask) { pba_xcfg_t pxc; - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF((group < 0) || (group >= PBAX_GROUPS) || (chip < 0) || @@ -270,6 +280,7 @@ pbax_configure(int master, int group, int chip, int group_mask) (group_mask > PBAX_GROUP_MASK_MAX), PBAX_INVALID_ARGUMENT_CONFIG); } + pxc.value = in64(PBA_XCFG); pxc.fields.reservation_en = (master != 0); pxc.fields.rcv_groupid = group; @@ -304,17 +315,18 @@ pbax_configure(int master, int group, int chip, int group_mask) /// \retval 0 Success /// /// \retval -PBAX_INVALID_OBJECT The \a target parameter is NULL (0) or -/// otherwise invalid. +/// otherwise invalid. /// -/// \retval -PBAX_INVALID_ARGUMENT_TARGET One or more of the arguments +/// \retval -PBAX_INVALID_ARGUMENT_TARGET One or more of the arguments /// is invalid. int pbax_target_create(PbaxTarget* target, - int type, int scope, int queue, + int type, int scope, int queue, int group, int chip_or_group) { - if (SSX_ERROR_CHECK_API) { + if (SSX_ERROR_CHECK_API) + { SSX_ERROR_IF(target == 0, PBAX_INVALID_OBJECT); SSX_ERROR_IF(((type != PBAX_UNICAST) && (type != PBAX_BROADCAST)) || ((scope != PBAX_GROUP) && (scope != PBAX_SYSTEM)) || @@ -376,7 +388,7 @@ pbax_target_create(PbaxTarget* target, /// /// \retval -PBAX_TIMEOUT The caller-specified timeout expired before the PBAX /// send machine became free, but the PBAX send machine does not show error -/// status. +/// status. /// /// \retval -PBAX_SEND_ERROR The PBAXSNDSTAT.snd_error bit is asserted. It /// is expected that this error will cause the PBA error interrupt to fire - @@ -391,39 +403,52 @@ _pbax_send(PbaxTarget* target, uint64_t data, SsxInterval timeout) // The PBAX is always polled at least twice to guarantee that we always // poll once after a timeout - unless the caller explicitly requested a 0 - // timeout. - - start = 0; - timed_out = 0; - do { + // timeout. + + start = 0; + timed_out = 0; + + do + { pss.words.high_order = in32(PBA_XSNDSTAT); - if (pss.fields.snd_error) { + + if (pss.fields.snd_error) + { rc = -PBAX_SEND_ERROR; break; } - if (!pss.fields.snd_in_progress) { + + if (!pss.fields.snd_in_progress) + { rc = 0; break; } - if (start == 0) { + + if (start == 0) + { start = ssx_timebase_get(); } - if ((timeout == 0) || timed_out) { + + if ((timeout == 0) || timed_out) + { rc = -PBAX_SEND_TIMEOUT; break; } - timed_out = + + timed_out = ((timeout != SSX_WAIT_FOREVER) && ((ssx_timebase_get() - start) > timeout)); - } while (1); + } + while (1); // Configure the send engine and initiate the write, which is kicked off // by writing the high-order word of the send data register. - if (!rc) { + if (!rc) + { out32(PBA_XSNDTX, target->target.words.high_order); - out32(PBA_XSNDDAT + 4, data & 0xffffffff); - out32(PBA_XSNDDAT, data >> 32); + out32(PBA_XSNDDAT + 4, data >> 32); + out32(PBA_XSNDDAT, data & 0xffffffff); } return rc; @@ -459,21 +484,27 @@ pbax_send(PbaxTarget* target, uint64_t data) int rc; rc = _pbax_send(target, data, PBAX_SEND_DEFAULT_TIMEOUT); - if (rc) { - if (rc == -PBAX_SEND_TIMEOUT) { + + if (rc) + { + if (rc == -PBAX_SEND_TIMEOUT) + { SSX_ERROR(PBAX_SEND_TIMEOUT); - } else { + } + else + { SSX_ERROR(PBAX_SEND_ERROR); } } + return rc; } - - - - + + + + diff --git a/src/ssx/occhw/occhw_pba.h b/src/ssx/occhw/occhw_pba.h index 96272a7..46c6901 100644 --- a/src/ssx/occhw/occhw_pba.h +++ b/src/ssx/occhw/occhw_pba.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -36,11 +36,6 @@ /// \todo Add Doxygen grouping to constant groups -// @TODO - TEMP: Added to eliminate errors: implicit declaration of functions out32 & in32 -// These functions are used in the pbax functions defined below. -#include "ssx_api.h" -#include "ppc32.h" - #include "pba_register_addresses.h" #include "pba_firmware_registers.h" @@ -52,7 +47,7 @@ // It is assumed the the PBA BAR sets will be assigned according to the // following scheme. There are still many open questions concerning PBA -// setup. +// setup. /// The number of PBA Base Address Registers (BARS) #define PBA_BARS 4 @@ -73,8 +68,8 @@ #define PBA_SLAVE_PORE_GPE 0 /* GPE0/1, but only 1 can access mainstore */ #define PBA_SLAVE_OCC 1 /* 405 I- and D-cache */ -#define PBA_SLAVE_PORE_SLW 2 -#define PBA_SLAVE_OCB 3 +#define PBA_SLAVE_PORE_SLW 2 +#define PBA_SLAVE_OCB 3 /// The maximum number of bytes a PBA block-copy engine can transfer at once #define PBA_BCE_SIZE_MAX 4096 @@ -117,10 +112,10 @@ #define PBA_WRITE_TSIZE_CHIPLET(chiplet) (chiplet) -#define PBA_WRITE_TSIZE_ARMW_ADD 0x03 -#define PBA_WRITE_TSIZE_ARMW_AND 0x13 -#define PBA_WRITE_TSIZE_ARMW_OR 0x23 -#define PBA_WRITE_TSIZE_ARMW_XOR 0x33 +#define PBA_WRITE_TSIZE_ARMW_ADD 0x02 +#define PBA_WRITE_TSIZE_ARMW_AND 0x22 +#define PBA_WRITE_TSIZE_ARMW_OR 0x42 +#define PBA_WRITE_TSIZE_ARMW_XOR 0x62 #define PBA_WRITE_TSIZE_DC 0x0 @@ -154,7 +149,7 @@ #define PBA_READ_TTYPE_CI_PR_RD 0x1 /// Cache-inhibited partial read for Centaur getscom(). /// PBA read TTYPE don't care assignment -#define PBA_READ_TTYPE_DC PBA_READ_TTYPE_CL_RD_NC +#define PBA_READ_TTYPE_DC PBA_READ_TTYPE_CL_RD_NC // PBA read prefetch options @@ -164,13 +159,13 @@ #define PBA_READ_PREFETCH_AUTO_LATE 0x2 /// Non-aggressive prefetch /// PBA read prefetch don't care assignment - see gpe_pba_parms_create() -#define PBA_READ_PREFETCH_DC -1 +#define PBA_READ_PREFETCH_DC -1 // PBA PowerBus command scope and priority, and PBA defaults /// Nodal, Local Node -#define POWERBUS_COMMAND_SCOPE_NODAL 0x0 +#define POWERBUS_COMMAND_SCOPE_NODAL 0x0 /// Group, Local 4-chip, (aka, node pump) #define POWERBUS_COMMAND_SCOPE_GROUP 0x1 @@ -183,7 +178,7 @@ /// Foreign, All units on the local chip, local SMP, and remote chip (pivot /// nodes), In P8, only 100 and 101 are valid. -#define POWERBUS_COMMAND_SCOPE_FOREIGN0 0x4 +#define POWERBUS_COMMAND_SCOPE_FOREIGN0 0x4 /// Foreign, All units on the local chip, local SMP, and remote chip (pivot /// nodes), In P8, only 100 and 101 are valid. @@ -207,8 +202,8 @@ /// initialization-only and/or lab-only procedure, so this long polling /// timeout is not a problem. #ifndef PBA_SLAVE_RESET_TIMEOUT -#define PBA_SLAVE_RESET_TIMEOUT SSX_MICROSECONDS(100) -#endif + #define PBA_SLAVE_RESET_TIMEOUT SSX_MICROSECONDS(100) +#endif // PBA Error/Panic codes @@ -229,11 +224,13 @@ /// /// The extended address covers only bits 23:36 of the 50-bit PowerBus address. -typedef union pba_extended_address { +typedef union pba_extended_address +{ uint64_t value; uint32_t word[2]; - struct { + struct + { uint64_t reserved0 : 23; uint64_t extended_address : 14; uint64_t reserved1 : 27; @@ -241,14 +238,11 @@ typedef union pba_extended_address { } pba_extended_address_t; -int +int pba_barset_initialize(int idx, uint64_t base, int log_size); -// @TODO - TEMP: PORE assembly code. to be replace with valid GPE code -/* int _pba_slave_reset(int id, SsxInterval timeout, SsxInterval sleep); -*/ int pba_slave_reset(int id); @@ -268,19 +262,18 @@ pba_slave_reset(int id); #define PBAX_QUEUES 2 /// The number of PBAX Node Ids -#define PBAX_NODES 8 +#define PBAX_GROUPS 16 /// The number of PBAX Chip Ids (and group Ids) #define PBAX_CHIPS 8 -#define PBAX_GROUPS PBAX_CHIPS /// The maximum legal PBAX group mask #define PBAX_GROUP_MASK_MAX 0xff // PBAX Send Message Scope -#define PBAX_GROUP 1 -#define PBAX_SYSTEM 2 +#define PBAX_GROUP 3 +#define PBAX_SYSTEM 5 // PBAX Send Type @@ -290,7 +283,7 @@ pba_slave_reset(int id); // Default timeout for pbax_send() #ifndef PBAX_SEND_DEFAULT_TIMEOUT -#define PBAX_SEND_DEFAULT_TIMEOUT SSX_MICROSECONDS(30) + #define PBAX_SEND_DEFAULT_TIMEOUT SSX_MICROSECONDS(30) #endif /// An abstract target for PBAX send operations @@ -304,7 +297,8 @@ pba_slave_reset(int id); /// For applications that use GPE programs to implement PBAX sends, a pointer /// to this object could also be passed to the GPE program. -typedef struct { +typedef struct +{ /// The abstract target /// @@ -317,7 +311,7 @@ typedef struct { int pbax_target_create(PbaxTarget* target, - int type, int scope, int queue, + int type, int scope, int queue, int node, int chip_or_group); int @@ -340,7 +334,7 @@ pbax_send_enable(void) pxc.words.high_order = in32(PBA_XCFG); pxc.fields.pbax_en = 1; out32(PBA_XCFG, pxc.words.high_order); - + } @@ -354,7 +348,7 @@ pbax_send_disable(void) pxc.words.high_order = in32(PBA_XCFG); pxc.fields.pbax_en = 0; out32(PBA_XCFG, pxc.words.high_order); - + } @@ -368,7 +362,7 @@ pbax_clear_send_error(void) pxc.words.high_order = in32(PBA_XCFG); pxc.fields.snd_reset = 1; out32(PBA_XCFG, pxc.words.high_order); -} +} /// Clear the PBAX receive error condition @@ -381,7 +375,7 @@ pbax_clear_receive_error(void) pxc.words.high_order = in32(PBA_XCFG); pxc.fields.rcv_reset = 1; out32(PBA_XCFG, pxc.words.high_order); -} +} #endif /* __ASSEMBLER__ */ diff --git a/src/ssx/occhw/occhw_scom.c b/src/ssx/occhw/occhw_scom.c index 743d0dc..359a991 100644 --- a/src/ssx/occhw/occhw_scom.c +++ b/src/ssx/occhw/occhw_scom.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -75,7 +75,7 @@ /// SCOM-by-SCOM basis. /// /// \bug Modify getscom/putscom to return the SSX error codes rather than -/// 1-7. +/// 1-7. /// /// \bug Implement and use a generic poll_with_timeout(f, arg, t) @@ -90,7 +90,7 @@ // Common SCOM polling loop with software timeout. The PMC is always polled // at least twice to guarantee that we always poll once after a timeout. -static int +static int poll_scom(SsxInterval timeout) { SsxTimebase start; @@ -99,19 +99,28 @@ poll_scom(SsxInterval timeout) start = ssx_timebase_get(); timed_out = 0; - do { - rc = ssx_irq_status_get(OCCHW_IRQ_IPI_SCOM); - if (!rc) { + + do + { + rc = ssx_irq_status_get(OCCHW_IRQ_IPI_SCOM); + + if (!rc) + { break; } - if (timed_out) { + + if (timed_out) + { rc = -SCOM_TIMEOUT_ERROR; break; } - timed_out = + + timed_out = ((timeout != SSX_WAIT_FOREVER) && ((ssx_timebase_get() - start) > timeout)); - } while (1); + } + while (1); + return rc; } @@ -145,15 +154,15 @@ poll_scom(SsxInterval timeout) /// \retval -SCOM_TIMEOUT_ERROR The software timeout specified by the \a /// timeout parameter expired before the transaction completed. /// -/// retval -SCOM_PROTOCOL_ERROR_GETSCOM_BUSY The PMC SCOM engine was busy when -/// the call was made. +/// retval -SCOM_PROTOCOL_ERROR_GETSCOM_BUSY The PMC SCOM engine was busy when +/// the call was made. int -_getscom(uint32_t address, uint64_t *data, SsxInterval timeout) +_getscom(uint32_t address, uint64_t* data, SsxInterval timeout) { SsxMachineContext ctx; int rc; - occhw_scom_cmd_t *scom_cmd = &OSD_PTR->scom_cmd; + occhw_scom_cmd_t* scom_cmd = &OSD_PTR->scom_cmd; occhw_scom_status_t scom_status; do @@ -167,8 +176,10 @@ _getscom(uint32_t address, uint64_t *data, SsxInterval timeout) ssx_critical_section_enter(SSX_CRITICAL, &ctx); // Check for a transaction already ongoing - rc = ssx_irq_status_get(OCCHW_IRQ_IPI_SCOM); - if (rc) { + rc = ssx_irq_status_get(OCCHW_IRQ_IPI_SCOM); + + if (rc) + { ssx_critical_section_exit(&ctx); rc = -SCOM_PROTOCOL_ERROR_GETSCOM_BUSY; break; @@ -208,7 +219,9 @@ _getscom(uint32_t address, uint64_t *data, SsxInterval timeout) } } - }while(0); + } + while(0); + return rc; } @@ -238,35 +251,66 @@ _getscom(uint32_t address, uint64_t *data, SsxInterval timeout) ///\ retval 1-7 A PCB error code. See \c pcb_common.h int -getscom(uint32_t address, uint64_t *data) +getscom(uint32_t address, uint64_t* data) { int rc; rc = _getscom(address, data, SCOM_TIMEOUT); - if (rc == 0) { + + if (rc == 0) + { return 0; } - if ((rc > 0) && (rc <= SCOM_ERROR_LIMIT)) { + if ((rc > 0) && (rc <= SCOM_ERROR_LIMIT)) + { *data = 0; - } else { + } + else + { //printk("getscom(0x%08x, %p) : Failed with error %d\n", // address, data, rc); - if (rc > 0) { - switch (rc) { - case 1: SSX_PANIC(SCOM_PCB_ERROR_1_GETSCOM); break; - case 2: SSX_PANIC(SCOM_PCB_ERROR_2_GETSCOM); break; - case 3: SSX_PANIC(SCOM_PCB_ERROR_3_GETSCOM); break; - case 4: SSX_PANIC(SCOM_PCB_ERROR_4_GETSCOM); break; - case 5: SSX_PANIC(SCOM_PCB_ERROR_5_GETSCOM); break; - case 6: SSX_PANIC(SCOM_PCB_ERROR_6_GETSCOM); break; - default: SSX_PANIC(SCOM_PCB_ERROR_7_GETSCOM); break; - } - } else if (rc == -SCOM_TIMEOUT_ERROR) { + if (rc > 0) + { + switch (rc) + { + case 1: + SSX_PANIC(SCOM_PCB_ERROR_1_GETSCOM); + break; + + case 2: + SSX_PANIC(SCOM_PCB_ERROR_2_GETSCOM); + break; + + case 3: + SSX_PANIC(SCOM_PCB_ERROR_3_GETSCOM); + break; + + case 4: + SSX_PANIC(SCOM_PCB_ERROR_4_GETSCOM); + break; + + case 5: + SSX_PANIC(SCOM_PCB_ERROR_5_GETSCOM); + break; + + case 6: + SSX_PANIC(SCOM_PCB_ERROR_6_GETSCOM); + break; + + default: + SSX_PANIC(SCOM_PCB_ERROR_7_GETSCOM); + break; + } + } + else if (rc == -SCOM_TIMEOUT_ERROR) + { SSX_PANIC(SCOM_TIMEOUT_ERROR_GETSCOM); - } else { + } + else + { SSX_PANIC(SCOM_PROTOCOL_ERROR_GETSCOM); } } @@ -288,7 +332,7 @@ getscom(uint32_t address, uint64_t *data) /// This routine executes in an SSX_CRITICAL critical section. /// /// Unlike most other APIs, this API returns both positive and negative error -/// codes, as well as the 0 code for success. +/// codes, as well as the 0 code for success. /// /// If the transaction experiences a software timeout (controlled by the \a /// timeout parameter) or a protocol error, the PMC PIB master will be left in @@ -302,15 +346,15 @@ getscom(uint32_t address, uint64_t *data) /// \retval -SCOM_TIMEOUT The software timeout specified by the \a timeout /// parameter expired before the transaction completed. /// -/// \retval -SCOM_PROTOCOL_ERROR_PUTSCOM_BUSY The PMC SCOM engine was busy when -/// the call was made. +/// \retval -SCOM_PROTOCOL_ERROR_PUTSCOM_BUSY The PMC SCOM engine was busy when +/// the call was made. int _putscom(uint32_t address, uint64_t data, SsxInterval timeout) { SsxMachineContext ctx; int rc; - occhw_scom_cmd_t *scom_cmd = &OSD_PTR->scom_cmd; + occhw_scom_cmd_t* scom_cmd = &OSD_PTR->scom_cmd; occhw_scom_status_t scom_status; do @@ -324,8 +368,10 @@ _putscom(uint32_t address, uint64_t data, SsxInterval timeout) ssx_critical_section_enter(SSX_CRITICAL, &ctx); // Check for a transaction already ongoing - rc = ssx_irq_status_get(OCCHW_IRQ_IPI_SCOM); - if (rc) { + rc = ssx_irq_status_get(OCCHW_IRQ_IPI_SCOM); + + if (rc) + { ssx_critical_section_exit(&ctx); rc = -SCOM_PROTOCOL_ERROR_PUTSCOM_BUSY; break; @@ -344,7 +390,7 @@ _putscom(uint32_t address, uint64_t data, SsxInterval timeout) scom_status.status32 = scom_cmd->scom_status.status32; ssx_critical_section_exit(&ctx); - + if(!rc) { //check that the GPE updated the scom status. Normally, @@ -362,7 +408,9 @@ _putscom(uint32_t address, uint64_t data, SsxInterval timeout) rc = scom_status.sibrc; } } - }while(0); + } + while(0); + return rc; } @@ -377,7 +425,7 @@ _putscom(uint32_t address, uint64_t data, SsxInterval timeout) /// This routine executes in an SSX_CRITICAL critical section. /// /// Unlike most other APIs, this API returns positive error -/// codes, as well as the 0 code for success. +/// codes, as well as the 0 code for success. /// /// If the transaction experiences a software timeout (controlled by the \a /// timeout parameter), a protocol error, or a PCB error greater than the @@ -397,26 +445,53 @@ putscom(uint32_t address, uint64_t data) rc = _putscom(address, data, SCOM_TIMEOUT); - if ((rc == 0) || ((rc > 0) && (rc <= SCOM_ERROR_LIMIT))) { + if ((rc == 0) || ((rc > 0) && (rc <= SCOM_ERROR_LIMIT))) + { return rc; } //printk("putscom(0x%08x, 0x%016llx) : Failed with error %d\n", // address, data, rc); - if (rc > 0) { - switch (rc) { - case 1: SSX_PANIC(SCOM_PCB_ERROR_1_PUTSCOM); break; - case 2: SSX_PANIC(SCOM_PCB_ERROR_2_PUTSCOM); break; - case 3: SSX_PANIC(SCOM_PCB_ERROR_3_PUTSCOM); break; - case 4: SSX_PANIC(SCOM_PCB_ERROR_4_PUTSCOM); break; - case 5: SSX_PANIC(SCOM_PCB_ERROR_5_PUTSCOM); break; - case 6: SSX_PANIC(SCOM_PCB_ERROR_6_PUTSCOM); break; - default: SSX_PANIC(SCOM_PCB_ERROR_7_PUTSCOM); break; + if (rc > 0) + { + switch (rc) + { + case 1: + SSX_PANIC(SCOM_PCB_ERROR_1_PUTSCOM); + break; + + case 2: + SSX_PANIC(SCOM_PCB_ERROR_2_PUTSCOM); + break; + + case 3: + SSX_PANIC(SCOM_PCB_ERROR_3_PUTSCOM); + break; + + case 4: + SSX_PANIC(SCOM_PCB_ERROR_4_PUTSCOM); + break; + + case 5: + SSX_PANIC(SCOM_PCB_ERROR_5_PUTSCOM); + break; + + case 6: + SSX_PANIC(SCOM_PCB_ERROR_6_PUTSCOM); + break; + + default: + SSX_PANIC(SCOM_PCB_ERROR_7_PUTSCOM); + break; } - } else if (rc == -SCOM_TIMEOUT_ERROR) { + } + else if (rc == -SCOM_TIMEOUT_ERROR) + { SSX_PANIC(SCOM_TIMEOUT_ERROR_PUTSCOM); - } else { + } + else + { SSX_PANIC(SCOM_PROTOCOL_ERROR_PUTSCOM); } diff --git a/src/ssx/occhw/occhw_scom.h b/src/ssx/occhw/occhw_scom.h index 847fa90..bbf1869 100644 --- a/src/ssx/occhw/occhw_scom.h +++ b/src/ssx/occhw/occhw_scom.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -46,17 +46,17 @@ #ifndef __ASSEMBLER__ -int -_getscom(uint32_t address, uint64_t *data, SsxInterval timeout); + int + _getscom(uint32_t address, uint64_t* data, SsxInterval timeout); -int -getscom(uint32_t address, uint64_t *data); + int + getscom(uint32_t address, uint64_t* data); -int -_putscom(uint32_t address, uint64_t data, SsxInterval timeout); + int + _putscom(uint32_t address, uint64_t data, SsxInterval timeout); -int -putscom(uint32_t address, uint64_t data); + int + putscom(uint32_t address, uint64_t data); #endif /* __ASSEMBLER__ */ @@ -92,7 +92,7 @@ putscom(uint32_t address, uint64_t data); /// The default timeout for getscom()/putscom() /// /// This timeout is enforced by the firmware to guarantee a timeout regardless -/// of the hardware setup. +/// of the hardware setup. /// /// The expectation is that the hardware will be set up to enforce a PCB /// timeout of 8K cycles, or 16.384us @ 500 MHz. A timeout only occurs if @@ -109,7 +109,7 @@ putscom(uint32_t address, uint64_t data); /// (either the setup, hardware or firmware) must be broken. #ifndef SCOM_TIMEOUT -#define SCOM_TIMEOUT SSX_MICROSECONDS(17) + #define SCOM_TIMEOUT SSX_MICROSECONDS(17) #endif @@ -124,7 +124,7 @@ putscom(uint32_t address, uint64_t data); /// well. #ifndef SCOM_ERROR_LIMIT -#define SCOM_ERROR_LIMIT PCB_ERROR_CHIPLET_OFFLINE + #define SCOM_ERROR_LIMIT PCB_ERROR_CHIPLET_OFFLINE #endif #endif // __OCCHW_SCOM_H__ diff --git a/src/ssx/occhw/occhw_sramctl.h b/src/ssx/occhw/occhw_sramctl.h index 7f1b1e5..c8f4604 100644 --- a/src/ssx/occhw/occhw_sramctl.h +++ b/src/ssx/occhw/occhw_sramctl.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/occhw/ssx_port.h b/src/ssx/occhw/ssx_port.h index 81a52aa..eda7c64 100644 --- a/src/ssx/occhw/ssx_port.h +++ b/src/ssx/occhw/ssx_port.h @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ diff --git a/src/ssx/occhw/ssxocchwfiles.mk b/src/ssx/occhw/ssxocchwfiles.mk index 3559ae7..41417df 100644 --- a/src/ssx/occhw/ssxocchwfiles.mk +++ b/src/ssx/occhw/ssxocchwfiles.mk @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2015 +# Contributors Listed Below - COPYRIGHT 2015,2016 # [+] International Business Machines Corp. # # |