Skip to content

Commit

Permalink
mei: Simplify the ME client enumeration code
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Samuel Ortiz authored and Greg Kroah-Hartman committed Nov 21, 2012
1 parent be9d87a commit c1174c0
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 86 deletions.
99 changes: 66 additions & 33 deletions drivers/misc/mei/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,54 +423,87 @@ 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.
*/
int mei_host_client_properties(struct mei_device *dev)

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
*/
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;
dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len);
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);

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

prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
prop_req->address = b;
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];

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

if (mei_write_message(dev, mei_hdr,
(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;
prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
prop_req->address = next_client_index;

if (mei_write_message(dev, mei_hdr, (unsigned char *) prop_req,
mei_hdr->length)) {
dev->dev_state = MEI_DEV_RESETING;
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 = next_client_index;

return 0;
}

Expand Down
75 changes: 23 additions & 52 deletions drivers/misc/mei/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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));
Expand Down Expand Up @@ -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 (me_client->client_id != props_res->address) {
dev_err(&dev->pdev->dev,
"Host client properties reply mismatch\n");
mei_reset(dev, 1);

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);
}
return;
}

} 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:
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions drivers/misc/mei/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion drivers/misc/mei/mei_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit c1174c0

Please sign in to comment.