Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+15 −19
Original line number Diff line number Diff line
@@ -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;

+9 −10
Original line number Diff line number Diff line
@@ -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);
+44 −72
Original line number Diff line number Diff line
@@ -77,48 +77,17 @@ 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;

	mei_hbm_idle(dev);
	list_for_each_entry_safe(me_cl, next, &dev->me_clients, list) {
		list_del(&me_cl->list);
		kfree(me_cl);
	}

/**
 * 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_idle(dev);
}

/**
@@ -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 */
+1 −0
Original line number Diff line number Diff line
@@ -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);
+2 −2
Original line number Diff line number Diff line
@@ -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;