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: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
be9d87a790
commit
c1174c0edf
4 changed files with 97 additions and 88 deletions
|
@ -423,54 +423,87 @@ void mei_allocate_me_clients_storage(struct mei_device *dev)
|
||||||
dev->me_clients = clients;
|
dev->me_clients = clients;
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* host_client_properties - reads properties for client
|
void mei_host_client_init(struct work_struct *work)
|
||||||
*
|
{
|
||||||
* @dev: the device structure
|
struct mei_device *dev = container_of(work,
|
||||||
*
|
struct mei_device, init_work);
|
||||||
* returns:
|
struct mei_client_properties *client_props;
|
||||||
* < 0 - Error.
|
int i;
|
||||||
* = 0 - no more clients.
|
|
||||||
* = 1 - still have clients to send properties request.
|
mutex_lock(&dev->device_lock);
|
||||||
*/
|
|
||||||
int mei_host_client_properties(struct mei_device *dev)
|
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
|
||||||
|
*/
|
||||||
|
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 mei_msg_hdr *mei_hdr;
|
||||||
struct hbm_props_request *prop_req;
|
struct hbm_props_request *prop_req;
|
||||||
const size_t len = sizeof(struct hbm_props_request);
|
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;
|
|
||||||
|
|
||||||
|
client_num = dev->me_client_presentation_num;
|
||||||
|
|
||||||
|
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);
|
||||||
prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
|
prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
|
||||||
|
|
||||||
b = dev->me_client_index;
|
memset(prop_req, 0, sizeof(struct hbm_props_request));
|
||||||
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;
|
|
||||||
dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
|
|
||||||
mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
|
|
||||||
|
|
||||||
|
|
||||||
memset(prop_req, 0, sizeof(struct hbm_props_request));
|
prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
|
||||||
|
prop_req->address = next_client_index;
|
||||||
|
|
||||||
prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
|
if (mei_write_message(dev, mei_hdr, (unsigned char *) prop_req,
|
||||||
prop_req->address = b;
|
mei_hdr->length)) {
|
||||||
|
dev->dev_state = MEI_DEV_RESETING;
|
||||||
|
dev_err(&dev->pdev->dev, "Properties request command failed\n");
|
||||||
|
mei_reset(dev, 1);
|
||||||
|
|
||||||
if (mei_write_message(dev, mei_hdr,
|
return -EIO;
|
||||||
(unsigned char *)prop_req, len)) {
|
|
||||||
dev->dev_state = MEI_DEV_RESETING;
|
|
||||||
dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
|
|
||||||
mei_reset(dev, 1);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
|
|
||||||
dev->me_client_index = b;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
|
||||||
|
dev->me_client_index = next_client_index;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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");
|
dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
|
||||||
mei_watchdog_register(dev);
|
mei_watchdog_register(dev);
|
||||||
|
|
||||||
/* next step in the state maching */
|
|
||||||
mei_amthif_host_init(dev);
|
|
||||||
return;
|
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_msg_hdr *mei_hdr)
|
||||||
{
|
{
|
||||||
struct mei_bus_message *mei_msg;
|
struct mei_bus_message *mei_msg;
|
||||||
|
struct mei_me_client *me_client;
|
||||||
struct hbm_host_version_response *version_res;
|
struct hbm_host_version_response *version_res;
|
||||||
struct hbm_client_connect_response *connect_res;
|
struct hbm_client_connect_response *connect_res;
|
||||||
struct hbm_client_connect_response *disconnect_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_props_response *props_res;
|
||||||
struct hbm_host_enum_response *enum_res;
|
struct hbm_host_enum_response *enum_res;
|
||||||
struct hbm_host_stop_request *stop_req;
|
struct hbm_host_stop_request *stop_req;
|
||||||
int res;
|
|
||||||
|
|
||||||
|
|
||||||
/* read the message to our buffer */
|
/* read the message to our buffer */
|
||||||
BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf));
|
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:
|
case HOST_CLIENT_PROPERTIES_RES_CMD:
|
||||||
props_res = (struct hbm_props_response *)mei_msg;
|
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) {
|
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");
|
dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n");
|
||||||
mei_reset(dev, 1);
|
mei_reset(dev, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (dev->me_clients[dev->me_client_presentation_num]
|
|
||||||
.client_id == props_res->address) {
|
|
||||||
|
|
||||||
dev->me_clients[dev->me_client_presentation_num].props
|
if (me_client->client_id != props_res->address) {
|
||||||
= props_res->client_properties;
|
dev_err(&dev->pdev->dev,
|
||||||
|
"Host client properties reply mismatch\n");
|
||||||
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++;
|
|
||||||
|
|
||||||
/** 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");
|
|
||||||
mei_reset(dev, 1);
|
mei_reset(dev, 1);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
break;
|
||||||
|
|
||||||
case HOST_ENUM_RES_CMD:
|
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);
|
mei_allocate_me_clients_storage(dev);
|
||||||
dev->init_clients_state =
|
dev->init_clients_state =
|
||||||
MEI_CLIENT_PROPERTIES_MESSAGE;
|
MEI_CLIENT_PROPERTIES_MESSAGE;
|
||||||
mei_host_client_properties(dev);
|
|
||||||
|
mei_host_client_enumerate(dev);
|
||||||
} else {
|
} else {
|
||||||
dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
|
dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
|
||||||
mei_reset(dev, 1);
|
mei_reset(dev, 1);
|
||||||
|
|
|
@ -829,6 +829,8 @@ static int __devinit mei_probe(struct pci_dev *pdev,
|
||||||
goto disable_msi;
|
goto disable_msi;
|
||||||
}
|
}
|
||||||
INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
|
INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
|
||||||
|
INIT_WORK(&dev->init_work, mei_host_client_init);
|
||||||
|
|
||||||
if (mei_hw_init(dev)) {
|
if (mei_hw_init(dev)) {
|
||||||
dev_err(&pdev->dev, "init hw failure.\n");
|
dev_err(&pdev->dev, "init hw failure.\n");
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
|
|
|
@ -287,6 +287,8 @@ struct mei_device {
|
||||||
bool iamthif_flow_control_pending;
|
bool iamthif_flow_control_pending;
|
||||||
bool iamthif_ioctl;
|
bool iamthif_ioctl;
|
||||||
bool iamthif_canceled;
|
bool iamthif_canceled;
|
||||||
|
|
||||||
|
struct work_struct init_work;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
|
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_start_message(struct mei_device *dev);
|
||||||
void mei_host_enum_clients_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
|
* MEI interrupt functions prototype
|
||||||
|
|
Loading…
Add table
Reference in a new issue