summaryrefslogtreecommitdiffstats
path: root/src/occ/dcom/dcomMasterTx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/occ/dcom/dcomMasterTx.c')
-rwxr-xr-xsrc/occ/dcom/dcomMasterTx.c628
1 files changed, 628 insertions, 0 deletions
diff --git a/src/occ/dcom/dcomMasterTx.c b/src/occ/dcom/dcomMasterTx.c
new file mode 100755
index 0000000..d0efa5a
--- /dev/null
+++ b/src/occ/dcom/dcomMasterTx.c
@@ -0,0 +1,628 @@
+/******************************************************************************
+// @file dcomMasterToSlave.c
+// @brief Master OCC to Slave OCC communication handler
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section dcomMasterToSlave.c DCOMMASTERTOSLAVE.C
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @00 abagepa 10/10/2011 Created
+ * @th002 thallet 11/01/2011 Misc Changes for Nov 1st Milestone
+ * @pb00A pbavari 11/15/2011 Set G_ApssPwrMeasCompleted to TRUE
+ * for SVN SIMICS
+ * @th005 thallet 11/01/2011 Added STATIC_ASSERT checks
+ * @01 tapiar 11/12/2011 Stage 3 updates
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @th010 thallet 07/11/2012 Pstate Enablement
+ * @th022 thallet 10/08/2012 Moved CNFG Data commands to diff file
+ * @ly003 861535 lychen 11/19/2012 Remove APSS configuration/gathering of Altitude & Temperature
+ * @th034 879027 thallet 04/18/2013 Broadcast Power Data over PBAX
+ * @at013 878755 alvinwan 04/17/2013 OCC power capping implementation
+ * @th032 thallet 04/16/2013 Tuleta HW Bringup
+ * @th040 887069 thallet 06/11/2013 Support Nom & FFO Freq Setting for Mnfg
+ * @fk001 879727 fmkassem 04/16/2013 OCC powercap support.
+ * @gs007 888247 gjsilva 06/19/2013 OCC mnfg support for frequency distribution
+ * @gs015 905166 gjsilva 11/04/2013 Full support for IPS function
+ * @gs016 905781 gjsilva 11/12/2013 Fix for Master->Slave doorbell loss of synchronization
+ * @gs017 905990 gjsilva 11/13/2013 Full support for tunable parameters
+ * @rt004 905638 tapiar 11/13/2013 Tunable parameters
+ * @gm014 907707 milesg 12/05/2013 don't panic on pbax_send timeout failures
+ * @jh00a 909791 joshych 12/16/2013 Enhance APSS pwr meas trace
+ * @sb003 908290 sbroyles 12/18/2013 Test BCE request states
+ * @jh00b 910184 joshych 01/10/2014 Add check for checkstop
+ * @sb013 911625 sbroyles 01/15/2014 Fix to 908290 changes
+ * @fk005 911760 fmkassem 01/14/2014 APSS data collection retry support.
+ * @gs025 913663 gjsilva 01/30/2014 Full fupport for soft frequency boundaries
+ * @sb023 913769 sbroyles 02/08/2014 Fix task_dcom_tx_slv_inbox !idle &&
+ * !complete hang.
+ * @gm028 911670 milesg 02/27/2014 Fixed compiler fails from stradale
+ * @gs027 918066 gjsilva 03/12/2014 Misc functions from ARL
+ * @wb001 919163 wilbryan 03/06/2014 Updating error call outs, descriptions, and severities
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+#ifndef _DCOMMASTERTX_C
+#define _DCOMMASTERTX_C
+
+/** \defgroup Master-Slave Communication
+ *
+ */
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include <pgp_pmc.h>
+#include "pgp_pba.h"
+#include <rtls.h>
+#include <apss.h>
+#include <dcom.h>
+#include <dcom_service_codes.h>
+#include <occ_service_codes.h>
+#include <trac.h>
+#include <proc_pstate.h>
+#include <amec_sys.h>
+#include <amec_master_smh.h>
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+extern UINT8 g_amec_tb_record; // from amec_amester.c for syncronized traces
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+
+
+// SSX Block Copy Request for the Slave Inbox Transmit Queue
+BceRequest G_slv_inbox_tx_pba_request;
+
+// Used by the master to house the doorbell data that is sent in
+// the master multicast doorbell, stating that it put slave inbox in main memory.
+dcom_slv_inbox_doorbell_t G_dcom_slv_inbox_doorbell_tx;
+
+// Make sure that the Slave Inbox TX Buffer is 256B, otherwise cause
+// error on the compile.
+STATIC_ASSERT( (NUM_BYTES_IN_SLAVE_INBOX != (sizeof(G_dcom_slv_inbox_tx)/MAX_OCCS)) );
+
+// Store return code and failed packet # from pbax_send so we can trace it
+uint32_t G_pbax_rc = 0;
+uint32_t G_pbax_packet = 0xffffffff;
+
+//Used to keep count of number of APSS data collection fails.
+uint8_t G_apss_fail_updown_count = 0x00;
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: dcom_build_slv_inbox
+//
+// Description: The purpose of this function is to copy the Control Data into
+// the Slave inbox structures so that the Master can send it out.
+// Build the slave inboxes so master can send them to slaves
+//
+// Flow: 06/19/13 FN=dcom_build_slv_inbox
+//
+// changedby: @at013c, @fk001c
+//
+// End Function Specification
+
+uint32_t dcom_build_slv_inbox(void)
+{
+ // Locals
+ uint32_t l_addr_of_slv_inbox_in_main_mem = 0;
+ uint32_t l_slv_idx = 0;
+ uint32_t l_core_idx = 0;
+ uint32_t l_cntr_idx = 0;
+ uint32_t l_mem_intr_idx = 0;
+
+ static uint8_t L_seq = 0xFF;
+
+ L_seq++;
+
+ //If there was a pbax_send failure, trace it here since we can't do it in the critical
+ //interrupt context.
+ if(G_pbax_rc)
+ {
+ TRAC_INFO("PBAX Send Failure in transimitting multicast doorbell - RC[%08X], packet[%d]", G_pbax_rc, G_pbax_packet);
+ }
+
+
+ //INBOX...............
+ //For each occ slave collect its occ data.
+ for(; l_slv_idx < MAX_OCCS; l_slv_idx++)
+ {
+ G_dcom_slv_inbox_tx[l_slv_idx].seq = L_seq;
+ G_dcom_slv_inbox_tx[l_slv_idx].version = 0;
+ //G_dcom_slv_inbox_tx[l_slv_idx].ambient_temp = //Activate when ambient temperature is available.
+ //G_dcom_slv_inbox_tx[l_slv_idx].altitude = //Acitivate when altitude is available.
+
+ //TODO: adc,gpio,and tod are only sent here for sanity check and for bringup only.
+ //If the values are needed by the slaves, they should use the values sent in the doorbell.
+ //Probably remove them after bringup is complete.
+ memcpy( G_dcom_slv_inbox_tx[l_slv_idx].adc, G_apss_pwr_meas.adc, sizeof(G_dcom_slv_inbox_tx[l_slv_idx].adc));
+ memcpy( G_dcom_slv_inbox_tx[l_slv_idx].gpio, G_apss_pwr_meas.gpio, sizeof(G_dcom_slv_inbox_tx[l_slv_idx].gpio));
+ memcpy( G_dcom_slv_inbox_tx[l_slv_idx].tod, &G_apss_pwr_meas.tod, sizeof( G_dcom_slv_inbox_tx[l_slv_idx].tod )); //TODO - this doesn't work
+
+ memset( G_dcom_slv_inbox_tx[l_slv_idx].occ_fw_mailbox, 0, sizeof( G_dcom_slv_inbox_tx[l_slv_idx].occ_fw_mailbox ));
+
+ //Collect frequency data for each core
+ for( l_core_idx = 0; l_core_idx < MAX_CORES; l_core_idx++)
+ {
+ // TODO - uncomment once macro exists
+ //G_dcom_slv_inbox_tx[l_slv_idx].freq250usp0cy = FREQ250USPC[l_core_idx];
+ G_dcom_slv_inbox_tx[l_slv_idx].freq250usp0cy[l_core_idx] = l_core_idx;
+ }
+
+ //collect data for each centaur throttle
+ for( l_cntr_idx = 0; l_cntr_idx < MAX_CENTAUR_THROTTLES; l_cntr_idx++)
+ {
+ // TODO - uncomment once macro exists
+ //G_dcom_slv_inbox_tx[l_slv_idx].memsp2msP0MxCyPz = MEMSP2MSP0MxCyPz[l_cntr_idx];
+ G_dcom_slv_inbox_tx[l_slv_idx].memsp2msP0MxCyPz[l_cntr_idx] = l_cntr_idx;
+ }
+
+ //collect data for each mem interleave group throttle
+ for( l_mem_intr_idx = 0; l_mem_intr_idx < MAX_MEM_INTERLEAVE_GROUP_THROTTLES; l_mem_intr_idx++)
+ {
+ // TODO - uncomment once macro exists
+ //G_dcom_slv_inbox_tx[l_slv_idx].memsp2msP0IGx = MEMSP2MSP0IG[l_mem_intr_idx];
+ G_dcom_slv_inbox_tx[l_slv_idx].memsp2msP0IGx[l_mem_intr_idx] = l_mem_intr_idx;
+ }
+
+ //collect mnfg parameters that need to be sent to slaves
+ G_dcom_slv_inbox_tx[l_slv_idx].foverride_enable = g_amec->mnfg_parms.auto_slew;
+ G_dcom_slv_inbox_tx[l_slv_idx].foverride = g_amec->mnfg_parms.foverride;
+ G_dcom_slv_inbox_tx[l_slv_idx].emulate_oversub = AMEC_INTF_GET_OVERSUBSCRIPTION_EMULATION();
+
+ //collect Idle Power Saver parameters to be sent to slaves
+ G_dcom_slv_inbox_tx[l_slv_idx].ips_freq_request = g_amec->mst_ips_parms.freq_request;
+
+ //collect Tunable Paramaters to be sent to slaves
+ G_dcom_slv_inbox_tx[l_slv_idx].alpha_up = G_mst_tunable_parameter_table_ext[0].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].alpha_down = G_mst_tunable_parameter_table_ext[1].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].sample_count_util = G_mst_tunable_parameter_table_ext[2].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].step_up = G_mst_tunable_parameter_table_ext[3].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].step_down = G_mst_tunable_parameter_table_ext[4].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].epsilon_perc = G_mst_tunable_parameter_table_ext[5].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].tlutil = G_mst_tunable_parameter_table_ext[6].adj_value;
+ G_dcom_slv_inbox_tx[l_slv_idx].tunable_param_overwrite = G_mst_tunable_parameter_overwrite;
+
+ //collect soft frequency bondaries to be sent to slaves
+ G_dcom_slv_inbox_tx[l_slv_idx].soft_fmin = G_mst_soft_fmin;
+ G_dcom_slv_inbox_tx[l_slv_idx].soft_fmax = G_mst_soft_fmax;
+
+ //send trace recording bit to slaves for synchronized tracing. //Lefurgy
+ G_dcom_slv_inbox_tx[l_slv_idx].tb_record = g_amec_tb_record;
+
+ G_dcom_slv_inbox_tx[l_slv_idx].counter++; // @th002
+
+ memcpy( &G_dcom_slv_inbox_tx[l_slv_idx].sys_mode_freq,
+ &G_sysConfigData.sys_mode_freq,
+ sizeof( freqConfig_t )); // @th040
+ }
+
+ //Clear the tunable parameter overwrite once we collect the new values
+ G_mst_tunable_parameter_overwrite = 0;
+
+ //@01a
+ dcom_build_occfw_msg( SLAVE_INBOX );
+
+ // Copy Data from one DCM pair's Outbox to other DCM pair's inbox
+ dcom_build_dcm_sync_msg( SLAVE_INBOX ); // @th010
+
+ l_addr_of_slv_inbox_in_main_mem = dcom_which_buffer();
+
+ //DOORBELL.................
+ //Prepare data for doorbell. This is sent to all OCCs
+
+ G_dcom_slv_inbox_doorbell_tx.pob_id = G_pob_id;
+ G_dcom_slv_inbox_doorbell_tx.magic1 = PBAX_MAGIC_NUMBER2_32B;
+ G_dcom_slv_inbox_doorbell_tx.addr_slv_inbox_buffer0 = l_addr_of_slv_inbox_in_main_mem;
+
+ memcpy( (void *) &G_dcom_slv_inbox_doorbell_tx.pcap,
+ (void *) &G_master_pcap_data, // @at013c @fk001c
+ sizeof(pcap_config_data_t));
+
+ G_dcom_slv_inbox_doorbell_tx.ppb_fmax = G_sysConfigData.master_ppb_fmax; //master ppb fmax is calculated in amec_ppb_fmax_calc
+
+ memcpy( (void *) &G_dcom_slv_inbox_doorbell_tx.adc[0],
+ (void *) &G_apss_pwr_meas.adc[0],
+ sizeof( G_dcom_slv_inbox_doorbell_tx.adc ));
+
+ G_dcom_slv_inbox_doorbell_tx.gpio[0] = G_apss_pwr_meas.gpio[0];
+ G_dcom_slv_inbox_doorbell_tx.gpio[1] = G_apss_pwr_meas.gpio[1];
+ G_dcom_slv_inbox_doorbell_tx.tod = G_apss_pwr_meas.tod;
+
+ G_dcom_slv_inbox_doorbell_tx.magic_counter++;
+ G_dcom_slv_inbox_doorbell_tx.magic2 = PBAX_MAGIC_NUMBER_32B;
+
+ return l_addr_of_slv_inbox_in_main_mem;
+}
+
+
+// Function Specification
+//
+// Name: dcom_which_buffer
+//
+// Description: Determines which buffer in the 'double buffer'
+// or ping/pong to use. Basically alternates between
+// returning the ping or the pong address
+//
+// Flow: 08/23/11 FN=dcom_which_buffer
+//
+// End Function Specification
+
+uint32_t dcom_which_buffer(void)
+{
+ //Locals
+ uint32_t l_mem_address = ADDR_SLAVE_INBOX_MAIN_MEM_PONG;
+
+ // switch back and forth based on tick
+ if( CURRENT_TICK & 1 )
+ {
+ l_mem_address = ADDR_SLAVE_INBOX_MAIN_MEM_PING;
+ }
+
+ return l_mem_address;
+}
+
+
+// Function Specification
+//
+// Name: task_dcom_tx_slv_inbox
+//
+// Description: Copy slave inboxes from SRAM to main memory
+// so master can send data to slave
+//
+// Flow: 08/23/11 FN=task_dcom_tx_slv_inbox
+//
+// Task Flags: RTL_FLAG_MSTR, RTL_FLAG_OBS, RTL_FLAG_ACTIVE
+//
+// Changes: @fk005c
+//
+// End Function Specification
+void task_dcom_tx_slv_inbox( task_t *i_self)
+{
+ static bool l_error = FALSE;
+ uint32_t l_orc = OCC_SUCCESS_REASON_CODE;
+ uint32_t l_orc_ext = OCC_NO_EXTENDED_RC; // @nh001a
+ uint64_t l_start = ssx_timebase_get();
+ bool l_pwr_meas = FALSE; // @th002
+ bool l_request_reset = FALSE; // @fk005a
+ bool l_ssx_failure = FALSE;
+ // @sb003 Use a static local bool to track whether the BCE request used
+ // here has ever been successfully created at least once
+ static bool L_bce_slv_inbox_tx_request_created_once = FALSE;
+
+ DCOM_DBG("4. TX Slave Inbox\n");
+
+ do
+ {
+ // If we are in standby, we need to fake out
+ // the APSS data since we aren't talking to APSS.
+ if( OCC_STATE_STANDBY == CURRENT_STATE() ) // @th022
+ {
+ G_ApssPwrMeasCompleted = TRUE; // @th022
+ }
+
+ l_pwr_meas = G_ApssPwrMeasCompleted; // @th002
+
+ //did apss pwr complete?
+ if( l_pwr_meas == TRUE ) // @th002
+ {
+#ifdef DCOM_DEBUG
+ uint64_t l_end = ssx_timebase_get();
+ DCOM_DBG("Got APSS after waiting %d us\n",(int)( (l_end-l_start) / ( SSX_TIMEBASE_FREQUENCY_HZ / 1000000 ) ));
+#endif
+
+ //@fk005a
+ APSS_SUCCESS();
+
+ // build/setup inboxes
+ uint32_t l_addr_in_mem = dcom_build_slv_inbox();
+ uint32_t l_ssxrc = 0;
+
+ // @sb003
+ // See dcomMasterRx.c/task_dcom_rx_slv_outboxes for details on the
+ // checking done here before creating and scheduling the request.
+ bool l_proceed_with_request_and_schedule = FALSE;
+ int l_req_idle = async_request_is_idle(&(G_slv_inbox_tx_pba_request.request));
+ int l_req_complete = async_request_completed(&(G_slv_inbox_tx_pba_request.request));
+
+ if (!L_bce_slv_inbox_tx_request_created_once)
+ {
+ // Do this case first, all other cases assume that this is
+ // true!
+ // This is the first time we have created a request so
+ // always proceed with request create and schedule
+ l_proceed_with_request_and_schedule = TRUE;
+ }
+ else if (l_req_idle && l_req_complete)
+ {
+ // Most likely case first. The request was created
+ // and scheduled and has completed without error. Proceed.
+ // Proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = TRUE;
+ }
+ else if (l_req_idle && !l_req_complete)
+ {
+ // There was an error on the schedule request or the request
+ // was scheduled but was canceled, killed or errored out.
+ // Proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = TRUE;
+ // Trace important information from the request
+ TRAC_INFO("BCE slv inbox tx request idle but not complete, \
+ callback_rc=%d options=0x%x state=0x%x abort_state=0x%x \
+ completion_state=0x%x",
+ G_slv_inbox_tx_pba_request.request.callback_rc,
+ G_slv_inbox_tx_pba_request.request.options,
+ G_slv_inbox_tx_pba_request.request.state,
+ G_slv_inbox_tx_pba_request.request.abort_state,
+ G_slv_inbox_tx_pba_request.request.completion_state);
+ TRAC_INFO("Proceeding with BCE slv inbox tx request and schedule");
+ }
+ else if (!l_req_idle && !l_req_complete)
+ {
+ // The request was created and scheduled but is still in
+ // progress or still enqueued OR there was some error
+ // creating the request so it was never scheduled. The latter
+ // case is unlikely and will generate an error message when
+ // it occurs. It will also have to happen after the request
+ // was created at least once or we'll never get here. If the
+ // request does fail though before the state parms in the
+ // request are reset (like a bad parameter error), then this
+ // represents a hang condition that we can't recover from.
+ // DO NOT proceed with request create and schedule.
+ l_proceed_with_request_and_schedule = FALSE;
+ // Trace important information from the request
+ TRAC_INFO("BCE slv inbox tx request not idle and not complete, \
+ callback_rc=%d options=0x%x state=0x%x abort_state=0x%x \
+ completion_state=0x%x",
+ G_slv_inbox_tx_pba_request.request.callback_rc,
+ G_slv_inbox_tx_pba_request.request.options,
+ G_slv_inbox_tx_pba_request.request.state,
+ G_slv_inbox_tx_pba_request.request.abort_state,
+ G_slv_inbox_tx_pba_request.request.completion_state);
+ TRAC_INFO("NOT proceeding with BCE slv inbox tx request and schedule");
+ }
+ // else {// This case can't happen, ignore it.}
+
+ // @sb003 Only proceed if the BCE request state checked out
+ if (l_proceed_with_request_and_schedule)
+ {
+ // set up inboxes copy request
+ l_ssxrc = bce_request_create(
+ &G_slv_inbox_tx_pba_request, // block copy object
+ &G_pba_bcue_queue, // mainstore to sram copy engine
+ l_addr_in_mem, // mainstore address
+ (uint32_t) &G_dcom_slv_inbox_tx[0], // sram starting address
+ sizeof(G_dcom_slv_inbox_tx), // size of copy // @th002
+ SSX_WAIT_FOREVER, // no timeout
+ (AsyncRequestCallback)dcom_tx_slv_inbox_doorbell, // call back
+ NULL, // call back arguments
+ ASYNC_CALLBACK_IMMEDIATE // callback mask
+ );
+
+ if(l_ssxrc != SSX_OK)
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_TX_SLV_INBOX
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 N/A
+ * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ TRAC_ERR("PBA request create failure rc=[%08X]",l_ssxrc);
+ l_orc = SSX_GENERIC_FAILURE; // @nh001c
+ l_orc_ext = ERC_BCE_REQUEST_CREATE_FAILURE; // @nh001a
+ l_ssx_failure = TRUE; // @wb001
+ break;
+ }
+
+ // @sb003 Request created at least once
+ L_bce_slv_inbox_tx_request_created_once = TRUE; // @sb013
+ l_ssxrc = bce_request_schedule(&G_slv_inbox_tx_pba_request); // actual copying
+
+ if(l_ssxrc != SSX_OK)
+ {
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_TX_SLV_INBOX
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 N/A
+ * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE
+ * @devdesc SSX BCE related failure
+ */
+ TRAC_ERR("PBA request schedule failure rc=[%08X]",l_ssxrc);
+ l_orc = SSX_GENERIC_FAILURE; // @nh001c
+ l_orc_ext = ERC_BCE_REQUEST_SCHEDULE_FAILURE; // @nh001a
+ l_ssx_failure = TRUE; // @wb001
+ break;
+ }
+ }
+ // @sb023 Moved the break statement here in case we decide not to
+ // schedule the BCE request.
+ break;
+ }
+ else
+ {
+ // check time and break out if we reached limit
+ // @th032 -- TODO: shrink this later depending on how much
+ // work we are doing in RTL
+ if ((ssx_timebase_get() - l_start) < SSX_MICROSECONDS(150))
+ {
+ continue;
+ }
+ else
+ {
+ //Failure occurred, step up the FAIL_COUNT
+ APSS_FAIL();
+
+
+ if (G_apss_fail_updown_count >= APSS_DATA_FAIL_MAX)
+ {
+ TRAC_ERR("task_dcom_tx_slv_inbox: APSS data collection failure exceeded threshold. fail_count=%i, threshold:%i",
+ G_apss_fail_updown_count, APSS_DATA_FAIL_MAX);
+
+ /* @
+ * @errortype
+ * @moduleid DCOM_MID_TASK_TX_SLV_INBOX
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 N/A
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Time out waiting on power measurement completion
+ */
+ TRAC_ERR("Timed out waiting apss meas completion (dcom_start:%d us, apss_start:%d us, apss_end:%d us)",
+ (int) ((l_start)/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)),
+ (int) ((G_gpe_apss_time_start)/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)),
+ (int) ((G_gpe_apss_time_end)/(SSX_TIMEBASE_FREQUENCY_HZ/1000000))); // @jh00ac
+ l_orc = INTERNAL_FAILURE; // @nh001c
+ l_orc_ext = OCC_NO_EXTENDED_RC; // @nh001a
+ l_request_reset = TRUE; // @fk005a
+
+ }
+ break;
+ }
+ }
+
+ } while (1); // @th002
+
+ //If an error exists and we have not logged one before or there's a new request to reset, then log error.
+ if ( (l_orc != OCC_SUCCESS_REASON_CODE) && ((l_error == FALSE) || (l_request_reset == TRUE)))
+ {
+ // create and commit error only once.
+ errlHndl_t l_errl = createErrl(
+ DCOM_MID_TASK_TX_SLV_INBOX, //modId
+ l_orc, //reasoncode // @nh001c
+ l_orc_ext, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0 //userdata2
+ );
+
+ // @wb001 -- Callout to firmware
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ if ( FALSE == l_ssx_failure ) // @wb001
+ {
+ // Callout to processor
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+
+ // Callout to APSS
+ addCalloutToErrl(l_errl,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.apss_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+ }
+
+ if (l_request_reset)
+ {
+ REQUEST_RESET(l_errl);
+ }
+ else
+ {
+ commitErrl(&l_errl);
+ }
+
+ l_error = TRUE;
+ l_request_reset = FALSE;
+ }
+
+}
+
+
+// Function Specification
+//
+// Name: dcom_tx_slv_inbox_doorbell
+//
+// Description: transmit doorbells to slaves
+// from master
+//
+// Flow: 08/23/11 FN=dcom_tx_slv_inbox_doorbell
+//
+// End Function Specification
+void dcom_tx_slv_inbox_doorbell( void )
+{
+ int l_pbarc = 0;
+ int l_tmp = 0;
+ int l_jj = 0;
+ uint64_t l_start = ssx_timebase_get();
+
+ /// Caclulate how many 8 byte packets are in the doorbell
+ l_tmp = sizeof( G_dcom_slv_inbox_doorbell_tx ) / sizeof(uint64_t);
+
+ /// Loop through all packets, sending one at a time. It should send
+ /// the previous packet almost immediately, but it is worth noting that
+ /// it is *possible* that the PowerBus is backed up, in which case it may
+ /// take a short amount of time (~1us <TBD>) to send each packet.
+ /// Estimated transfer time, under normal circumstances is 1kB/1us.
+ for(l_jj=0; l_jj<l_tmp; l_jj++)
+ {
+ // Send 8 bytes of multicast doorbell
+ l_pbarc = _pbax_send( &G_pbax_multicast_target, //gm014
+ G_dcom_slv_inbox_doorbell_tx.words[l_jj],
+ SSX_MICROSECONDS(15));
+
+ //Set this global so we know to trace this in the non-critical interrupt context
+ G_pbax_rc = l_pbarc;
+ if ( (l_pbarc != 0 ) )
+ {
+ G_pbax_packet = l_jj;
+ //Trace causes a panic in a critical interrupt! Don't trace here!(tries to pend a semaphore)
+
+ /// Break out of for loop and stop sending the rest of the doorbell
+ /// packets, since this likely occured b/c of a timeout.
+ break;
+ }
+ }
+
+ // <TULETA HW BRINGUP TIMING> @th032
+ uint64_t l_delta = (ssx_timebase_get() - l_start);
+ G_dcomTime.master.doorbellStartTx = l_start;
+ G_dcomTime.master.doorbellStopTx = ssx_timebase_get();
+ G_dcomTime.master.doorbellMaxDeltaTx = (l_delta > G_dcomTime.master.doorbellMaxDeltaTx) ?
+ l_delta : G_dcomTime.master.doorbellMaxDeltaTx;
+ G_dcomTime.master.doorbellSeq = G_dcom_slv_inbox_doorbell_tx.magic_counter;
+ G_dcomTime.master.doorbellNumSent++;
+ // </TULETA HW BRINGUP TIMING> @th032
+
+ DCOM_DBG("Sent multicast doorbell\n");
+} // @th034 - rewrote most of functino
+
+#endif //_DCOMMASTERTOSLAVE_C
+
OpenPOWER on IntegriCloud