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

Commit c1174c0e authored by Samuel Ortiz's avatar Samuel Ortiz Committed by Greg Kroah-Hartman
Browse files

mei: Simplify the ME client enumeration code



After enumerating all ME clients we call the client init functions for
all matching UUIDs from a separate context.
This remove the hackish cascading client initialisation process that was
interleaving properties and connection command replies.

Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent be9d87a7
Loading
Loading
Loading
Loading
+66 −33
Original line number Diff line number Diff line
@@ -423,53 +423,86 @@ void mei_allocate_me_clients_storage(struct mei_device *dev)
	dev->me_clients = clients;
	return ;
}
/**
 * host_client_properties - reads properties for client
 *
 * @dev: the device structure
 *
 * returns:
 * 	< 0 - Error.
 *  = 0 - no more clients.
 *  = 1 - still have clients to send properties request.

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;

	mutex_lock(&dev->device_lock);

	bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
	dev->open_handle_count = 0;

	/*
	 * Reserving the first three client IDs
	 * 0: Reserved for MEI Bus Message communications
	 * 1: Reserved for Watchdog
	 * 2: Reserved for AMTHI
	 */
int mei_host_client_properties(struct mei_device *dev)
	bitmap_set(dev->host_clients_map, 0, 3);

	for (i = 0; i < dev->me_clients_num; i++) {
		client_props = &dev->me_clients[i].props;

		if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid))
			mei_amthif_host_init(dev);
		else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid))
			mei_wd_host_init(dev);
	}

	dev->dev_state = MEI_DEV_ENABLED;

	mutex_unlock(&dev->device_lock);
}

int mei_host_client_enumerate(struct mei_device *dev)
{

	struct mei_msg_hdr *mei_hdr;
	struct hbm_props_request *prop_req;
	const size_t len = sizeof(struct hbm_props_request);
	unsigned long next_client_index;
	u8 client_num;

	int b;
	u8 client_num = dev->me_client_presentation_num;

	prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
	client_num = dev->me_client_presentation_num;

	b = dev->me_client_index;
	b = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, b);
	if (b < MEI_CLIENTS_MAX) {
		dev->me_clients[client_num].client_id = b;
	next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX,
					  dev->me_client_index);

	/* We got all client properties */
	if (next_client_index == MEI_CLIENTS_MAX) {
		schedule_work(&dev->init_work);

		return 0;
	}

	dev->me_clients[client_num].client_id = next_client_index;
	dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
		mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);

	mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
	prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];

	memset(prop_req, 0, sizeof(struct hbm_props_request));


	prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
		prop_req->address = b;
	prop_req->address = next_client_index;

		if (mei_write_message(dev, mei_hdr,
				(unsigned char *)prop_req, len)) {
	if (mei_write_message(dev, mei_hdr, (unsigned char *) prop_req,
			      mei_hdr->length)) {
		dev->dev_state = MEI_DEV_RESETING;
			dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
		dev_err(&dev->pdev->dev, "Properties request command failed\n");
		mei_reset(dev, 1);

		return -EIO;
	}

	dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
		dev->me_client_index = b;
		return 1;
	}
	dev->me_client_index = next_client_index;

	return 0;
}
+23 −52
Original line number Diff line number Diff line
@@ -252,8 +252,6 @@ static void mei_client_connect_response(struct mei_device *dev,
		dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
		mei_watchdog_register(dev);

		/* next step in the state maching */
		mei_amthif_host_init(dev);
		return;
	}

@@ -470,6 +468,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
		struct mei_msg_hdr *mei_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;
@@ -478,8 +477,6 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
	struct hbm_props_response *props_res;
	struct hbm_host_enum_response *enum_res;
	struct hbm_host_stop_request *stop_req;
	int res;


	/* read the message to our buffer */
	BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf));
@@ -547,64 +544,37 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,

	case HOST_CLIENT_PROPERTIES_RES_CMD:
		props_res = (struct hbm_props_response *)mei_msg;
		me_client = &dev->me_clients[dev->me_client_presentation_num];

		if (props_res->status || !dev->me_clients) {
			dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n");
			mei_reset(dev, 1);
			return;
		}
		if (dev->me_clients[dev->me_client_presentation_num]
					.client_id == props_res->address) {

			dev->me_clients[dev->me_client_presentation_num].props
						= props_res->client_properties;

			if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
			    dev->init_clients_state ==
					MEI_CLIENT_PROPERTIES_MESSAGE) {
				dev->me_client_index++;
				dev->me_client_presentation_num++;
		if (me_client->client_id != props_res->address) {
			dev_err(&dev->pdev->dev,
				"Host client properties reply mismatch\n");
			mei_reset(dev, 1);

				/** Send Client Properties request **/
				res = mei_host_client_properties(dev);
				if (res < 0) {
					dev_dbg(&dev->pdev->dev, "mei_host_client_properties() failed");
			return;
				} else if (!res) {
					/*
					 * No more clients to send to.
					 * Clear Map for indicating now ME clients
					 * with associated host client
					 */
					bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
					dev->open_handle_count = 0;

					/*
					 * Reserving the first three client IDs
					 * Client Id 0 - Reserved for MEI Bus Message communications
					 * Client Id 1 - Reserved for Watchdog
					 * Client ID 2 - Reserved for AMTHI
					 */
					bitmap_set(dev->host_clients_map, 0, 3);
					dev->dev_state = MEI_DEV_ENABLED;

					/* if wd initialization fails, initialization the AMTHI client,
					 * otherwise the AMTHI client will be initialized after the WD client connect response
					 * will be received
					 */
					if (mei_wd_host_init(dev))
						mei_amthif_host_init(dev);
		}

			} else {
				dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message");
				mei_reset(dev, 1);
				return;
			}
		} else {
			dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message for wrong client ID\n");
		if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
		    dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) {
			dev_err(&dev->pdev->dev,
				"Unexpected client properties reply\n");
			mei_reset(dev, 1);

			return;
		}

		me_client->props = props_res->client_properties;
		dev->me_client_index++;
		dev->me_client_presentation_num++;

		mei_host_client_enumerate(dev);

		break;

	case HOST_ENUM_RES_CMD:
@@ -618,7 +588,8 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev,
				mei_allocate_me_clients_storage(dev);
				dev->init_clients_state =
					MEI_CLIENT_PROPERTIES_MESSAGE;
				mei_host_client_properties(dev);

				mei_host_client_enumerate(dev);
		} else {
			dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
			mei_reset(dev, 1);
+2 −0
Original line number Diff line number Diff line
@@ -829,6 +829,8 @@ static int __devinit mei_probe(struct pci_dev *pdev,
		goto disable_msi;
	}
	INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
	INIT_WORK(&dev->init_work, mei_host_client_init);

	if (mei_hw_init(dev)) {
		dev_err(&pdev->dev, "init hw failure.\n");
		err = -ENODEV;
+4 −1
Original line number Diff line number Diff line
@@ -287,6 +287,8 @@ struct mei_device {
	bool iamthif_flow_control_pending;
	bool iamthif_ioctl;
	bool iamthif_canceled;

	struct work_struct init_work;
};

static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
@@ -363,7 +365,8 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
 */
void mei_host_start_message(struct mei_device *dev);
void mei_host_enum_clients_message(struct mei_device *dev);
int mei_host_client_properties(struct mei_device *dev);
int mei_host_client_enumerate(struct mei_device *dev);
void mei_host_client_init(struct work_struct *work);

/*
 *  MEI interrupt functions prototype