mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 00:21:59 +00:00
mei: support for dynamic clients
HBM version 2.0 and above allows ME clients in the system to register/unregister after the system is fully initialized. Clients may be added or removed after enum_resp message was received 1. To preserve backward compatibility the driver can opt-in to receive client add messages by setting allow_add field in enum_req 2. A new client is added upon reception of MEI_HBM_ADD_CLIENT_REQ_CMD 3. A client is removed in a lazy manner when connection request respond with MEI_HBMS_CLIENT_NOT_FOUND status Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
6009595a66
commit
70ef835c84
@ -154,6 +154,8 @@ static ssize_t mei_dbgfs_read_devstate(struct file *fp, char __user *ubuf,
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "hbm features:\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "\tPG: %01d\n",
|
||||
dev->hbm_f_pg_supported);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "\tDC: %01d\n",
|
||||
dev->hbm_f_dc_supported);
|
||||
}
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "pg: %s, %s\n",
|
||||
|
@ -299,6 +299,7 @@ static int mei_hbm_enum_clients_req(struct mei_device *dev)
|
||||
enum_req = (struct hbm_host_enum_request *)dev->wr_msg.data;
|
||||
memset(enum_req, 0, len);
|
||||
enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
|
||||
enum_req->allow_add = dev->hbm_f_dc_supported;
|
||||
|
||||
ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
|
||||
if (ret) {
|
||||
@ -343,6 +344,64 @@ static int mei_hbm_me_cl_add(struct mei_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_hbm_add_cl_resp - send response to fw on client add request
|
||||
*
|
||||
* @dev: the device structure
|
||||
* @addr: me address
|
||||
* @status: response status
|
||||
*
|
||||
* Return: 0 on success and < 0 on failure
|
||||
*/
|
||||
static int mei_hbm_add_cl_resp(struct mei_device *dev, u8 addr, u8 status)
|
||||
{
|
||||
struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
|
||||
struct hbm_add_client_response *resp;
|
||||
const size_t len = sizeof(struct hbm_add_client_response);
|
||||
int ret;
|
||||
|
||||
dev_dbg(dev->dev, "adding client response\n");
|
||||
|
||||
resp = (struct hbm_add_client_response *)dev->wr_msg.data;
|
||||
|
||||
mei_hbm_hdr(mei_hdr, len);
|
||||
memset(resp, 0, sizeof(struct hbm_add_client_response));
|
||||
|
||||
resp->hbm_cmd = MEI_HBM_ADD_CLIENT_RES_CMD;
|
||||
resp->me_addr = addr;
|
||||
resp->status = status;
|
||||
|
||||
ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
|
||||
if (ret)
|
||||
dev_err(dev->dev, "add client response write failed: ret = %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_hbm_fw_add_cl_req - request from the fw to add a client
|
||||
*
|
||||
* @dev: the device structure
|
||||
* @req: add client request
|
||||
*
|
||||
* Return: 0 on success and < 0 on failure
|
||||
*/
|
||||
static int mei_hbm_fw_add_cl_req(struct mei_device *dev,
|
||||
struct hbm_add_client_request *req)
|
||||
{
|
||||
int ret;
|
||||
u8 status = MEI_HBMS_SUCCESS;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct hbm_add_client_request) !=
|
||||
sizeof(struct hbm_props_response));
|
||||
|
||||
ret = mei_hbm_me_cl_add(dev, (struct hbm_props_response *)req);
|
||||
if (ret)
|
||||
status = !MEI_HBMS_SUCCESS;
|
||||
|
||||
return mei_hbm_add_cl_resp(dev, req->me_addr, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_hbm_prop_req - request property for a single client
|
||||
*
|
||||
@ -610,8 +669,11 @@ static void mei_hbm_cl_connect_res(struct mei_device *dev, struct mei_cl *cl,
|
||||
|
||||
if (rs->status == MEI_CL_CONN_SUCCESS)
|
||||
cl->state = MEI_FILE_CONNECTED;
|
||||
else
|
||||
else {
|
||||
cl->state = MEI_FILE_DISCONNECT_REPLY;
|
||||
if (rs->status == MEI_CL_CONN_NOT_FOUND)
|
||||
mei_me_cl_del(dev, cl->me_cl);
|
||||
}
|
||||
cl->status = mei_cl_conn_status_to_errno(rs->status);
|
||||
}
|
||||
|
||||
@ -709,6 +771,9 @@ static void mei_hbm_config_features(struct mei_device *dev)
|
||||
if (dev->version.major_version == HBM_MAJOR_VERSION_PGI &&
|
||||
dev->version.minor_version >= HBM_MINOR_VERSION_PGI)
|
||||
dev->hbm_f_pg_supported = 1;
|
||||
|
||||
if (dev->version.major_version >= HBM_MAJOR_VERSION_DC)
|
||||
dev->hbm_f_dc_supported = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -740,6 +805,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
|
||||
struct hbm_host_version_response *version_res;
|
||||
struct hbm_props_response *props_res;
|
||||
struct hbm_host_enum_response *enum_res;
|
||||
struct hbm_add_client_request *add_cl_req;
|
||||
int ret;
|
||||
|
||||
struct mei_hbm_cl_cmd *cl_cmd;
|
||||
struct hbm_client_connect_request *disconnect_req;
|
||||
@ -937,6 +1004,29 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
|
||||
return -EIO;
|
||||
}
|
||||
break;
|
||||
|
||||
case MEI_HBM_ADD_CLIENT_REQ_CMD:
|
||||
dev_dbg(dev->dev, "hbm: add client request received\n");
|
||||
/*
|
||||
* after the host receives the enum_resp
|
||||
* message clients may be added or removed
|
||||
*/
|
||||
if (dev->hbm_state <= MEI_HBM_ENUM_CLIENTS &&
|
||||
dev->hbm_state >= MEI_HBM_STOPPED) {
|
||||
dev_err(dev->dev, "hbm: add client: state mismatch, [%d, %d]\n",
|
||||
dev->dev_state, dev->hbm_state);
|
||||
return -EPROTO;
|
||||
}
|
||||
add_cl_req = (struct hbm_add_client_request *)mei_msg;
|
||||
ret = mei_hbm_fw_add_cl_req(dev, add_cl_req);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "hbm: add client: failed to send response %d\n",
|
||||
ret);
|
||||
return -EIO;
|
||||
}
|
||||
dev_dbg(dev->dev, "hbm: add client request processed\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
|
@ -46,6 +46,12 @@
|
||||
#define HBM_MINOR_VERSION_PGI 1
|
||||
#define HBM_MAJOR_VERSION_PGI 1
|
||||
|
||||
/*
|
||||
* MEI version with Dynamic clients support
|
||||
*/
|
||||
#define HBM_MINOR_VERSION_DC 0
|
||||
#define HBM_MAJOR_VERSION_DC 2
|
||||
|
||||
/* Host bus message command opcode */
|
||||
#define MEI_HBM_CMD_OP_MSK 0x7f
|
||||
/* Host bus message command RESPONSE */
|
||||
@ -81,6 +87,8 @@
|
||||
#define MEI_PG_ISOLATION_EXIT_REQ_CMD 0x0b
|
||||
#define MEI_PG_ISOLATION_EXIT_RES_CMD 0x8b
|
||||
|
||||
#define MEI_HBM_ADD_CLIENT_REQ_CMD 0x0f
|
||||
#define MEI_HBM_ADD_CLIENT_RES_CMD 0x8f
|
||||
/*
|
||||
* MEI Stop Reason
|
||||
* used by hbm_host_stop_request.reason
|
||||
@ -213,9 +221,17 @@ struct hbm_me_stop_request {
|
||||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct hbm_host_enum_request - enumeration request from host to fw
|
||||
*
|
||||
* @hbm_cmd: bus message command header
|
||||
* @allow_add: allow dynamic clients add HBM version >= 2.0
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct hbm_host_enum_request {
|
||||
u8 hbm_cmd;
|
||||
u8 reserved[3];
|
||||
u8 allow_add;
|
||||
u8 reserved[2];
|
||||
} __packed;
|
||||
|
||||
struct hbm_host_enum_response {
|
||||
@ -247,6 +263,38 @@ struct hbm_props_response {
|
||||
struct mei_client_properties client_properties;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct hbm_add_client_request - request to add a client
|
||||
* might be sent by fw after enumeration has already completed
|
||||
*
|
||||
* @hbm_cmd: bus message command header
|
||||
* @me_addr: address of the client in ME
|
||||
* @reserved: reserved
|
||||
* @client_properties: client properties
|
||||
*/
|
||||
struct hbm_add_client_request {
|
||||
u8 hbm_cmd;
|
||||
u8 me_addr;
|
||||
u8 reserved[2];
|
||||
struct mei_client_properties client_properties;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct hbm_add_client_response - response to add a client
|
||||
* sent by the host to report client addition status to fw
|
||||
*
|
||||
* @hbm_cmd: bus message command header
|
||||
* @me_addr: address of the client in ME
|
||||
* @status: if HBMS_SUCCESS then the client can now accept connections.
|
||||
* @reserved: reserved
|
||||
*/
|
||||
struct hbm_add_client_response {
|
||||
u8 hbm_cmd;
|
||||
u8 me_addr;
|
||||
u8 status;
|
||||
u8 reserved[1];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct hbm_power_gate - power gate request/response
|
||||
*
|
||||
|
@ -408,6 +408,7 @@ const char *mei_pg_state_str(enum mei_pg_state state);
|
||||
*
|
||||
* @version : HBM protocol version in use
|
||||
* @hbm_f_pg_supported : hbm feature pgi protocol
|
||||
* @hbm_f_dc_supported : hbm feature dynamic clients
|
||||
*
|
||||
* @me_clients_rwsem: rw lock over me_clients list
|
||||
* @me_clients : list of FW clients
|
||||
@ -501,6 +502,7 @@ struct mei_device {
|
||||
|
||||
struct hbm_version version;
|
||||
unsigned int hbm_f_pg_supported:1;
|
||||
unsigned int hbm_f_dc_supported:1;
|
||||
|
||||
struct rw_semaphore me_clients_rwsem;
|
||||
struct list_head me_clients;
|
||||
|
Loading…
Reference in New Issue
Block a user