+
+/*******************************************************************
+ *
+ * @brief Fill and send statistics response to MAC
+ *
+ * @details
+ *
+ * Function : SchSendStatsRspToMac
+ *
+ * Functionality: Fill and send statistics response to MAC
+ *
+ * @params[in] Inst inst, SchMacRsp result
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t SchSendStatsRspToMac(Inst inst, SchMacRsp result, CauseOfResult cause)
+{
+ Pst rspPst;
+ uint8_t ret = ROK;
+ SchStatsRsp *statsRsp;
+
+ DU_LOG("\nINFO --> SCH : Filling statistics response");
+ SCH_ALLOC(statsRsp, sizeof(SchStatsRsp));
+ if(statsRsp == NULLP)
+ {
+ DU_LOG("\nERROR --> SCH : Failed to allocate memory in SchSendStatsRspToMac()");
+ return RFAILED;
+ }
+ memset(statsRsp, 0, sizeof(SchStatsRsp));
+ statsRsp->rsp = result;
+ statsRsp->cause = cause;
+
+ /* Filling response post */
+ memset(&rspPst, 0, sizeof(Pst));
+ FILL_PST_SCH_TO_MAC(rspPst, inst);
+ rspPst.event = EVENT_STATISTICS_RSP_TO_MAC;
+
+ ret = MacMessageRouter(&rspPst, (void *)statsRsp);
+ if(ret == RFAILED)
+ {
+ DU_LOG("\nERROR --> SCH : SchSendStatsRspToMac(): Failed to send Statistics Response");
+ return ret;
+ }
+ return ret;
+}
+
+/*******************************************************************
+ *
+ * @brief Processes Statistics Request from MAC
+ *
+ * @details
+ *
+ * Function : SchProcStatsReq
+ *
+ * Functionality:
+ * Processes Statistics Request from MAC
+ *
+ * @params[in]
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t SchProcStatsReq(Pst *pst, SchStatsReq *statsReq)
+{
+ uint8_t idx;
+ Inst inst = pst->dstInst - SCH_INST_START;
+ SchMacRsp rsp = RSP_OK;
+ CauseOfResult cause = SUCCESSFUL;
+ bool isDlTotlPrbUseCfgd = false, isUlTotlPrbUseCfgd = false;
+
+ DU_LOG("\nINFO --> SCH : Received Statistics Request from MAC");
+
+ for(idx=0; idx < statsReq->numStats; idx++)
+ {
+ switch(statsReq->statsList[idx].type)
+ {
+ case SCH_DL_TOTAL_PRB_USAGE:
+ {
+ /* Check if duplicate configuration */
+ if(schCb[inst].statistics.dlTotalPrbUsage)
+ {
+ DU_LOG("\nERROR --> SCH : SCH_DL_TOTAL_PRB_USAGE stats already configured");
+ rsp = RSP_NOK;
+ cause = DUPLICATE_ENTRY;
+ }
+
+ /* Allocate memory */
+ SCH_ALLOC(schCb[inst].statistics.dlTotalPrbUsage, sizeof(TotalPrbUsage));
+ if(!schCb[inst].statistics.dlTotalPrbUsage)
+ {
+ DU_LOG("\nERROR --> SCH : Memory allocation failed for dlTotalPrbUsage in \
+ SchProcStatsReq()");
+ rsp = RSP_NOK;
+ cause = RESOURCE_UNAVAILABLE;
+ break;
+ }
+
+ /* Initialize */
+ memset(schCb[inst].statistics.dlTotalPrbUsage, 0, sizeof(TotalPrbUsage));
+
+ /* Configure */
+ schCb[inst].statistics.dlTotalPrbUsage->schInst = inst;
+ schCb[inst].statistics.dlTotalPrbUsage->periodicity = statsReq->statsList[idx].periodicity;
+ cmInitTimers(&(schCb[inst].statistics.dlTotalPrbUsage->periodTimer), 1);
+
+ /* Start timer */
+ schStartTmr(&schCb[inst], (PTR)(schCb[inst].statistics.dlTotalPrbUsage), \
+ EVENT_DL_TOTAL_PRB_USAGE_TMR, schCb[inst].statistics.dlTotalPrbUsage->periodicity);
+
+ isDlTotlPrbUseCfgd = true;
+ break;
+ }
+
+ case SCH_UL_TOTAL_PRB_USAGE:
+ {
+ /* Check if duplicate configuration */
+ if(schCb[inst].statistics.ulTotalPrbUsage)
+ {
+ DU_LOG("\nERROR --> SCH : SCH_UL_TOTAL_PRB_USAGE stats already configured");
+ rsp = RSP_NOK;
+ cause = DUPLICATE_ENTRY;
+ }
+
+ /* Allocate memory */
+ SCH_ALLOC(schCb[inst].statistics.ulTotalPrbUsage, sizeof(TotalPrbUsage));
+ if(!schCb[inst].statistics.ulTotalPrbUsage)
+ {
+ DU_LOG("\nERROR --> SCH : Memory allocation failed for ulTotalPrbUsage in \
+ SchProcStatsReq()");
+ rsp = RSP_NOK;
+ cause = RESOURCE_UNAVAILABLE;
+ break;
+ }
+
+ /* Initialize */
+ memset(schCb[inst].statistics.ulTotalPrbUsage, 0, sizeof(TotalPrbUsage));
+
+ /* Configure */
+ schCb[inst].statistics.ulTotalPrbUsage->schInst = inst;
+ schCb[inst].statistics.ulTotalPrbUsage->periodicity = statsReq->statsList[idx].periodicity;
+ cmInitTimers(&(schCb[inst].statistics.ulTotalPrbUsage->periodTimer), 1);
+
+ /* Start timer */
+ schStartTmr(&schCb[inst], (PTR)(schCb[inst].statistics.ulTotalPrbUsage), \
+ EVENT_UL_TOTAL_PRB_USAGE_TMR, schCb[inst].statistics.ulTotalPrbUsage->periodicity);
+
+ isUlTotlPrbUseCfgd = true;
+ break;
+ }
+ default:
+ {
+ DU_LOG("\nERROR --> SCH : Invalid statistics type [%d]", statsReq->statsList[idx].type);
+ rsp = RSP_NOK;
+ cause = PARAM_INVALID;
+ }
+ } /* End of switch */
+
+ if(rsp == RSP_NOK)
+ {
+ /* If failed to configure any KPI, then clear configuration of other
+ * KPIs that were configured successfully as part of this statsReq */
+ if(isDlTotlPrbUseCfgd)
+ {
+ if((schChkTmr((PTR)(schCb[inst].statistics.dlTotalPrbUsage), EVENT_DL_TOTAL_PRB_USAGE_TMR)) == FALSE)
+ {
+ schStopTmr(&schCb[inst], (PTR)(schCb[inst].statistics.dlTotalPrbUsage), EVENT_DL_TOTAL_PRB_USAGE_TMR);
+ }
+ SCH_FREE(schCb[inst].statistics.dlTotalPrbUsage, sizeof(TotalPrbUsage));
+ }
+
+ if(isUlTotlPrbUseCfgd)
+ {
+ if((schChkTmr((PTR)(schCb[inst].statistics.ulTotalPrbUsage), EVENT_UL_TOTAL_PRB_USAGE_TMR)) == FALSE)
+ {
+ schStopTmr(&schCb[inst], (PTR)(schCb[inst].statistics.ulTotalPrbUsage), EVENT_UL_TOTAL_PRB_USAGE_TMR);
+ }
+ SCH_FREE(schCb[inst].statistics.ulTotalPrbUsage, sizeof(TotalPrbUsage));
+ }
+ break;
+ }
+ } /* End of FOR */
+
+ SCH_FREE(statsReq, sizeof(SchStatsReq));
+
+ SchSendStatsRspToMac(inst, rsp, cause);
+
+ return ROK;
+} /* End of SchProcStatsReq */
+