mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-07-05 03:26:29 +00:00
dm: mei: add me clients enumeration
ME client enumeration is received from sysfs attributes of the native device. V3: Use bounded functions. Tracked-On: #1536 Signed-off-by: Vitaly Lubart <vitaly.lubart@intel.com> Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
parent
7cbb3872a2
commit
3abbf10e55
@ -203,6 +203,24 @@ static void vmei_dbg_print_hex(const char *title,
|
||||
fprintf(dbg_file, "\n");
|
||||
}
|
||||
|
||||
static void
|
||||
vmei_dbg_client_properties(const struct mei_client_properties *prop)
|
||||
{
|
||||
char guid_str[UUID_STR_LEN] = {0};
|
||||
|
||||
if (vmei_debug < 2)
|
||||
return;
|
||||
|
||||
guid_unparse(&prop->protocol_name, guid_str, UUID_STR_LEN);
|
||||
|
||||
DPRINTF("client properties:\n");
|
||||
DPRINTF("\t fixed_address: %d\n", prop->fixed_address);
|
||||
DPRINTF("\t protocol_version: %d\n", prop->protocol_version);
|
||||
DPRINTF("\t max_connections: %d\n", prop->max_connections);
|
||||
DPRINTF("\t single_recv_buf: %d\n", prop->single_recv_buf);
|
||||
DPRINTF("\t max_msg_length: %u\n", prop->max_msg_length);
|
||||
DPRINTF("\t protocol_name: %s\n", guid_str);
|
||||
}
|
||||
|
||||
#define MEI_FW_STATUS_MAX 6
|
||||
|
||||
@ -595,6 +613,53 @@ static void vmei_free_me_clients(struct virtio_mei *vmei)
|
||||
pthread_mutex_unlock(&vmei->list_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* vmei_get_free_me_id() - search for free me id in clients map
|
||||
*
|
||||
* @vmei: virtio mei device
|
||||
* @fixed: is a a fixed address client
|
||||
*
|
||||
* Return: free me id, 0 - if none found
|
||||
*/
|
||||
static uint8_t
|
||||
vmei_clients_map_find_free(struct virtio_mei *vmei, bool fixed)
|
||||
{
|
||||
unsigned int octet, bit;
|
||||
uint8_t *valid_addresses = vmei->me_clients_map.valid_addresses;
|
||||
|
||||
for (octet = fixed ? 0 : 4; octet < 32; octet++) {
|
||||
for (bit = 0; bit < 8; bit++) {
|
||||
/* ID 0 is reserved and should not be allocated*/
|
||||
if (!octet && !bit)
|
||||
continue;
|
||||
if (!(valid_addresses[octet] & BIT(bit)))
|
||||
return octet * 8 + bit;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* vmei_clients_map_update() - set or unset me id in the valid address map
|
||||
*
|
||||
* @vmei: virtio mei device
|
||||
* @me_id: me client id
|
||||
* @set: set or unset the client id
|
||||
*/
|
||||
static void
|
||||
vmei_clients_map_update(struct virtio_mei *vmei, uint8_t me_id, bool set)
|
||||
{
|
||||
unsigned int octet, bit;
|
||||
uint8_t *valid_addresses = vmei->me_clients_map.valid_addresses;
|
||||
|
||||
octet = me_id / 8;
|
||||
bit = me_id % 8;
|
||||
|
||||
if (set)
|
||||
valid_addresses[octet] |= BIT(bit);
|
||||
else
|
||||
valid_addresses[octet] &= ~BIT(bit);
|
||||
}
|
||||
|
||||
static int mei_sysfs_read_property_file(const char *fname, char *buf, size_t sz)
|
||||
{
|
||||
@ -665,6 +730,129 @@ static int mei_sysfs_read_property_uuid(char *fname, guid_t *uuid)
|
||||
return guid_parse(buf, sizeof(buf), uuid);
|
||||
}
|
||||
|
||||
static int mei_sysfs_read_properties(char *devpath, size_t size, size_t offset,
|
||||
struct mei_client_properties *props)
|
||||
{
|
||||
uint32_t max_msg_length;
|
||||
|
||||
snprintf(&devpath[offset], size - offset, "%s", "uuid");
|
||||
if (mei_sysfs_read_property_uuid(devpath, &props->protocol_name) < 0)
|
||||
return -EFAULT;
|
||||
|
||||
snprintf(&devpath[offset], size - offset, "%s", "version");
|
||||
if (mei_sysfs_read_property_u8(devpath, &props->protocol_version) < 0)
|
||||
return -EFAULT;
|
||||
|
||||
snprintf(&devpath[offset], size - offset, "%s", "fixed");
|
||||
if (mei_sysfs_read_property_u8(devpath, &props->fixed_address) < 0)
|
||||
props->fixed_address = 0;
|
||||
|
||||
/* Use local variable as function is unaware of the unaligned pointer */
|
||||
snprintf(&devpath[offset], size - offset, "%s", "max_len");
|
||||
if (mei_sysfs_read_property_u32(devpath, &max_msg_length) < 0)
|
||||
max_msg_length = 512;
|
||||
props->max_msg_length = max_msg_length;
|
||||
|
||||
snprintf(&devpath[offset], size - offset, "%s", "max_conn");
|
||||
if (mei_sysfs_read_property_u8(devpath, &props->max_connections) < 0)
|
||||
props->max_connections = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static bool is_prefix(const char *prfx, const char *str, size_t maxlen)
|
||||
{
|
||||
if (!prfx || !str || prfx[0] == '\0')
|
||||
return false;
|
||||
|
||||
return strncmp(prfx, str, maxlen);
|
||||
}
|
||||
|
||||
static int vmei_me_client_scan_list(struct virtio_mei *vmei)
|
||||
{
|
||||
DIR *dev_dir = NULL;
|
||||
struct dirent *ent;
|
||||
char devpath[256];
|
||||
int d_offset, c_offset;
|
||||
uint8_t me_id = 1;
|
||||
struct vmei_me_client *mclient;
|
||||
uint8_t vtag, vtag_supported = 0;
|
||||
|
||||
d_offset = snprintf(devpath, sizeof(devpath) - 1, "%s/%s/%s",
|
||||
MEI_SYSFS_ROOT, vmei->name, "device/");
|
||||
if (d_offset < 0)
|
||||
return -1;
|
||||
|
||||
dev_dir = opendir(devpath);
|
||||
if (!dev_dir) {
|
||||
WPRINTF("opendir failed %d", errno);
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* iterate over device directory and find the directories
|
||||
* starting with "mei::" - those are the clients.
|
||||
*/
|
||||
while ((ent = readdir(dev_dir)) != NULL) {
|
||||
|
||||
if (ent->d_type == DT_DIR &&
|
||||
is_prefix("mei::", ent->d_name, DEV_NAME_SIZE)) {
|
||||
|
||||
struct mei_client_properties props;
|
||||
|
||||
memset(&props, 0, sizeof(props));
|
||||
|
||||
DPRINTF("found client %s %s\n", ent->d_name, devpath);
|
||||
|
||||
c_offset = snprintf(&devpath[d_offset],
|
||||
sizeof(devpath) - d_offset,
|
||||
"%s/", ent->d_name);
|
||||
if (c_offset < 0)
|
||||
continue;
|
||||
c_offset += d_offset;
|
||||
|
||||
vtag = 0;
|
||||
snprintf(&devpath[c_offset],
|
||||
sizeof(devpath) - c_offset, "%s", "vtag");
|
||||
if (mei_sysfs_read_property_u8(devpath, &vtag) < 0)
|
||||
vtag = 0;
|
||||
|
||||
if (!vtag)
|
||||
continue;
|
||||
|
||||
if (mei_sysfs_read_properties(devpath,
|
||||
sizeof(devpath), c_offset,
|
||||
&props) < 0)
|
||||
continue;
|
||||
|
||||
me_id = vmei_clients_map_find_free(vmei,
|
||||
props.fixed_address);
|
||||
|
||||
mclient = vmei_me_client_create(vmei, me_id, &props);
|
||||
if (!mclient)
|
||||
continue;
|
||||
|
||||
vmei_clients_map_update(vmei, me_id, true);
|
||||
vmei_add_me_client(mclient);
|
||||
|
||||
vtag_supported = 1;
|
||||
}
|
||||
}
|
||||
|
||||
vmei_dbg_print_hex("me_clients_map",
|
||||
vmei->me_clients_map.valid_addresses,
|
||||
sizeof(vmei->me_clients_map.valid_addresses));
|
||||
|
||||
closedir(dev_dir);
|
||||
|
||||
/*
|
||||
* Don't return error in order not to the crash DM;
|
||||
* currently it cannot deal with single driver error.
|
||||
*/
|
||||
if (!vtag_supported)
|
||||
WPRINTF("The platform doesn't support vtags!!!\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
vmei_read_fw_status(struct virtio_mei *vmei, uint32_t *fw_status)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user