mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 01:10:04 +00:00
mei: add a reference from the host client to the me client
Keep a pointer to associated me client in the host client object to eliminate me client searches. Check if the me client is active in the firmware by checking if its is linked on the me clients list Add accessors for the me client properties from host client. Signed-off-by: Alexander Usyskin <alexander.usyskin@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
0c53357ca4
commit
d49ed64a6e
11 changed files with 228 additions and 182 deletions
|
@ -59,28 +59,19 @@ void mei_amthif_reset_params(struct mei_device *dev)
|
|||
* mei_amthif_host_init - mei initialization amthif client.
|
||||
*
|
||||
* @dev: the device structure
|
||||
* @me_cl: me client
|
||||
*
|
||||
* Return: 0 on success, <0 on failure.
|
||||
*/
|
||||
int mei_amthif_host_init(struct mei_device *dev)
|
||||
int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
|
||||
{
|
||||
struct mei_cl *cl = &dev->iamthif_cl;
|
||||
struct mei_me_client *me_cl;
|
||||
int ret;
|
||||
|
||||
dev->iamthif_state = MEI_IAMTHIF_IDLE;
|
||||
|
||||
mei_cl_init(cl, dev);
|
||||
|
||||
me_cl = mei_me_cl_by_uuid(dev, &mei_amthif_guid);
|
||||
if (!me_cl) {
|
||||
dev_info(dev->dev, "amthif: failed to find the client");
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
cl->me_client_id = me_cl->client_id;
|
||||
cl->cl_uuid = me_cl->props.protocol_name;
|
||||
|
||||
/* Assign iamthif_mtu to the value received from ME */
|
||||
|
||||
dev->iamthif_mtu = me_cl->props.max_msg_length;
|
||||
|
@ -90,15 +81,13 @@ int mei_amthif_host_init(struct mei_device *dev)
|
|||
ret = mei_cl_link(cl, MEI_IAMTHIF_HOST_CLIENT_ID);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "amthif: failed cl_link %d\n", ret);
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mei_cl_connect(cl, NULL);
|
||||
ret = mei_cl_connect(cl, me_cl, NULL);
|
||||
|
||||
dev->iamthif_state = MEI_IAMTHIF_IDLE;
|
||||
|
||||
out:
|
||||
mei_me_cl_put(me_cl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,13 @@ static struct bus_type mei_cl_bus_type = {
|
|||
|
||||
static void mei_cl_dev_release(struct device *dev)
|
||||
{
|
||||
kfree(to_mei_cl_device(dev));
|
||||
struct mei_cl_device *device = to_mei_cl_device(dev);
|
||||
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
mei_me_cl_put(device->me_cl);
|
||||
kfree(device);
|
||||
}
|
||||
|
||||
static struct device_type mei_cl_device_type = {
|
||||
|
@ -141,33 +147,37 @@ static struct device_type mei_cl_device_type = {
|
|||
};
|
||||
|
||||
struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev,
|
||||
uuid_le uuid)
|
||||
uuid_le uuid)
|
||||
{
|
||||
struct mei_cl *cl;
|
||||
|
||||
list_for_each_entry(cl, &dev->device_list, device_link) {
|
||||
if (!uuid_le_cmp(uuid, cl->cl_uuid))
|
||||
if (cl->device && cl->device->me_cl &&
|
||||
!uuid_le_cmp(uuid, *mei_me_cl_uuid(cl->device->me_cl)))
|
||||
return cl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
|
||||
uuid_le uuid, char *name,
|
||||
struct mei_me_client *me_cl,
|
||||
struct mei_cl *cl,
|
||||
char *name,
|
||||
struct mei_cl_ops *ops)
|
||||
{
|
||||
struct mei_cl_device *device;
|
||||
struct mei_cl *cl;
|
||||
int status;
|
||||
|
||||
cl = mei_cl_bus_find_cl_by_uuid(dev, uuid);
|
||||
if (cl == NULL)
|
||||
return NULL;
|
||||
|
||||
device = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
|
||||
if (!device)
|
||||
return NULL;
|
||||
|
||||
device->me_cl = mei_me_cl_get(me_cl);
|
||||
if (!device->me_cl) {
|
||||
kfree(device);
|
||||
return NULL;
|
||||
}
|
||||
device->cl = cl;
|
||||
device->ops = ops;
|
||||
|
||||
|
@ -180,6 +190,7 @@ struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
|
|||
status = device_register(&device->dev);
|
||||
if (status) {
|
||||
dev_err(dev->dev, "Failed to register MEI device\n");
|
||||
mei_me_cl_put(device->me_cl);
|
||||
kfree(device);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -228,7 +239,6 @@ static ssize_t ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
|
|||
bool blocking)
|
||||
{
|
||||
struct mei_device *dev;
|
||||
struct mei_me_client *me_cl = NULL;
|
||||
struct mei_cl_cb *cb = NULL;
|
||||
ssize_t rets;
|
||||
|
||||
|
@ -244,13 +254,12 @@ static ssize_t ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
|
|||
}
|
||||
|
||||
/* Check if we have an ME client device */
|
||||
me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
|
||||
if (!me_cl) {
|
||||
if (!mei_me_cl_is_active(cl->me_cl)) {
|
||||
rets = -ENOTTY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (length > me_cl->props.max_msg_length) {
|
||||
if (length > mei_cl_mtu(cl)) {
|
||||
rets = -EFBIG;
|
||||
goto out;
|
||||
}
|
||||
|
@ -266,7 +275,6 @@ static ssize_t ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
|
|||
rets = mei_cl_write(cl, cb, blocking);
|
||||
|
||||
out:
|
||||
mei_me_cl_put(me_cl);
|
||||
mutex_unlock(&dev->device_lock);
|
||||
if (rets < 0)
|
||||
mei_io_cb_free(cb);
|
||||
|
@ -442,7 +450,7 @@ int mei_cl_enable_device(struct mei_cl_device *device)
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
err = mei_cl_connect(cl, NULL);
|
||||
err = mei_cl_connect(cl, device->me_cl, NULL);
|
||||
if (err < 0) {
|
||||
mutex_unlock(&dev->device_lock);
|
||||
dev_err(dev->dev, "Could not connect to the ME client");
|
||||
|
|
|
@ -83,7 +83,7 @@ void mei_me_cl_put(struct mei_me_client *me_cl)
|
|||
}
|
||||
|
||||
/**
|
||||
* __mei_me_cl_del - delete me client form the list and decrease
|
||||
* __mei_me_cl_del - delete me client from the list and decrease
|
||||
* reference counter
|
||||
*
|
||||
* @dev: mei device
|
||||
|
@ -96,10 +96,24 @@ static void __mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl)
|
|||
if (!me_cl)
|
||||
return;
|
||||
|
||||
list_del(&me_cl->list);
|
||||
list_del_init(&me_cl->list);
|
||||
mei_me_cl_put(me_cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_me_cl_del - delete me client from the list and decrease
|
||||
* reference counter
|
||||
*
|
||||
* @dev: mei device
|
||||
* @me_cl: me client
|
||||
*/
|
||||
void mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl)
|
||||
{
|
||||
down_write(&dev->me_clients_rwsem);
|
||||
__mei_me_cl_del(dev, me_cl);
|
||||
up_write(&dev->me_clients_rwsem);
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_me_cl_add - add me client to the list
|
||||
*
|
||||
|
@ -317,7 +331,7 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
|
|||
{
|
||||
return cl1 && cl2 &&
|
||||
(cl1->host_client_id == cl2->host_client_id) &&
|
||||
(cl1->me_client_id == cl2->me_client_id);
|
||||
(mei_cl_me_id(cl1) == mei_cl_me_id(cl2));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -620,7 +634,7 @@ int mei_cl_link(struct mei_cl *cl, int id)
|
|||
}
|
||||
|
||||
/**
|
||||
* mei_cl_unlink - remove me_cl from the list
|
||||
* mei_cl_unlink - remove host client from the list
|
||||
*
|
||||
* @cl: host client
|
||||
*
|
||||
|
@ -668,17 +682,17 @@ void mei_host_client_init(struct work_struct *work)
|
|||
|
||||
me_cl = mei_me_cl_by_uuid(dev, &mei_amthif_guid);
|
||||
if (me_cl)
|
||||
mei_amthif_host_init(dev);
|
||||
mei_amthif_host_init(dev, me_cl);
|
||||
mei_me_cl_put(me_cl);
|
||||
|
||||
me_cl = mei_me_cl_by_uuid(dev, &mei_wd_guid);
|
||||
if (me_cl)
|
||||
mei_wd_host_init(dev);
|
||||
mei_wd_host_init(dev, me_cl);
|
||||
mei_me_cl_put(me_cl);
|
||||
|
||||
me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
|
||||
if (me_cl)
|
||||
mei_nfc_host_init(dev);
|
||||
mei_nfc_host_init(dev, me_cl);
|
||||
mei_me_cl_put(me_cl);
|
||||
|
||||
|
||||
|
@ -734,6 +748,9 @@ void mei_cl_set_disconnected(struct mei_cl *cl)
|
|||
mei_io_list_flush(&dev->ctrl_wr_list, cl);
|
||||
cl->mei_flow_ctrl_creds = 0;
|
||||
cl->timer_count = 0;
|
||||
|
||||
mei_me_cl_put(cl->me_cl);
|
||||
cl->me_cl = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -890,7 +907,7 @@ static bool mei_cl_is_other_connecting(struct mei_cl *cl)
|
|||
|
||||
list_for_each_entry(cb, &dev->ctrl_rd_list.list, list) {
|
||||
if (cb->fop_type == MEI_FOP_CONNECT &&
|
||||
cl->me_client_id == cb->cl->me_client_id)
|
||||
mei_cl_me_id(cl) == mei_cl_me_id(cb->cl))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -961,13 +978,15 @@ int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
|
|||
* mei_cl_connect - connect host client to the me one
|
||||
*
|
||||
* @cl: host client
|
||||
* @me_cl: me client
|
||||
* @file: pointer to file structure
|
||||
*
|
||||
* Locking: called under "dev->device_lock" lock
|
||||
*
|
||||
* Return: 0 on success, <0 on failure.
|
||||
*/
|
||||
int mei_cl_connect(struct mei_cl *cl, struct file *file)
|
||||
int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl,
|
||||
struct file *file)
|
||||
{
|
||||
struct mei_device *dev;
|
||||
struct mei_cl_cb *cb;
|
||||
|
@ -990,6 +1009,12 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
|
|||
if (rets)
|
||||
goto out;
|
||||
|
||||
cl->me_cl = mei_me_cl_get(me_cl);
|
||||
if (!cl->me_cl) {
|
||||
rets = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cl->state = MEI_FILE_CONNECTING;
|
||||
list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
|
||||
|
||||
|
@ -1064,36 +1089,20 @@ struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id)
|
|||
* @cl: private data of the file object
|
||||
*
|
||||
* Return: 1 if mei_flow_ctrl_creds >0, 0 - otherwise.
|
||||
* -ENOENT if mei_cl is not present
|
||||
* -EINVAL if single_recv_buf == 0
|
||||
*/
|
||||
int mei_cl_flow_ctrl_creds(struct mei_cl *cl)
|
||||
{
|
||||
struct mei_device *dev;
|
||||
struct mei_me_client *me_cl;
|
||||
int rets = 0;
|
||||
|
||||
if (WARN_ON(!cl || !cl->dev))
|
||||
if (WARN_ON(!cl || !cl->me_cl))
|
||||
return -EINVAL;
|
||||
|
||||
dev = cl->dev;
|
||||
|
||||
if (cl->mei_flow_ctrl_creds > 0)
|
||||
return 1;
|
||||
|
||||
me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
|
||||
if (!me_cl) {
|
||||
cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
|
||||
return -ENOENT;
|
||||
if (mei_cl_is_single_recv_buf(cl)) {
|
||||
if (cl->me_cl->mei_flow_ctrl_creds > 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (me_cl->mei_flow_ctrl_creds > 0) {
|
||||
rets = 1;
|
||||
if (WARN_ON(me_cl->props.single_recv_buf == 0))
|
||||
rets = -EINVAL;
|
||||
}
|
||||
mei_me_cl_put(me_cl);
|
||||
return rets;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1103,43 +1112,23 @@ int mei_cl_flow_ctrl_creds(struct mei_cl *cl)
|
|||
*
|
||||
* Return:
|
||||
* 0 on success
|
||||
* -ENOENT when me client is not found
|
||||
* -EINVAL when ctrl credits are <= 0
|
||||
*/
|
||||
int mei_cl_flow_ctrl_reduce(struct mei_cl *cl)
|
||||
{
|
||||
struct mei_device *dev;
|
||||
struct mei_me_client *me_cl;
|
||||
int rets;
|
||||
|
||||
if (WARN_ON(!cl || !cl->dev))
|
||||
if (WARN_ON(!cl || !cl->me_cl))
|
||||
return -EINVAL;
|
||||
|
||||
dev = cl->dev;
|
||||
|
||||
me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
|
||||
if (!me_cl) {
|
||||
cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (me_cl->props.single_recv_buf) {
|
||||
if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0)) {
|
||||
rets = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
me_cl->mei_flow_ctrl_creds--;
|
||||
if (mei_cl_is_single_recv_buf(cl)) {
|
||||
if (WARN_ON(cl->me_cl->mei_flow_ctrl_creds <= 0))
|
||||
return -EINVAL;
|
||||
cl->me_cl->mei_flow_ctrl_creds--;
|
||||
} else {
|
||||
if (WARN_ON(cl->mei_flow_ctrl_creds <= 0)) {
|
||||
rets = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (WARN_ON(cl->mei_flow_ctrl_creds <= 0))
|
||||
return -EINVAL;
|
||||
cl->mei_flow_ctrl_creds--;
|
||||
}
|
||||
rets = 0;
|
||||
out:
|
||||
mei_me_cl_put(me_cl);
|
||||
return rets;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1155,7 +1144,6 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp)
|
|||
{
|
||||
struct mei_device *dev;
|
||||
struct mei_cl_cb *cb;
|
||||
struct mei_me_client *me_cl;
|
||||
int rets;
|
||||
|
||||
if (WARN_ON(!cl || !cl->dev))
|
||||
|
@ -1170,14 +1158,12 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp)
|
|||
if (!list_empty(&cl->rd_pending))
|
||||
return -EBUSY;
|
||||
|
||||
me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
|
||||
if (!me_cl) {
|
||||
cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
|
||||
if (!mei_me_cl_is_active(cl->me_cl)) {
|
||||
cl_err(dev, cl, "no such me client\n");
|
||||
return -ENOTTY;
|
||||
}
|
||||
/* always allocate at least client max message */
|
||||
length = max_t(size_t, length, me_cl->props.max_msg_length);
|
||||
mei_me_cl_put(me_cl);
|
||||
length = max_t(size_t, length, mei_cl_mtu(cl));
|
||||
|
||||
rets = pm_runtime_get(dev->dev);
|
||||
if (rets < 0 && rets != -EINPROGRESS) {
|
||||
|
@ -1254,7 +1240,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
|
|||
msg_slots = mei_data2slots(len);
|
||||
|
||||
mei_hdr.host_addr = cl->host_client_id;
|
||||
mei_hdr.me_addr = cl->me_client_id;
|
||||
mei_hdr.me_addr = mei_cl_me_id(cl);
|
||||
mei_hdr.reserved = 0;
|
||||
mei_hdr.internal = cb->internal;
|
||||
|
||||
|
@ -1338,7 +1324,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
|
|||
cl->writing_state = MEI_IDLE;
|
||||
|
||||
mei_hdr.host_addr = cl->host_client_id;
|
||||
mei_hdr.me_addr = cl->me_client_id;
|
||||
mei_hdr.me_addr = mei_cl_me_id(cl);
|
||||
mei_hdr.reserved = 0;
|
||||
mei_hdr.msg_complete = 0;
|
||||
mei_hdr.internal = cb->internal;
|
||||
|
|
|
@ -44,6 +44,30 @@ void mei_me_cl_rm_by_uuid_id(struct mei_device *dev,
|
|||
const uuid_le *uuid, u8 id);
|
||||
void mei_me_cl_rm_all(struct mei_device *dev);
|
||||
|
||||
/**
|
||||
* mei_me_cl_is_active - check whether me client is active in the fw
|
||||
*
|
||||
* @me_cl: me client
|
||||
*
|
||||
* Return: true if the me client is active in the firmware
|
||||
*/
|
||||
static inline bool mei_me_cl_is_active(const struct mei_me_client *me_cl)
|
||||
{
|
||||
return !list_empty_careful(&me_cl->list);
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_me_cl_uuid - return me client protocol name (uuid)
|
||||
*
|
||||
* @me_cl: me client
|
||||
*
|
||||
* Return: me client protocol name
|
||||
*/
|
||||
static inline const uuid_le *mei_me_cl_uuid(const struct mei_me_client *me_cl)
|
||||
{
|
||||
return &me_cl->props.protocol_name;
|
||||
}
|
||||
|
||||
/*
|
||||
* MEI IO Functions
|
||||
*/
|
||||
|
@ -94,20 +118,82 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl);
|
|||
/**
|
||||
* mei_cl_is_connected - host client is connected
|
||||
*
|
||||
* @cl: host clinet
|
||||
* @cl: host client
|
||||
*
|
||||
* Return: true if the host clinet is connected
|
||||
* Return: true if the host client is connected
|
||||
*/
|
||||
static inline bool mei_cl_is_connected(struct mei_cl *cl)
|
||||
{
|
||||
return cl->state == MEI_FILE_CONNECTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_me_id - me client id
|
||||
*
|
||||
* @cl: host client
|
||||
*
|
||||
* Return: me client id or 0 if client is not connected
|
||||
*/
|
||||
static inline u8 mei_cl_me_id(const struct mei_cl *cl)
|
||||
{
|
||||
return cl->me_cl ? cl->me_cl->client_id : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_mtu - maximal message that client can send and receive
|
||||
*
|
||||
* @cl: host client
|
||||
*
|
||||
* Return: mtu
|
||||
*/
|
||||
static inline size_t mei_cl_mtu(const struct mei_cl *cl)
|
||||
{
|
||||
return cl->me_cl->props.max_msg_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_is_fixed_address - check whether the me client uses fixed address
|
||||
*
|
||||
* @cl: host client
|
||||
*
|
||||
* Return: true if the client is connected and it has fixed me address
|
||||
*/
|
||||
static inline bool mei_cl_is_fixed_address(const struct mei_cl *cl)
|
||||
{
|
||||
return cl->me_cl && cl->me_cl->props.fixed_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_is_single_recv_buf- check whether the me client
|
||||
* uses single receiving buffer
|
||||
*
|
||||
* @cl: host client
|
||||
*
|
||||
* Return: true if single_recv_buf == 1; 0 otherwise
|
||||
*/
|
||||
static inline bool mei_cl_is_single_recv_buf(const struct mei_cl *cl)
|
||||
{
|
||||
return cl->me_cl->props.single_recv_buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_uuid - client's uuid
|
||||
*
|
||||
* @cl: host client
|
||||
*
|
||||
* Return: return uuid of connected me client
|
||||
*/
|
||||
static inline const uuid_le *mei_cl_uuid(const struct mei_cl *cl)
|
||||
{
|
||||
return mei_me_cl_uuid(cl->me_cl);
|
||||
}
|
||||
|
||||
int mei_cl_disconnect(struct mei_cl *cl);
|
||||
void mei_cl_set_disconnected(struct mei_cl *cl);
|
||||
int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb,
|
||||
struct mei_cl_cb *cmpl_list);
|
||||
int mei_cl_connect(struct mei_cl *cl, struct file *file);
|
||||
int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl,
|
||||
struct file *file);
|
||||
int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
|
||||
struct mei_cl_cb *cmpl_list);
|
||||
int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp);
|
||||
|
@ -121,14 +207,12 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb);
|
|||
|
||||
void mei_host_client_init(struct work_struct *work);
|
||||
|
||||
|
||||
|
||||
void mei_cl_all_disconnect(struct mei_device *dev);
|
||||
void mei_cl_all_wakeup(struct mei_device *dev);
|
||||
void mei_cl_all_write_clear(struct mei_device *dev);
|
||||
|
||||
#define MEI_CL_FMT "cl:host=%02d me=%02d "
|
||||
#define MEI_CL_PRM(cl) (cl)->host_client_id, (cl)->me_client_id
|
||||
#define MEI_CL_PRM(cl) (cl)->host_client_id, mei_cl_me_id(cl)
|
||||
|
||||
#define cl_dbg(dev, cl, format, arg...) \
|
||||
dev_dbg((dev)->dev, MEI_CL_FMT format, MEI_CL_PRM(cl), ##arg)
|
||||
|
|
|
@ -116,7 +116,7 @@ static ssize_t mei_dbgfs_read_active(struct file *fp, char __user *ubuf,
|
|||
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"%2d|%2d|%4d|%5d|%2d|%2d|\n",
|
||||
i, cl->me_client_id, cl->host_client_id, cl->state,
|
||||
i, mei_cl_me_id(cl), cl->host_client_id, cl->state,
|
||||
!list_empty(&cl->rd_completed), cl->writing_state);
|
||||
i++;
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ void mei_hbm_cl_hdr(struct mei_cl *cl, u8 hbm_cmd, void *buf, size_t len)
|
|||
|
||||
cmd->hbm_cmd = hbm_cmd;
|
||||
cmd->host_addr = cl->host_client_id;
|
||||
cmd->me_addr = cl->me_client_id;
|
||||
cmd->me_addr = mei_cl_me_id(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,7 +189,7 @@ static inline
|
|||
bool mei_hbm_cl_addr_equal(struct mei_cl *cl, struct mei_hbm_cl_cmd *cmd)
|
||||
{
|
||||
return cl->host_client_id == cmd->host_addr &&
|
||||
cl->me_client_id == cmd->me_addr;
|
||||
mei_cl_me_id(cl) == cmd->me_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -66,7 +66,7 @@ static inline int mei_cl_hbm_equal(struct mei_cl *cl,
|
|||
struct mei_msg_hdr *mei_hdr)
|
||||
{
|
||||
return cl->host_client_id == mei_hdr->host_addr &&
|
||||
cl->me_client_id == mei_hdr->me_addr;
|
||||
mei_cl_me_id(cl) == mei_hdr->me_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -182,6 +182,8 @@ static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
|
|||
ret = mei_hbm_cl_disconnect_rsp(dev, cl);
|
||||
mei_cl_set_disconnected(cl);
|
||||
mei_io_cb_free(cb);
|
||||
mei_me_cl_put(cl->me_cl);
|
||||
cl->me_cl = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -271,7 +271,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
|
|||
size_t length, loff_t *offset)
|
||||
{
|
||||
struct mei_cl *cl = file->private_data;
|
||||
struct mei_me_client *me_cl = NULL;
|
||||
struct mei_cl_cb *write_cb = NULL;
|
||||
struct mei_device *dev;
|
||||
unsigned long timeout = 0;
|
||||
|
@ -289,27 +288,27 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
|
|||
goto out;
|
||||
}
|
||||
|
||||
me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
|
||||
if (!me_cl) {
|
||||
if (!mei_cl_is_connected(cl)) {
|
||||
cl_err(dev, cl, "is not connected");
|
||||
rets = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!mei_me_cl_is_active(cl->me_cl)) {
|
||||
rets = -ENOTTY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (length > mei_cl_mtu(cl)) {
|
||||
rets = -EFBIG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (length == 0) {
|
||||
rets = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (length > me_cl->props.max_msg_length) {
|
||||
rets = -EFBIG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!mei_cl_is_connected(cl)) {
|
||||
cl_err(dev, cl, "is not connected");
|
||||
rets = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
if (cl == &dev->iamthif_cl) {
|
||||
write_cb = mei_amthif_find_read_list_entry(dev, file);
|
||||
|
||||
|
@ -347,14 +346,12 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
|
|||
"amthif write failed with status = %d\n", rets);
|
||||
goto out;
|
||||
}
|
||||
mei_me_cl_put(me_cl);
|
||||
mutex_unlock(&dev->device_lock);
|
||||
return length;
|
||||
}
|
||||
|
||||
rets = mei_cl_write(cl, write_cb, false);
|
||||
out:
|
||||
mei_me_cl_put(me_cl);
|
||||
mutex_unlock(&dev->device_lock);
|
||||
if (rets < 0)
|
||||
mei_io_cb_free(write_cb);
|
||||
|
@ -394,15 +391,13 @@ static int mei_ioctl_connect_client(struct file *file,
|
|||
me_cl = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
|
||||
if (!me_cl || me_cl->props.fixed_address) {
|
||||
dev_dbg(dev->dev, "Cannot connect to FW Client UUID = %pUl\n",
|
||||
&data->in_client_uuid);
|
||||
&data->in_client_uuid);
|
||||
mei_me_cl_put(me_cl);
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
cl->me_client_id = me_cl->client_id;
|
||||
cl->cl_uuid = me_cl->props.protocol_name;
|
||||
|
||||
dev_dbg(dev->dev, "Connect to FW Client ID = %d\n",
|
||||
cl->me_client_id);
|
||||
me_cl->client_id);
|
||||
dev_dbg(dev->dev, "FW Client - Protocol Version = %d\n",
|
||||
me_cl->props.protocol_version);
|
||||
dev_dbg(dev->dev, "FW Client - Max Msg Len = %d\n",
|
||||
|
@ -438,7 +433,7 @@ static int mei_ioctl_connect_client(struct file *file,
|
|||
client->protocol_version = me_cl->props.protocol_version;
|
||||
dev_dbg(dev->dev, "Can connect?\n");
|
||||
|
||||
rets = mei_cl_connect(cl, file);
|
||||
rets = mei_cl_connect(cl, me_cl, file);
|
||||
|
||||
end:
|
||||
mei_me_cl_put(me_cl);
|
||||
|
|
|
@ -227,11 +227,11 @@ struct mei_cl_cb {
|
|||
* @rx_wait: wait queue for rx completion
|
||||
* @wait: wait queue for management operation
|
||||
* @status: connection status
|
||||
* @cl_uuid: client uuid name
|
||||
* @me_cl: fw client connected
|
||||
* @host_client_id: host id
|
||||
* @me_client_id: me/fw id
|
||||
* @mei_flow_ctrl_creds: transmit flow credentials
|
||||
* @timer_count: watchdog timer for operation completion
|
||||
* @reserved: reserved for alignment
|
||||
* @writing_state: state of the tx
|
||||
* @rd_pending: pending read credits
|
||||
* @rd_completed: completed read
|
||||
|
@ -247,11 +247,11 @@ struct mei_cl {
|
|||
wait_queue_head_t rx_wait;
|
||||
wait_queue_head_t wait;
|
||||
int status;
|
||||
uuid_le cl_uuid;
|
||||
struct mei_me_client *me_cl;
|
||||
u8 host_client_id;
|
||||
u8 me_client_id;
|
||||
u8 mei_flow_ctrl_creds;
|
||||
u8 timer_count;
|
||||
u8 reserved;
|
||||
enum mei_file_transaction_states writing_state;
|
||||
struct list_head rd_pending;
|
||||
struct list_head rd_completed;
|
||||
|
@ -346,7 +346,9 @@ struct mei_cl_ops {
|
|||
};
|
||||
|
||||
struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
|
||||
uuid_le uuid, char *name,
|
||||
struct mei_me_client *me_cl,
|
||||
struct mei_cl *cl,
|
||||
char *name,
|
||||
struct mei_cl_ops *ops);
|
||||
void mei_cl_remove_device(struct mei_cl_device *device);
|
||||
|
||||
|
@ -368,6 +370,7 @@ struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev, uuid_le uuid);
|
|||
* when being probed and shall use it for doing ME bus I/O.
|
||||
*
|
||||
* @dev: linux driver model device pointer
|
||||
* @me_cl: me client
|
||||
* @cl: mei client
|
||||
* @ops: ME transport ops
|
||||
* @event_work: async work to execute event callback
|
||||
|
@ -380,6 +383,7 @@ struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev, uuid_le uuid);
|
|||
struct mei_cl_device {
|
||||
struct device dev;
|
||||
|
||||
struct mei_me_client *me_cl;
|
||||
struct mei_cl *cl;
|
||||
|
||||
const struct mei_cl_ops *ops;
|
||||
|
@ -653,7 +657,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list);
|
|||
*/
|
||||
void mei_amthif_reset_params(struct mei_device *dev);
|
||||
|
||||
int mei_amthif_host_init(struct mei_device *dev);
|
||||
int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl);
|
||||
|
||||
int mei_amthif_read(struct mei_device *dev, struct file *file,
|
||||
char __user *ubuf, size_t length, loff_t *offset);
|
||||
|
@ -680,7 +684,7 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots);
|
|||
/*
|
||||
* NFC functions
|
||||
*/
|
||||
int mei_nfc_host_init(struct mei_device *dev);
|
||||
int mei_nfc_host_init(struct mei_device *dev, struct mei_me_client *me_cl);
|
||||
void mei_nfc_host_exit(struct mei_device *dev);
|
||||
|
||||
/*
|
||||
|
@ -690,7 +694,7 @@ extern const uuid_le mei_nfc_guid;
|
|||
|
||||
int mei_wd_send(struct mei_device *dev);
|
||||
int mei_wd_stop(struct mei_device *dev);
|
||||
int mei_wd_host_init(struct mei_device *dev);
|
||||
int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl);
|
||||
/*
|
||||
* mei_watchdog_register - Registering watchdog interface
|
||||
* once we got connection to the WD Client
|
||||
|
|
|
@ -91,6 +91,7 @@ struct mei_nfc_hci_hdr {
|
|||
/**
|
||||
* struct mei_nfc_dev - NFC mei device
|
||||
*
|
||||
* @me_cl: NFC me client
|
||||
* @cl: NFC host client
|
||||
* @cl_info: NFC info host client
|
||||
* @init_work: perform connection to the info client
|
||||
|
@ -104,6 +105,7 @@ struct mei_nfc_hci_hdr {
|
|||
* @recv_req_id: reception message counter
|
||||
*/
|
||||
struct mei_nfc_dev {
|
||||
struct mei_me_client *me_cl;
|
||||
struct mei_cl *cl;
|
||||
struct mei_cl *cl_info;
|
||||
struct work_struct init_work;
|
||||
|
@ -151,6 +153,7 @@ static void mei_nfc_free(struct mei_nfc_dev *ndev)
|
|||
kfree(ndev->cl_info);
|
||||
}
|
||||
|
||||
mei_me_cl_put(ndev->me_cl);
|
||||
kfree(ndev);
|
||||
}
|
||||
|
||||
|
@ -417,6 +420,7 @@ static void mei_nfc_init(struct work_struct *work)
|
|||
struct mei_cl_device *cldev;
|
||||
struct mei_nfc_dev *ndev;
|
||||
struct mei_cl *cl_info;
|
||||
struct mei_me_client *me_cl_info;
|
||||
|
||||
ndev = container_of(work, struct mei_nfc_dev, init_work);
|
||||
|
||||
|
@ -425,13 +429,22 @@ static void mei_nfc_init(struct work_struct *work)
|
|||
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
||||
if (mei_cl_connect(cl_info, NULL) < 0) {
|
||||
/* check for valid client id */
|
||||
me_cl_info = mei_me_cl_by_uuid(dev, &mei_nfc_info_guid);
|
||||
if (!me_cl_info) {
|
||||
mutex_unlock(&dev->device_lock);
|
||||
dev_info(dev->dev, "nfc: failed to find the info client\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mei_cl_connect(cl_info, me_cl_info, NULL) < 0) {
|
||||
mei_me_cl_put(me_cl_info);
|
||||
mutex_unlock(&dev->device_lock);
|
||||
dev_err(dev->dev, "Could not connect to the NFC INFO ME client");
|
||||
|
||||
goto err;
|
||||
}
|
||||
|
||||
mei_me_cl_put(me_cl_info);
|
||||
mutex_unlock(&dev->device_lock);
|
||||
|
||||
if (mei_nfc_if_version(ndev) < 0) {
|
||||
|
@ -459,7 +472,8 @@ static void mei_nfc_init(struct work_struct *work)
|
|||
return;
|
||||
}
|
||||
|
||||
cldev = mei_cl_add_device(dev, mei_nfc_guid, ndev->bus_name, &nfc_ops);
|
||||
cldev = mei_cl_add_device(dev, ndev->me_cl, ndev->cl,
|
||||
ndev->bus_name, &nfc_ops);
|
||||
if (!cldev) {
|
||||
dev_err(dev->dev, "Could not add the NFC device to the MEI bus\n");
|
||||
|
||||
|
@ -479,11 +493,10 @@ static void mei_nfc_init(struct work_struct *work)
|
|||
}
|
||||
|
||||
|
||||
int mei_nfc_host_init(struct mei_device *dev)
|
||||
int mei_nfc_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
|
||||
{
|
||||
struct mei_nfc_dev *ndev;
|
||||
struct mei_cl *cl_info, *cl;
|
||||
struct mei_me_client *me_cl = NULL;
|
||||
int ret;
|
||||
|
||||
|
||||
|
@ -500,11 +513,9 @@ int mei_nfc_host_init(struct mei_device *dev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
/* check for valid client id */
|
||||
me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_info_guid);
|
||||
if (!me_cl) {
|
||||
dev_info(dev->dev, "nfc: failed to find the client\n");
|
||||
ret = -ENOTTY;
|
||||
ndev->me_cl = mei_me_cl_get(me_cl);
|
||||
if (!ndev->me_cl) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -514,34 +525,16 @@ int mei_nfc_host_init(struct mei_device *dev)
|
|||
goto err;
|
||||
}
|
||||
|
||||
cl_info->me_client_id = me_cl->client_id;
|
||||
cl_info->cl_uuid = me_cl->props.protocol_name;
|
||||
mei_me_cl_put(me_cl);
|
||||
me_cl = NULL;
|
||||
|
||||
list_add_tail(&cl_info->device_link, &dev->device_list);
|
||||
|
||||
ndev->cl_info = cl_info;
|
||||
|
||||
/* check for valid client id */
|
||||
me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
|
||||
if (!me_cl) {
|
||||
dev_info(dev->dev, "nfc: failed to find the client\n");
|
||||
ret = -ENOTTY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
cl = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY);
|
||||
if (IS_ERR(cl)) {
|
||||
ret = PTR_ERR(cl);
|
||||
goto err;
|
||||
}
|
||||
|
||||
cl->me_client_id = me_cl->client_id;
|
||||
cl->cl_uuid = me_cl->props.protocol_name;
|
||||
mei_me_cl_put(me_cl);
|
||||
me_cl = NULL;
|
||||
|
||||
list_add_tail(&cl->device_link, &dev->device_list);
|
||||
|
||||
ndev->cl = cl;
|
||||
|
@ -555,7 +548,6 @@ int mei_nfc_host_init(struct mei_device *dev)
|
|||
return 0;
|
||||
|
||||
err:
|
||||
mei_me_cl_put(me_cl);
|
||||
mei_nfc_free(ndev);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -50,15 +50,15 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
|
|||
* mei_wd_host_init - connect to the watchdog client
|
||||
*
|
||||
* @dev: the device structure
|
||||
* @me_cl: me client
|
||||
*
|
||||
* Return: -ENOTTY if wd client cannot be found
|
||||
* -EIO if write has failed
|
||||
* 0 on success
|
||||
*/
|
||||
int mei_wd_host_init(struct mei_device *dev)
|
||||
int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
|
||||
{
|
||||
struct mei_cl *cl = &dev->wd_cl;
|
||||
struct mei_me_client *me_cl;
|
||||
int ret;
|
||||
|
||||
mei_cl_init(cl, dev);
|
||||
|
@ -66,27 +66,13 @@ int mei_wd_host_init(struct mei_device *dev)
|
|||
dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT;
|
||||
dev->wd_state = MEI_WD_IDLE;
|
||||
|
||||
|
||||
/* check for valid client id */
|
||||
me_cl = mei_me_cl_by_uuid(dev, &mei_wd_guid);
|
||||
if (!me_cl) {
|
||||
dev_info(dev->dev, "wd: failed to find the client\n");
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
cl->me_client_id = me_cl->client_id;
|
||||
cl->cl_uuid = me_cl->props.protocol_name;
|
||||
mei_me_cl_put(me_cl);
|
||||
|
||||
ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_info(dev->dev, "wd: failed link client\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mei_cl_connect(cl, NULL);
|
||||
|
||||
ret = mei_cl_connect(cl, me_cl, NULL);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "wd: failed to connect = %d\n", ret);
|
||||
mei_cl_unlink(cl);
|
||||
|
@ -118,7 +104,7 @@ int mei_wd_send(struct mei_device *dev)
|
|||
int ret;
|
||||
|
||||
hdr.host_addr = cl->host_client_id;
|
||||
hdr.me_addr = cl->me_client_id;
|
||||
hdr.me_addr = mei_cl_me_id(cl);
|
||||
hdr.msg_complete = 1;
|
||||
hdr.reserved = 0;
|
||||
hdr.internal = 0;
|
||||
|
|
Loading…
Reference in a new issue