mei: normalize me host client linking routines
In order we can use the same code pattern for in-kernel and user space host clients we replace mei_cl_link_to_me with mei_cl_link function. We then have to keep me client lookupout of the new link function. The unlinking cannot be yet symetric due to amthif connection handling Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
1a1aca42c9
commit
781d0d8922
|
@ -65,22 +65,22 @@ void mei_amthif_reset_params(struct mei_device *dev)
|
||||||
* @dev: the device structure
|
* @dev: the device structure
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void mei_amthif_host_init(struct mei_device *dev)
|
int mei_amthif_host_init(struct mei_device *dev)
|
||||||
{
|
{
|
||||||
int i;
|
struct mei_cl *cl = &dev->iamthif_cl;
|
||||||
unsigned char *msg_buf;
|
unsigned char *msg_buf;
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
mei_cl_init(&dev->iamthif_cl, dev);
|
mei_cl_init(cl, dev);
|
||||||
dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
|
|
||||||
|
|
||||||
/* find ME amthif client */
|
i = mei_me_cl_by_uuid(dev, &mei_amthif_guid);
|
||||||
i = mei_cl_link_me(&dev->iamthif_cl,
|
|
||||||
&mei_amthif_guid, MEI_IAMTHIF_HOST_CLIENT_ID);
|
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
dev_info(&dev->pdev->dev, "failed to find iamthif client.\n");
|
dev_info(&dev->pdev->dev, "amthif: failed to find the client\n");
|
||||||
return;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cl->me_client_id = dev->me_clients[i].client_id;
|
||||||
|
|
||||||
/* Assign iamthif_mtu to the value received from ME */
|
/* Assign iamthif_mtu to the value received from ME */
|
||||||
|
|
||||||
dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
|
dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
|
||||||
|
@ -94,19 +94,29 @@ void mei_amthif_host_init(struct mei_device *dev)
|
||||||
msg_buf = kcalloc(dev->iamthif_mtu,
|
msg_buf = kcalloc(dev->iamthif_mtu,
|
||||||
sizeof(unsigned char), GFP_KERNEL);
|
sizeof(unsigned char), GFP_KERNEL);
|
||||||
if (!msg_buf) {
|
if (!msg_buf) {
|
||||||
dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n");
|
dev_err(&dev->pdev->dev, "amthif: memory allocation for ME message buffer failed.\n");
|
||||||
return;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->iamthif_msg_buf = msg_buf;
|
dev->iamthif_msg_buf = msg_buf;
|
||||||
|
|
||||||
if (mei_hbm_cl_connect_req(dev, &dev->iamthif_cl)) {
|
ret = mei_cl_link(cl, MEI_IAMTHIF_HOST_CLIENT_ID);
|
||||||
dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n");
|
|
||||||
dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
|
if (ret < 0) {
|
||||||
dev->iamthif_cl.host_client_id = 0;
|
dev_err(&dev->pdev->dev, "amthif: failed link client\n");
|
||||||
} else {
|
return -ENOENT;
|
||||||
dev->iamthif_cl.timer_count = MEI_CONNECT_TIMEOUT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cl->state = MEI_FILE_CONNECTING;
|
||||||
|
|
||||||
|
if (mei_hbm_cl_connect_req(dev, cl)) {
|
||||||
|
dev_dbg(&dev->pdev->dev, "amthif: Failed to connect to ME client\n");
|
||||||
|
cl->state = MEI_FILE_DISCONNECTED;
|
||||||
|
cl->host_client_id = 0;
|
||||||
|
} else {
|
||||||
|
cl->timer_count = MEI_CONNECT_TIMEOUT;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -258,54 +258,61 @@ struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** mei_cl_link: allocte host id in the host map
|
||||||
/**
|
|
||||||
* mei_me_cl_link - create link between host and me clinet and add
|
|
||||||
* me_cl to the list
|
|
||||||
*
|
*
|
||||||
* @cl: link between me and host client assocated with opened file descriptor
|
* @cl - host client
|
||||||
* @uuid: uuid of ME client
|
* @id - fixed host id or -1 for genereting one
|
||||||
* @client_id: id of the host client
|
* returns 0 on success
|
||||||
*
|
|
||||||
* returns ME client index if ME client
|
|
||||||
* -EINVAL on incorrect values
|
* -EINVAL on incorrect values
|
||||||
* -ENONET if client not found
|
* -ENONET if client not found
|
||||||
*/
|
*/
|
||||||
int mei_cl_link_me(struct mei_cl *cl, const uuid_le *uuid, u8 host_cl_id)
|
int mei_cl_link(struct mei_cl *cl, int id)
|
||||||
{
|
{
|
||||||
struct mei_device *dev;
|
struct mei_device *dev;
|
||||||
int i;
|
|
||||||
|
|
||||||
if (WARN_ON(!cl || !cl->dev || !uuid))
|
if (WARN_ON(!cl || !cl->dev))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
dev = cl->dev;
|
dev = cl->dev;
|
||||||
|
|
||||||
/* check for valid client id */
|
/* If Id is not asigned get one*/
|
||||||
i = mei_me_cl_by_uuid(dev, uuid);
|
if (id == MEI_HOST_CLIENT_ID_ANY)
|
||||||
if (i >= 0) {
|
id = find_first_zero_bit(dev->host_clients_map,
|
||||||
cl->me_client_id = dev->me_clients[i].client_id;
|
MEI_CLIENTS_MAX);
|
||||||
cl->state = MEI_FILE_CONNECTING;
|
|
||||||
cl->host_client_id = host_cl_id;
|
|
||||||
|
|
||||||
list_add_tail(&cl->link, &dev->file_list);
|
if (id >= MEI_CLIENTS_MAX) {
|
||||||
return (u8)i;
|
dev_err(&dev->pdev->dev, "id exceded %d", MEI_CLIENTS_MAX) ;
|
||||||
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ENOENT;
|
dev->open_handle_count++;
|
||||||
|
|
||||||
|
cl->host_client_id = id;
|
||||||
|
list_add_tail(&cl->link, &dev->file_list);
|
||||||
|
|
||||||
|
set_bit(id, dev->host_clients_map);
|
||||||
|
|
||||||
|
cl->state = MEI_FILE_INITIALIZING;
|
||||||
|
|
||||||
|
dev_dbg(&dev->pdev->dev, "link cl host id = %d\n", cl->host_client_id);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mei_cl_unlink - remove me_cl from the list
|
* mei_cl_unlink - remove me_cl from the list
|
||||||
*
|
*
|
||||||
* @dev: the device structure
|
* @dev: the device structure
|
||||||
* @host_client_id: host client id to be removed
|
|
||||||
*/
|
*/
|
||||||
int mei_cl_unlink(struct mei_cl *cl)
|
int mei_cl_unlink(struct mei_cl *cl)
|
||||||
{
|
{
|
||||||
struct mei_device *dev;
|
struct mei_device *dev;
|
||||||
struct mei_cl *pos, *next;
|
struct mei_cl *pos, *next;
|
||||||
|
|
||||||
if (WARN_ON(!cl || !cl->dev))
|
/* don't shout on error exit path */
|
||||||
|
if (!cl)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (WARN_ON(!cl->dev))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
dev = cl->dev;
|
dev = cl->dev;
|
||||||
|
|
|
@ -55,7 +55,7 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev);
|
||||||
void mei_cl_init(struct mei_cl *cl, struct mei_device *dev);
|
void mei_cl_init(struct mei_cl *cl, struct mei_device *dev);
|
||||||
|
|
||||||
|
|
||||||
int mei_cl_link_me(struct mei_cl *cl, const uuid_le *uuid, u8 host_cl_id);
|
int mei_cl_link(struct mei_cl *cl, int id);
|
||||||
int mei_cl_unlink(struct mei_cl *cl);
|
int mei_cl_unlink(struct mei_cl *cl);
|
||||||
|
|
||||||
int mei_cl_flush_queues(struct mei_cl *cl);
|
int mei_cl_flush_queues(struct mei_cl *cl);
|
||||||
|
|
|
@ -242,7 +242,11 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
|
||||||
/* remove entry if already in list */
|
/* remove entry if already in list */
|
||||||
dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n");
|
dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n");
|
||||||
mei_cl_unlink(&dev->wd_cl);
|
mei_cl_unlink(&dev->wd_cl);
|
||||||
|
if (dev->open_handle_count > 0)
|
||||||
|
dev->open_handle_count--;
|
||||||
mei_cl_unlink(&dev->iamthif_cl);
|
mei_cl_unlink(&dev->iamthif_cl);
|
||||||
|
if (dev->open_handle_count > 0)
|
||||||
|
dev->open_handle_count--;
|
||||||
|
|
||||||
mei_amthif_reset_params(dev);
|
mei_amthif_reset_params(dev);
|
||||||
memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg));
|
memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg));
|
||||||
|
|
|
@ -103,7 +103,6 @@ static int mei_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct mei_cl *cl;
|
struct mei_cl *cl;
|
||||||
struct mei_device *dev;
|
struct mei_device *dev;
|
||||||
unsigned long cl_id;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = -ENODEV;
|
err = -ENODEV;
|
||||||
|
@ -133,24 +132,9 @@ static int mei_open(struct inode *inode, struct file *file)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
cl_id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX);
|
err = mei_cl_link(cl, MEI_HOST_CLIENT_ID_ANY);
|
||||||
if (cl_id >= MEI_CLIENTS_MAX) {
|
if (err)
|
||||||
dev_err(&dev->pdev->dev, "client_id exceded %d",
|
|
||||||
MEI_CLIENTS_MAX) ;
|
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
|
||||||
|
|
||||||
cl->host_client_id = cl_id;
|
|
||||||
|
|
||||||
dev_dbg(&dev->pdev->dev, "client_id = %d\n", cl->host_client_id);
|
|
||||||
|
|
||||||
dev->open_handle_count++;
|
|
||||||
|
|
||||||
list_add_tail(&cl->link, &dev->file_list);
|
|
||||||
|
|
||||||
set_bit(cl->host_client_id, dev->host_clients_map);
|
|
||||||
cl->state = MEI_FILE_INITIALIZING;
|
|
||||||
cl->sm_state = 0;
|
|
||||||
|
|
||||||
file->private_data = cl;
|
file->private_data = cl;
|
||||||
mutex_unlock(&dev->device_lock);
|
mutex_unlock(&dev->device_lock);
|
||||||
|
@ -209,6 +193,7 @@ static int mei_release(struct inode *inode, struct file *file)
|
||||||
}
|
}
|
||||||
mei_cl_unlink(cl);
|
mei_cl_unlink(cl);
|
||||||
|
|
||||||
|
|
||||||
/* free read cb */
|
/* free read cb */
|
||||||
cb = NULL;
|
cb = NULL;
|
||||||
if (cl->read_cb) {
|
if (cl->read_cb) {
|
||||||
|
@ -991,7 +976,13 @@ static void mei_remove(struct pci_dev *pdev)
|
||||||
|
|
||||||
/* remove entry if already in list */
|
/* remove entry if already in list */
|
||||||
dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
|
dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
|
||||||
|
|
||||||
|
if (dev->open_handle_count > 0)
|
||||||
|
dev->open_handle_count--;
|
||||||
mei_cl_unlink(&dev->wd_cl);
|
mei_cl_unlink(&dev->wd_cl);
|
||||||
|
|
||||||
|
if (dev->open_handle_count > 0)
|
||||||
|
dev->open_handle_count--;
|
||||||
mei_cl_unlink(&dev->iamthif_cl);
|
mei_cl_unlink(&dev->iamthif_cl);
|
||||||
|
|
||||||
dev->iamthif_current_cb = NULL;
|
dev->iamthif_current_cb = NULL;
|
||||||
|
|
|
@ -67,16 +67,16 @@ extern const u8 mei_wd_state_independence_msg[3][4];
|
||||||
* Number of File descriptors/handles
|
* Number of File descriptors/handles
|
||||||
* that can be opened to the driver.
|
* that can be opened to the driver.
|
||||||
*
|
*
|
||||||
* Limit to 253: 256 Total Clients
|
* Limit to 255: 256 Total Clients
|
||||||
* minus internal client for MEI Bus Messags
|
* minus internal client for MEI Bus Messags
|
||||||
* minus internal client for AMTHI
|
|
||||||
* minus internal client for Watchdog
|
|
||||||
*/
|
*/
|
||||||
#define MEI_MAX_OPEN_HANDLE_COUNT (MEI_CLIENTS_MAX - 3)
|
#define MEI_MAX_OPEN_HANDLE_COUNT (MEI_CLIENTS_MAX - 1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal Clients Number
|
* Internal Clients Number
|
||||||
*/
|
*/
|
||||||
|
#define MEI_HOST_CLIENT_ID_ANY (-1)
|
||||||
|
#define MEI_HBM_HOST_CLIENT_ID 0 /* not used, just for documentation */
|
||||||
#define MEI_WD_HOST_CLIENT_ID 1
|
#define MEI_WD_HOST_CLIENT_ID 1
|
||||||
#define MEI_IAMTHIF_HOST_CLIENT_ID 2
|
#define MEI_IAMTHIF_HOST_CLIENT_ID 2
|
||||||
|
|
||||||
|
@ -339,7 +339,7 @@ void mei_timer(struct work_struct *work);
|
||||||
*/
|
*/
|
||||||
void mei_amthif_reset_params(struct mei_device *dev);
|
void mei_amthif_reset_params(struct mei_device *dev);
|
||||||
|
|
||||||
void mei_amthif_host_init(struct mei_device *dev);
|
int mei_amthif_host_init(struct mei_device *dev);
|
||||||
|
|
||||||
int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *priv_cb);
|
int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *priv_cb);
|
||||||
|
|
||||||
|
|
|
@ -64,30 +64,41 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
|
||||||
*/
|
*/
|
||||||
int mei_wd_host_init(struct mei_device *dev)
|
int mei_wd_host_init(struct mei_device *dev)
|
||||||
{
|
{
|
||||||
int id;
|
struct mei_cl *cl = &dev->wd_cl;
|
||||||
mei_cl_init(&dev->wd_cl, dev);
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mei_cl_init(cl, dev);
|
||||||
|
|
||||||
/* look for WD client and connect to it */
|
|
||||||
dev->wd_cl.state = MEI_FILE_DISCONNECTED;
|
|
||||||
dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT;
|
dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT;
|
||||||
dev->wd_state = MEI_WD_IDLE;
|
dev->wd_state = MEI_WD_IDLE;
|
||||||
|
|
||||||
/* Connect WD ME client to the host client */
|
|
||||||
id = mei_cl_link_me(&dev->wd_cl,
|
|
||||||
&mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
|
|
||||||
|
|
||||||
if (id < 0) {
|
/* check for valid client id */
|
||||||
|
i = mei_me_cl_by_uuid(dev, &mei_wd_guid);
|
||||||
|
if (i < 0) {
|
||||||
dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
|
dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mei_hbm_cl_connect_req(dev, &dev->wd_cl)) {
|
cl->me_client_id = dev->me_clients[i].client_id;
|
||||||
|
|
||||||
|
ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_info(&dev->pdev->dev, "wd: failed link client\n");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl->state = MEI_FILE_CONNECTING;
|
||||||
|
|
||||||
|
if (mei_hbm_cl_connect_req(dev, cl)) {
|
||||||
dev_err(&dev->pdev->dev, "wd: failed to connect to the client\n");
|
dev_err(&dev->pdev->dev, "wd: failed to connect to the client\n");
|
||||||
dev->wd_cl.state = MEI_FILE_DISCONNECTED;
|
cl->state = MEI_FILE_DISCONNECTED;
|
||||||
dev->wd_cl.host_client_id = 0;
|
cl->host_client_id = 0;
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
dev->wd_cl.timer_count = MEI_CONNECT_TIMEOUT;
|
cl->timer_count = MEI_CONNECT_TIMEOUT;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue