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: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
		
							parent
							
								
									d320832f64
								
							
						
					
					
						commit
						5ca2d3882d
					
				| @ -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,11 +431,10 @@ 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", | ||||
| 				    cl->mei_flow_ctrl_creds); | ||||
| 				break; | ||||
| 			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,26 +751,6 @@ 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"); | ||||
| 			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", | ||||
| 				props_res->status); | ||||
| 			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; | ||||
| 		} | ||||
| 
 | ||||
| 		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", | ||||
| @ -790,7 +758,16 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) | ||||
| 			return -EPROTO; | ||||
| 		} | ||||
| 
 | ||||
| 		me_client->props = props_res->client_properties; | ||||
| 		props_res = (struct hbm_props_response *)mei_msg; | ||||
| 
 | ||||
| 		if (props_res->status) { | ||||
| 			dev_err(&dev->pdev->dev, "hbm: properties response: wrong status = %d\n", | ||||
| 				props_res->status); | ||||
| 			return -EPROTO; | ||||
| 		} | ||||
| 
 | ||||
| 		mei_hbm_me_cl_add(dev, props_res); | ||||
| 
 | ||||
| 		dev->me_client_index++; | ||||
| 		dev->me_client_presentation_num++; | ||||
| 
 | ||||
| @ -809,7 +786,7 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) | ||||
| 		BUILD_BUG_ON(sizeof(dev->me_clients_map) | ||||
| 				< sizeof(enum_res->valid_addresses)); | ||||
| 		memcpy(dev->me_clients_map, enum_res->valid_addresses, | ||||
| 			sizeof(enum_res->valid_addresses)); | ||||
| 				sizeof(enum_res->valid_addresses)); | ||||
| 
 | ||||
| 		if (dev->dev_state != MEI_DEV_INIT_CLIENTS || | ||||
| 		    dev->hbm_state != MEI_HBM_ENUM_CLIENTS) { | ||||
| @ -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; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user