Commit 5ca2d388 authored by Tomas Winkler's avatar Tomas Winkler Committed by Greg Kroah-Hartman

mei: use list for me clients book keeping

To support dynamic addition/remove of clients
it is more convenient to use list instead of
static array
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d320832f
......@@ -38,12 +38,11 @@
struct mei_me_client *mei_me_cl_by_uuid(const struct mei_device *dev,
const uuid_le *uuid)
{
int i;
struct mei_me_client *me_cl;
for (i = 0; i < dev->me_clients_num; ++i)
if (uuid_le_cmp(*uuid,
dev->me_clients[i].props.protocol_name) == 0)
return &dev->me_clients[i];
list_for_each_entry(me_cl, &dev->me_clients, list)
if (uuid_le_cmp(*uuid, me_cl->props.protocol_name) == 0)
return me_cl;
return NULL;
}
......@@ -62,12 +61,12 @@ struct mei_me_client *mei_me_cl_by_uuid(const struct mei_device *dev,
struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
{
int i;
for (i = 0; i < dev->me_clients_num; i++)
if (dev->me_clients[i].client_id == client_id)
return &dev->me_clients[i];
struct mei_me_client *me_cl;
list_for_each_entry(me_cl, &dev->me_clients, list)
if (me_cl->client_id == client_id)
return me_cl;
return NULL;
}
......@@ -396,19 +395,19 @@ void mei_host_client_init(struct work_struct *work)
{
struct mei_device *dev = container_of(work,
struct mei_device, init_work);
struct mei_client_properties *client_props;
int i;
struct mei_me_client *me_cl;
struct mei_client_properties *props;
mutex_lock(&dev->device_lock);
for (i = 0; i < dev->me_clients_num; i++) {
client_props = &dev->me_clients[i].props;
list_for_each_entry(me_cl, &dev->me_clients, list) {
props = &me_cl->props;
if (!uuid_le_cmp(client_props->protocol_name, mei_amthif_guid))
if (!uuid_le_cmp(props->protocol_name, mei_amthif_guid))
mei_amthif_host_init(dev);
else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid))
else if (!uuid_le_cmp(props->protocol_name, mei_wd_guid))
mei_wd_host_init(dev);
else if (!uuid_le_cmp(client_props->protocol_name, mei_nfc_guid))
else if (!uuid_le_cmp(props->protocol_name, mei_nfc_guid))
mei_nfc_host_init(dev);
}
......@@ -653,9 +652,6 @@ int mei_cl_flow_ctrl_creds(struct mei_cl *cl)
dev = cl->dev;
if (!dev->me_clients_num)
return 0;
if (cl->mei_flow_ctrl_creds > 0)
return 1;
......
......@@ -28,10 +28,10 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
size_t cnt, loff_t *ppos)
{
struct mei_device *dev = fp->private_data;
struct mei_me_client *cl;
struct mei_me_client *me_cl;
const size_t bufsz = 1024;
char *buf = kzalloc(bufsz, GFP_KERNEL);
int i;
int i = 0;
int pos = 0;
int ret;
......@@ -47,20 +47,19 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
if (dev->dev_state != MEI_DEV_ENABLED)
goto out;
for (i = 0; i < dev->me_clients_num; i++) {
cl = &dev->me_clients[i];
list_for_each_entry(me_cl, &dev->me_clients, list) {
/* skip me clients that cannot be connected */
if (cl->props.max_number_of_connections == 0)
if (me_cl->props.max_number_of_connections == 0)
continue;
pos += scnprintf(buf + pos, bufsz - pos,
"%2d|%2d|%4d|%pUl|%3d|%7d|\n",
i, cl->client_id,
cl->props.fixed_address,
&cl->props.protocol_name,
cl->props.max_number_of_connections,
cl->props.max_msg_length);
i++, me_cl->client_id,
me_cl->props.fixed_address,
&me_cl->props.protocol_name,
me_cl->props.max_number_of_connections,
me_cl->props.max_msg_length);
}
out:
mutex_unlock(&dev->device_lock);
......
......@@ -77,50 +77,19 @@ void mei_hbm_idle(struct mei_device *dev)
*/
void mei_hbm_reset(struct mei_device *dev)
{
dev->me_clients_num = 0;
struct mei_me_client *me_cl, *next;
dev->me_client_presentation_num = 0;
dev->me_client_index = 0;
kfree(dev->me_clients);
dev->me_clients = NULL;
list_for_each_entry_safe(me_cl, next, &dev->me_clients, list) {
list_del(&me_cl->list);
kfree(me_cl);
}
mei_hbm_idle(dev);
}
/**
* mei_hbm_me_cl_allocate - allocates storage for me clients
*
* @dev: the device structure
*
* returns 0 on success -ENOMEM on allocation failure
*/
static int mei_hbm_me_cl_allocate(struct mei_device *dev)
{
struct mei_me_client *clients;
int b;
mei_hbm_reset(dev);
/* count how many ME clients we have */
for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX)
dev->me_clients_num++;
if (dev->me_clients_num == 0)
return 0;
dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%ld.\n",
dev->me_clients_num * sizeof(struct mei_me_client));
/* allocate storage for ME clients representation */
clients = kcalloc(dev->me_clients_num,
sizeof(struct mei_me_client), GFP_KERNEL);
if (!clients) {
dev_err(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
return -ENOMEM;
}
dev->me_clients = clients;
return 0;
}
/**
* mei_hbm_cl_hdr - construct client hbm header
*
......@@ -213,6 +182,8 @@ int mei_hbm_start_req(struct mei_device *dev)
const size_t len = sizeof(struct hbm_host_version_request);
int ret;
mei_hbm_reset(dev);
mei_hbm_hdr(mei_hdr, len);
/* host start message */
......@@ -267,6 +238,32 @@ static int mei_hbm_enum_clients_req(struct mei_device *dev)
return 0;
}
/*
* mei_hbm_me_cl_add - add new me client to the list
*
* @dev: the device structure
* @res: hbm property response
*
* returns 0 on success and -ENOMEM on allocation failure
*/
static int mei_hbm_me_cl_add(struct mei_device *dev,
struct hbm_props_response *res)
{
struct mei_me_client *me_cl;
me_cl = kzalloc(sizeof(struct mei_me_client), GFP_KERNEL);
if (!me_cl)
return -ENOMEM;
me_cl->props = res->client_properties;
me_cl->client_id = res->me_addr;
me_cl->mei_flow_ctrl_creds = 0;
list_add(&me_cl->list, &dev->me_clients);
return 0;
}
/**
* mei_hbm_prop_req - request property for a single client
*
......@@ -282,11 +279,8 @@ static int mei_hbm_prop_req(struct mei_device *dev)
struct hbm_props_request *prop_req;
const size_t len = sizeof(struct hbm_props_request);
unsigned long next_client_index;
unsigned long client_num;
int ret;
client_num = dev->me_client_presentation_num;
next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX,
dev->me_client_index);
......@@ -298,15 +292,11 @@ static int mei_hbm_prop_req(struct mei_device *dev)
return 0;
}
dev->me_clients[client_num].client_id = next_client_index;
dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
mei_hbm_hdr(mei_hdr, len);
prop_req = (struct hbm_props_request *)dev->wr_msg.data;
memset(prop_req, 0, sizeof(struct hbm_props_request));
prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
prop_req->me_addr = next_client_index;
......@@ -441,9 +431,8 @@ static void mei_hbm_cl_flow_control_res(struct mei_device *dev,
list_for_each_entry(cl, &dev->file_list, link) {
if (mei_hbm_cl_addr_equal(cl, flow_control)) {
cl->mei_flow_ctrl_creds++;
dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n",
flow_control->host_addr, flow_control->me_addr);
dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n",
dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d creds %d.\n",
flow_control->host_addr, flow_control->me_addr,
cl->mei_flow_ctrl_creds);
break;
}
......@@ -641,7 +630,6 @@ bool mei_hbm_version_is_supported(struct mei_device *dev)
int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
{
struct mei_bus_message *mei_msg;
struct mei_me_client *me_client;
struct hbm_host_version_response *version_res;
struct hbm_client_connect_response *connect_res;
struct hbm_client_connect_response *disconnect_res;
......@@ -763,13 +751,14 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
dev->init_clients_timer = 0;
if (dev->me_clients == NULL) {
dev_err(&dev->pdev->dev, "hbm: properties response: mei_clients not allocated\n");
if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
dev_err(&dev->pdev->dev, "hbm: properties response: state mismatch, [%d, %d]\n",
dev->dev_state, dev->hbm_state);
return -EPROTO;
}
props_res = (struct hbm_props_response *)mei_msg;
me_client = &dev->me_clients[dev->me_client_presentation_num];
if (props_res->status) {
dev_err(&dev->pdev->dev, "hbm: properties response: wrong status = %d\n",
......@@ -777,20 +766,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
return -EPROTO;
}
if (me_client->client_id != props_res->me_addr) {
dev_err(&dev->pdev->dev, "hbm: properties response: address mismatch %d ?= %d\n",
me_client->client_id, props_res->me_addr);
return -EPROTO;
}
mei_hbm_me_cl_add(dev, props_res);
if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
dev_err(&dev->pdev->dev, "hbm: properties response: state mismatch, [%d, %d]\n",
dev->dev_state, dev->hbm_state);
return -EPROTO;
}
me_client->props = props_res->client_properties;
dev->me_client_index++;
dev->me_client_presentation_num++;
......@@ -818,11 +795,6 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
return -EPROTO;
}
if (mei_hbm_me_cl_allocate(dev)) {
dev_err(&dev->pdev->dev, "hbm: enumeration response: cannot allocate clients array\n");
return -ENOMEM;
}
dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
/* first property request */
......
......@@ -356,6 +356,7 @@ void mei_device_init(struct mei_device *dev, const struct mei_cfg *cfg)
/* setup our list array */
INIT_LIST_HEAD(&dev->file_list);
INIT_LIST_HEAD(&dev->device_list);
INIT_LIST_HEAD(&dev->me_clients);
mutex_init(&dev->device_lock);
init_waitqueue_head(&dev->wait_hw_ready);
init_waitqueue_head(&dev->wait_pg);
......
......@@ -175,6 +175,7 @@ struct mei_fw_status {
* @mei_flow_ctrl_creds - flow control credits
*/
struct mei_me_client {
struct list_head list;
struct mei_client_properties props;
u8 client_id;
u8 mei_flow_ctrl_creds;
......@@ -478,10 +479,9 @@ struct mei_device {
struct hbm_version version;
struct mei_me_client *me_clients; /* Note: memory has to be allocated */
struct list_head me_clients;
DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
unsigned long me_clients_num;
unsigned long me_client_presentation_num;
unsigned long me_client_index;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment