664 lines
18 KiB
C
664 lines
18 KiB
C
/*******************************************************************************
|
|
** This file is provided under a dual BSD/GPLv2 license. When using or
|
|
** redistributing this file, you may do so under either license.
|
|
**
|
|
** GPL LICENSE SUMMARY
|
|
**
|
|
** Copyright (c) 2013 Intel Corporation All Rights Reserved
|
|
**
|
|
** This program is free software; you can redistribute it and/or modify it under
|
|
** the terms of version 2 of the GNU General Public License as published by the
|
|
** Free Software Foundation.
|
|
**
|
|
** This program is distributed in the hope that it will be useful, but WITHOUT
|
|
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
** details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License along with
|
|
** this program; if not, write to the Free Software Foundation, Inc.,
|
|
** 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
** The full GNU General Public License is included in this distribution in the
|
|
** file called LICENSE.GPL.
|
|
**
|
|
** BSD LICENSE
|
|
**
|
|
** Copyright (c) 2013 Intel Corporation All Rights Reserved
|
|
**
|
|
** Redistribution and use in source and binary forms, with or without
|
|
** modification, are permitted provided that the following conditions are met:
|
|
**
|
|
** * Redistributions of source code must retain the above copyright notice, this
|
|
** list of conditions and the following disclaimer.
|
|
** * Redistributions in binary form must reproduce the above copyright notice,
|
|
** this list of conditions and the following disclaimer in the documentation
|
|
** and/or other materials provided with the distribution.
|
|
** * Neither the name of Intel Corporation nor the names of its contributors may
|
|
** be used to endorse or promote products derived from this software without
|
|
** specific prior written permission.
|
|
**
|
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
** POSSIBILITY OF SUCH DAMAGE.
|
|
**
|
|
*******************************************************************************/
|
|
|
|
#include "esif_pm.h"
|
|
#include "esif_lf.h"
|
|
#include "esif_lf_poll.h"
|
|
|
|
#ifdef ESIF_ATTR_OS_WINDOWS
|
|
|
|
/*
|
|
* The Windows banned-API check header must be included after all other headers,
|
|
* or issues can be identified against Windows SDK/DDK included headers which
|
|
* we have no control over.
|
|
*/
|
|
#define _SDL_BANNED_RECOMMENDED
|
|
#include "win\banned.h"
|
|
#endif
|
|
|
|
#define INIT_DEBUG 0
|
|
#define PM_DEBUG 1
|
|
|
|
#define ESIF_TRACE_DYN_INIT(format, ...) \
|
|
ESIF_TRACE_DYN(ESIF_DEBUG_MOD_PMG, INIT_DEBUG, format, ##__VA_ARGS__)
|
|
#define ESIF_TRACE_DYN_PM(format, ...) \
|
|
ESIF_TRACE_DYN(ESIF_DEBUG_MOD_PMG, PM_DEBUG, format, ##__VA_ARGS__)
|
|
|
|
/*
|
|
*******************************************************************************
|
|
** PRIVATE
|
|
*******************************************************************************
|
|
*/
|
|
|
|
/* Participant Manager Entry */
|
|
struct esif_pme {
|
|
enum esif_pm_participant_state state; /* Current Participant State */
|
|
struct esif_participant_iface *pi_ptr; /* Participant INTERFACE */
|
|
struct esif_lp *lp_ptr; /* Lower Participant Instance */
|
|
};
|
|
|
|
/* Package Manager */
|
|
struct esif_pm {
|
|
u8 pme_count; /* Current Reference Count */
|
|
struct esif_pme pme[MAX_PARTICIPANT_ENTRY]; /* Maximum Participants */
|
|
esif_ccb_lock_t lock; /* Package Manager Lock */
|
|
};
|
|
|
|
/*
|
|
** Package Manager. Keeps Track of all participant interfaces, lower
|
|
** participants and there corresponding state
|
|
*/
|
|
static struct esif_pm g_pm = {0};
|
|
|
|
/* Allocate Lower Participant Instance */
|
|
static struct esif_lp *esif_pm_lp_alloc(void)
|
|
{
|
|
struct esif_lp *lp_ptr = NULL;
|
|
|
|
lp_ptr = (struct esif_lp *)
|
|
esif_ccb_mempool_zalloc(ESIF_MEMPOOL_TYPE_PM);
|
|
|
|
return lp_ptr;
|
|
}
|
|
|
|
|
|
/* Free Lower Participant Instance */
|
|
static void esif_pm_lp_free(
|
|
struct esif_lp *lp_ptr
|
|
)
|
|
{
|
|
if (NULL == lp_ptr)
|
|
return;
|
|
|
|
esif_ccb_mempool_free(ESIF_MEMPOOL_TYPE_PM, lp_ptr);
|
|
}
|
|
|
|
|
|
/*
|
|
*******************************************************************************
|
|
** PUBLIC
|
|
*******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
** Participant State Management
|
|
*/
|
|
|
|
/* Get Participant State */
|
|
enum esif_pm_participant_state esif_lf_pm_lp_get_state(
|
|
const struct esif_lp *lp_ptr
|
|
)
|
|
{
|
|
enum esif_pm_participant_state state;
|
|
|
|
state = ESIF_PM_PARTICIPANT_STATE_AVAILABLE;
|
|
|
|
if (lp_ptr->instance < MAX_PARTICIPANT_ENTRY) {
|
|
esif_ccb_read_lock(&g_pm.lock);
|
|
state = g_pm.pme[lp_ptr->instance].state;
|
|
esif_ccb_read_unlock(&g_pm.lock);
|
|
}
|
|
ESIF_TRACE_DYN_PM("%s: instance %d current state %s(%d)\n",
|
|
ESIF_FUNC,
|
|
lp_ptr->instance,
|
|
esif_pm_participant_state_str(state),
|
|
state);
|
|
return state;
|
|
}
|
|
|
|
static void esif_lf_pm_build_lpat(struct esif_lp *lp_ptr)
|
|
{
|
|
struct esif_lp_dsp *dsp_ptr = lp_ptr->dsp_ptr;
|
|
struct esif_primitive_tuple tuple_lpat = {
|
|
GET_TEMPERATURE_APPROX_TABLE, '0D', 255};
|
|
struct esif_data esif_lpat = {ESIF_DATA_BINARY, NULL, 0, 0};
|
|
struct esif_data esif_void = {ESIF_DATA_VOID, NULL, 0, 0};
|
|
enum esif_rc rc = ESIF_OK;
|
|
u32 size = sizeof(union esif_data_variant) * 1024; /* ie. 512 LPAT */
|
|
|
|
/* Allow Upto 512 LPAT Entries (Each Takes Two Integer In
|
|
* esif_data_variant{}, For Example, {{INT64, -20}, {UINT64, 997}}
|
|
* Represents An Entry {Temp=-20, RawValue=996} In LPAT ACPI Obj.)
|
|
*/
|
|
esif_lpat.buf_ptr = (void *)esif_ccb_malloc(size);
|
|
esif_lpat.buf_len = size;
|
|
if (NULL == esif_lpat.buf_ptr)
|
|
goto exit;
|
|
|
|
rc = esif_execute_primitive(lp_ptr, &tuple_lpat, &esif_void,
|
|
&esif_lpat, NULL);
|
|
if (ESIF_OK != rc) {
|
|
esif_ccb_free(esif_lpat.buf_ptr);
|
|
goto exit;
|
|
}
|
|
|
|
dsp_ptr->table = esif_lpat.buf_ptr;
|
|
dsp_ptr->table_size = esif_lpat.data_len;
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
/* Set Participant State */
|
|
enum esif_rc esif_lf_pm_lp_set_state(
|
|
struct esif_lp *lp_ptr,
|
|
const enum esif_pm_participant_state state
|
|
)
|
|
{
|
|
struct esif_lp_dsp *dsp_ptr = NULL;
|
|
enum esif_rc rc = ESIF_OK;
|
|
u8 i = 0;
|
|
|
|
if (NULL == lp_ptr) {
|
|
rc = ESIF_E_PARAMETER_IS_NULL;
|
|
goto exit;
|
|
}
|
|
ESIF_TRACE_DYN_PM("%s: instance %d new state %d\n",
|
|
ESIF_FUNC,
|
|
lp_ptr->instance,
|
|
state);
|
|
|
|
|
|
if (lp_ptr->instance >= MAX_PARTICIPANT_ENTRY) {
|
|
rc = ESIF_E_PARAMETER_IS_OUT_OF_BOUNDS;
|
|
goto exit;
|
|
}
|
|
|
|
esif_ccb_write_lock(&g_pm.lock);
|
|
g_pm.pme[lp_ptr->instance].state = state;
|
|
esif_ccb_write_unlock(&g_pm.lock);
|
|
|
|
/* Have DSP Instrument If We Have DSP */
|
|
if (ESIF_PM_PARTICIPANT_STATE_REGISTERED == state) {
|
|
rc = esif_lf_instrument_participant(lp_ptr);
|
|
if (ESIF_OK != rc)
|
|
goto exit;
|
|
|
|
/* Build LPAT Before Others Can Use Its Xform */
|
|
dsp_ptr = lp_ptr->dsp_ptr;
|
|
if (NULL != dsp_ptr) {
|
|
if (dsp_ptr->dsp_has_algorithm(dsp_ptr,
|
|
ESIF_ALGORITHM_TYPE_TEMP_LPAT) == ESIF_TRUE)
|
|
esif_lf_pm_build_lpat(lp_ptr);
|
|
}
|
|
|
|
/* Have DSP Instrument Domain */
|
|
for (i = 0; i < lp_ptr->domain_count; i++) {
|
|
struct esif_lp_domain *lpd_ptr = &lp_ptr->domains[i];
|
|
|
|
/* Assign Hysteresis Here with Best Effort */
|
|
if (lpd_ptr->capabilities &
|
|
ESIF_CAPABILITY_TEMP_STATUS) {
|
|
struct esif_data esif_void =
|
|
{ESIF_DATA_VOID, NULL, 0, 0};
|
|
struct esif_data esif_hyst = {
|
|
ESIF_DATA_UINT32,
|
|
&lpd_ptr->temp_hysteresis,
|
|
sizeof(u32),
|
|
sizeof(u32)
|
|
};
|
|
struct esif_data esif_tjmax = {
|
|
ESIF_DATA_UINT32,
|
|
&lpd_ptr->temp_tjmax,
|
|
sizeof(u32),
|
|
sizeof(u32)
|
|
};
|
|
struct esif_primitive_tuple tuple_hyst = {
|
|
GET_TEMPERATURE_THRESHOLD_HYSTERESIS,
|
|
lpd_ptr->id,
|
|
255
|
|
};
|
|
struct esif_primitive_tuple tuple_tjmax = {
|
|
GET_PROC_TJMAX,
|
|
lpd_ptr->id,
|
|
255
|
|
};
|
|
/*
|
|
* Grab and intitialize lpd_ptr->temp_tjmax =
|
|
* GET_PROC_TJ_MAX. Don't use DSP constant tc1
|
|
* for this any longer use this value it will
|
|
* change from 100 to 90 to 105 depending on SKU
|
|
* get it from the hardware here.
|
|
*
|
|
* We need to get it as soon as possible there
|
|
* is a silicon bug that causes this value to be
|
|
* reported as 0x40 hex after a connected standy
|
|
* cycle for now we need to work around this by
|
|
* reading it early and hanging onto the value.
|
|
*
|
|
* TJMAX from the DSP is no longer needed. We
|
|
* will leave the two TC values for
|
|
* future use.
|
|
*/
|
|
esif_execute_primitive(lpd_ptr->lp_ptr,
|
|
&tuple_hyst,
|
|
&esif_void,
|
|
&esif_hyst,
|
|
NULL);
|
|
|
|
|
|
/* Get Unit Data Needed By Power Conversion */
|
|
esif_execute_primitive(lpd_ptr->lp_ptr,
|
|
&tuple_tjmax,
|
|
&esif_void,
|
|
&esif_tjmax,
|
|
NULL);
|
|
ESIF_TRACE_DYN_PM(
|
|
"%s: dmn %s hyst %d tjmax %d\n",
|
|
ESIF_FUNC,
|
|
lpd_ptr->name_ptr,
|
|
lpd_ptr->temp_hysteresis,
|
|
lpd_ptr->temp_tjmax);
|
|
|
|
lpd_ptr->temp_aux0 = ESIF_DOMAIN_TEMP_INVALID;
|
|
lpd_ptr->temp_aux1 = ESIF_DOMAIN_TEMP_INVALID;
|
|
}
|
|
|
|
esif_lf_instrument_capability(lpd_ptr);
|
|
|
|
if (lpd_ptr->capabilities &
|
|
ESIF_CAPABILITY_POWER_STATUS) {
|
|
struct esif_data esif_void =
|
|
{ESIF_DATA_VOID, NULL, 0, 0};
|
|
struct esif_data esif_energy = {
|
|
ESIF_DATA_UINT32,
|
|
&lpd_ptr->unit_energy,
|
|
sizeof(u32),
|
|
sizeof(u32)
|
|
};
|
|
struct esif_data esif_power = {
|
|
ESIF_DATA_UINT32,
|
|
&lpd_ptr->unit_power,
|
|
sizeof(u32),
|
|
sizeof(u32)
|
|
};
|
|
struct esif_data esif_time = {
|
|
ESIF_DATA_UINT32,
|
|
&lpd_ptr->unit_time,
|
|
sizeof(u32), sizeof(u32)
|
|
};
|
|
struct esif_primitive_tuple tuple_energy = {
|
|
GET_RAPL_ENERGY_UNIT, lpd_ptr->id, 255
|
|
};
|
|
struct esif_primitive_tuple tuple_power = {
|
|
GET_RAPL_POWER_UNIT, lpd_ptr->id, 255
|
|
};
|
|
struct esif_primitive_tuple tuple_time = {
|
|
GET_RAPL_TIME_UNIT, lpd_ptr->id, 255
|
|
};
|
|
|
|
/* Get Unit Data Needed By Power Conversion
|
|
* lpd_ptr->unit_power = GET_RAPL_POWER_UNIT
|
|
* lpd_ptr->unit_energy = GET_RAPL_ENERGY_UNIT
|
|
* lpd_ptr->unit_time = GET_RAPL_TIME_UNIT
|
|
*/
|
|
esif_execute_primitive(lpd_ptr->lp_ptr,
|
|
&tuple_energy,
|
|
&esif_void,
|
|
&esif_energy,
|
|
NULL);
|
|
esif_execute_primitive(lpd_ptr->lp_ptr,
|
|
&tuple_power,
|
|
&esif_void,
|
|
&esif_power,
|
|
NULL);
|
|
esif_execute_primitive(lpd_ptr->lp_ptr,
|
|
&tuple_time,
|
|
&esif_void,
|
|
&esif_time,
|
|
NULL);
|
|
ESIF_TRACE_DYN_PM(
|
|
"%s: dmn %s id %d energy %d power %d "
|
|
"time %d\n",
|
|
ESIF_FUNC,
|
|
lpd_ptr->name_ptr,
|
|
lpd_ptr->id,
|
|
lpd_ptr->unit_energy,
|
|
lpd_ptr->unit_power,
|
|
lpd_ptr->unit_time);
|
|
|
|
lpd_ptr->power_aux0 = 0;
|
|
lpd_ptr->power_aux1 = 10000000; /* Something
|
|
*other than
|
|
*zero */
|
|
|
|
lpd_ptr->poll_mask |= ESIF_POLL_POWER;
|
|
esif_poll_start(lpd_ptr);
|
|
}
|
|
}
|
|
|
|
|
|
} else if (ESIF_PM_PARTICIPANT_STATE_NEEDDSP == state) {
|
|
/*
|
|
* Uninstrument domains that currently have a DSP
|
|
*/
|
|
for (i = 0; i < lp_ptr->domain_count; i++) {
|
|
struct esif_lp_domain *lpd_ptr = &lp_ptr->domains[i];
|
|
esif_poll_stop(lpd_ptr);
|
|
esif_lf_uninstrument_capability(lpd_ptr);
|
|
}
|
|
esif_lf_uninstrument_participant(lp_ptr);
|
|
|
|
} else if (ESIF_PM_PARTICIPANT_STATE_SUSPENDED == state) {
|
|
for (i = 0; i < lp_ptr->domain_count; i++) {
|
|
struct esif_lp_domain *lpd_ptr = &lp_ptr->domains[i];
|
|
esif_poll_stop(lpd_ptr);
|
|
}
|
|
|
|
} else if (ESIF_PM_PARTICIPANT_STATE_RESUMED == state) {
|
|
for (i = 0; i < lp_ptr->domain_count; i++) {
|
|
struct esif_lp_domain *lpd_ptr = &lp_ptr->domains[i];
|
|
if (lp_ptr->domains[i].poll_mask != 0)
|
|
esif_poll_start(lpd_ptr);
|
|
}
|
|
esif_ccb_write_lock(&g_pm.lock);
|
|
g_pm.pme[lp_ptr->instance].state = ESIF_PM_PARTICIPANT_STATE_REGISTERED;
|
|
esif_ccb_write_unlock(&g_pm.lock);
|
|
}
|
|
exit:
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
** Participant Lookups
|
|
*/
|
|
|
|
/* Get Lower Participant INTERFACE By Instance ID */
|
|
struct esif_participant_iface *esif_lf_pm_pi_get_by_instance_id(
|
|
const u8 instance
|
|
)
|
|
{
|
|
struct esif_participant_iface *pi_ptr = NULL;
|
|
ESIF_TRACE_DYN_PM("%s: instance %d\n", ESIF_FUNC, instance);
|
|
|
|
if (instance >= MAX_PARTICIPANT_ENTRY)
|
|
goto exit;
|
|
|
|
esif_ccb_read_lock(&g_pm.lock);
|
|
if (g_pm.pme[instance].state > ESIF_PM_PARTICIPANT_REMOVED)
|
|
pi_ptr = g_pm.pme[instance].pi_ptr;
|
|
|
|
esif_ccb_read_unlock(&g_pm.lock);
|
|
exit:
|
|
if (NULL == pi_ptr)
|
|
ESIF_TRACE_DYN_PM(
|
|
"%s: instance %d NOT found or OUT OF BOUNDS\n",
|
|
ESIF_FUNC,
|
|
instance);
|
|
return pi_ptr;
|
|
}
|
|
|
|
|
|
/* Get Lower Participant By Instance ID */
|
|
struct esif_lp *esif_lf_pm_lp_get_by_instance_id(
|
|
const u8 instance
|
|
)
|
|
{
|
|
struct esif_lp *lp_ptr = NULL;
|
|
ESIF_TRACE_DYN_PM("%s: instance %d\n", ESIF_FUNC, instance);
|
|
|
|
if (instance >= MAX_PARTICIPANT_ENTRY)
|
|
goto exit;
|
|
|
|
esif_ccb_read_lock(&g_pm.lock);
|
|
if (g_pm.pme[instance].state > ESIF_PM_PARTICIPANT_REMOVED)
|
|
lp_ptr = g_pm.pme[instance].lp_ptr;
|
|
|
|
esif_ccb_read_unlock(&g_pm.lock);
|
|
exit:
|
|
if (NULL == lp_ptr)
|
|
ESIF_TRACE_DYN_PM(
|
|
"%s: instance %d NOT found or OUT OF BOUNDS\n",
|
|
ESIF_FUNC,
|
|
instance);
|
|
return lp_ptr;
|
|
}
|
|
|
|
|
|
/* Get Lower Participant By Particiapnt Interface */
|
|
struct esif_lp *esif_lf_pm_lp_get_by_pi(
|
|
const struct esif_participant_iface *pi_ptr
|
|
)
|
|
{
|
|
u8 i = 0;
|
|
struct esif_lp *lp_ptr = NULL;
|
|
|
|
if (NULL == pi_ptr)
|
|
goto exit;
|
|
|
|
esif_ccb_read_lock(&g_pm.lock);
|
|
for (i = 0; i < MAX_PARTICIPANT_ENTRY; i++) {
|
|
if (g_pm.pme[i].pi_ptr == pi_ptr) {
|
|
/* Found */
|
|
if(g_pm.pme[i].state > ESIF_PM_PARTICIPANT_REMOVED)
|
|
lp_ptr = g_pm.pme[i].lp_ptr;
|
|
break;
|
|
}
|
|
}
|
|
|
|
esif_ccb_read_unlock(&g_pm.lock);
|
|
exit:
|
|
return lp_ptr; /* Not Found Will Be NULL */
|
|
}
|
|
|
|
|
|
/* Create Participant Instance */
|
|
struct esif_lp *esif_lf_pm_lp_create(
|
|
struct esif_participant_iface *pi_ptr
|
|
)
|
|
{
|
|
u8 i = 0;
|
|
struct esif_lp *lp_ptr = NULL;
|
|
|
|
/* Lock Package Manager */
|
|
esif_ccb_write_lock(&g_pm.lock);
|
|
|
|
if (NULL == pi_ptr)
|
|
goto exit;
|
|
|
|
ESIF_TRACE_DYN_PM("%s: pi %p\n", ESIF_FUNC, pi_ptr);
|
|
|
|
/*
|
|
* First check for a participant that was previously removed.
|
|
* If found, reset to initial state, update participant count, and then
|
|
* update the pi_ptr as that may have changed when the participant
|
|
* was reloaded.
|
|
*/
|
|
for (i = ESIF_INSTANCE_FIRST; i < MAX_PARTICIPANT_ENTRY; i++) {
|
|
if ((g_pm.pme[i].state != ESIF_PM_PARTICIPANT_STATE_AVAILABLE)
|
|
&& (!memcmp(g_pm.pme[i].lp_ptr->pi_name,
|
|
pi_ptr->name,
|
|
sizeof(pi_ptr->name)))) {
|
|
|
|
g_pm.pme[i].pi_ptr = pi_ptr;
|
|
g_pm.pme[i].state = ESIF_PM_PARTICIPANT_STATE_CREATED;
|
|
g_pm.pme_count++;
|
|
|
|
lp_ptr = g_pm.pme[i].lp_ptr;
|
|
lp_ptr->pi_ptr = pi_ptr;
|
|
ESIF_TRACE_DYN_PM("%s: lp %p\n", ESIF_FUNC, lp_ptr);
|
|
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
/* Find Available Slot In Package Manager Table */
|
|
if (pi_ptr->flags & ESIF_FLAG_DPTFZ) {
|
|
i = 0; /* Treat DPTFZ Special As ID 0 */
|
|
} else {
|
|
/*
|
|
* Simple Table Lookup For Now. Scan Table And Find First Empty
|
|
* Slot indicated by AVAILABLE state
|
|
*/
|
|
for (i = ESIF_INSTANCE_FIRST; i < MAX_PARTICIPANT_ENTRY; i++) {
|
|
if (ESIF_PM_PARTICIPANT_STATE_AVAILABLE ==
|
|
g_pm.pme[i].state) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If No Available Slots Return */
|
|
if (i >= MAX_PARTICIPANT_ENTRY)
|
|
goto exit;
|
|
|
|
lp_ptr = esif_pm_lp_alloc();
|
|
if (NULL == lp_ptr)
|
|
goto exit;
|
|
|
|
ESIF_TRACE_DYN_PM("%s: lp %p\n", ESIF_FUNC, lp_ptr);
|
|
|
|
/*
|
|
* Take Slot
|
|
*/
|
|
g_pm.pme[i].state = ESIF_PM_PARTICIPANT_STATE_CREATED;
|
|
g_pm.pme_count++;
|
|
|
|
|
|
/*
|
|
* Initialize Our New Lower Participant
|
|
*/
|
|
lp_ptr->instance = i; /* Our PME Instance */
|
|
lp_ptr->enable = ESIF_TRUE; /* Enable By Default */
|
|
lp_ptr->pi_ptr = pi_ptr; /* Keep The Original Interface Data */
|
|
|
|
/*
|
|
* We copy the name so it may be used later when a participant is
|
|
* removed to tell when it returns.
|
|
*/
|
|
esif_ccb_strcpy(lp_ptr->pi_name, pi_ptr->name, ESIF_NAME_LEN);
|
|
|
|
/* Assume One Domain */
|
|
lp_ptr->domain_count = 1;
|
|
|
|
ESIF_TRACE_DYN_PM("%s: Assigned Instance: %d of %d\n",
|
|
ESIF_FUNC, lp_ptr->instance, MAX_PARTICIPANT_ENTRY);
|
|
|
|
g_pm.pme[i].pi_ptr = pi_ptr;
|
|
g_pm.pme[i].lp_ptr = lp_ptr;
|
|
|
|
exit:
|
|
esif_ccb_write_unlock(&g_pm.lock);
|
|
return lp_ptr;
|
|
}
|
|
|
|
|
|
/* Disable Paticipant Instance */
|
|
void esif_lf_pm_lp_remove(
|
|
struct esif_lp *lp_ptr
|
|
)
|
|
{
|
|
if (NULL == lp_ptr)
|
|
return;
|
|
|
|
ESIF_TRACE_DYN_PM("%s: lp %p\n", ESIF_FUNC, lp_ptr);
|
|
|
|
esif_ccb_write_lock(&g_pm.lock);
|
|
|
|
g_pm.pme[lp_ptr->instance].state = ESIF_PM_PARTICIPANT_REMOVED;
|
|
g_pm.pme_count--;
|
|
|
|
lp_ptr->enable = ESIF_FALSE; /* Not used anywhere that I can see */
|
|
lp_ptr->pi_ptr = NULL; /* Keep The Original Interface Data */
|
|
g_pm.pme[lp_ptr->instance].pi_ptr = NULL;
|
|
/* Note we don't free PI since that is someone elses */
|
|
esif_ccb_write_unlock(&g_pm.lock);
|
|
}
|
|
|
|
|
|
/* Initialize Participant Manager */
|
|
enum esif_rc esif_lf_pm_init(void)
|
|
{
|
|
enum esif_rc rc = ESIF_OK;
|
|
struct esif_ccb_mempool *mempool_ptr = NULL;
|
|
|
|
ESIF_TRACE_DYN_INIT("%s: Initialize Participant Manager\n", ESIF_FUNC);
|
|
|
|
mempool_ptr =
|
|
esif_ccb_mempool_create(ESIF_MEMPOOL_TYPE_PM,
|
|
ESIF_MEMPOOL_FW_PM,
|
|
sizeof(struct esif_lp));
|
|
if (NULL == mempool_ptr) {
|
|
rc = ESIF_E_NO_MEMORY;
|
|
goto exit;
|
|
}
|
|
esif_ccb_lock_init(&g_pm.lock);
|
|
exit:
|
|
return rc;
|
|
}
|
|
|
|
|
|
/* Exit Participant Manager */
|
|
void esif_lf_pm_exit(void)
|
|
{
|
|
u8 i = 0;
|
|
|
|
esif_ccb_write_lock(&g_pm.lock);
|
|
for (i = 0; i < MAX_PARTICIPANT_ENTRY; i++) {
|
|
esif_pm_lp_free(g_pm.pme[i].lp_ptr);
|
|
g_pm.pme[i].lp_ptr = NULL;
|
|
g_pm.pme[i].pi_ptr = NULL;
|
|
g_pm.pme_count--;
|
|
g_pm.pme[i].state = ESIF_PM_PARTICIPANT_STATE_AVAILABLE;
|
|
}
|
|
esif_ccb_write_unlock(&g_pm.lock);
|
|
|
|
esif_ccb_lock_uninit(&g_pm_lock);
|
|
ESIF_TRACE_DYN_INIT("%s: Exit Participant Manager\n", ESIF_FUNC);
|
|
}
|
|
|
|
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|