2019-03-12 00:10:41 +02:00
// SPDX-License-Identifier: GPL-2.0
2012-12-25 19:06:07 +02:00
/*
2020-07-23 17:59:22 +03:00
* Copyright ( c ) 2003 - 2020 , Intel Corporation . All rights reserved .
2012-12-25 19:06:07 +02:00
* Intel Management Engine Interface ( Intel MEI ) Linux driver
*/
2014-03-18 22:51:55 +02:00
# include <linux/export.h>
2012-12-25 19:06:07 +02:00
# include <linux/sched.h>
# include <linux/wait.h>
2014-03-18 22:52:02 +02:00
# include <linux/pm_runtime.h>
2014-09-29 16:31:46 +03:00
# include <linux/slab.h>
# include <linux/mei.h>
2012-12-25 19:06:07 +02:00
# include "mei_dev.h"
2013-01-08 23:07:12 +02:00
# include "hbm.h"
2014-02-17 15:13:23 +02:00
# include "client.h"
2012-12-25 19:06:07 +02:00
2014-08-21 14:29:16 +03:00
static const char * mei_hbm_status_str ( enum mei_hbm_status status )
{
# define MEI_HBM_STATUS(status) case MEI_HBMS_##status: return #status
switch ( status ) {
MEI_HBM_STATUS ( SUCCESS ) ;
MEI_HBM_STATUS ( CLIENT_NOT_FOUND ) ;
MEI_HBM_STATUS ( ALREADY_EXISTS ) ;
MEI_HBM_STATUS ( REJECTED ) ;
MEI_HBM_STATUS ( INVALID_PARAMETER ) ;
MEI_HBM_STATUS ( NOT_ALLOWED ) ;
MEI_HBM_STATUS ( ALREADY_STARTED ) ;
MEI_HBM_STATUS ( NOT_STARTED ) ;
default : return " unknown " ;
}
# undef MEI_HBM_STATUS
} ;
2014-02-17 15:13:20 +02:00
static const char * mei_cl_conn_status_str ( enum mei_cl_connect_status status )
{
# define MEI_CL_CS(status) case MEI_CL_CONN_##status: return #status
switch ( status ) {
MEI_CL_CS ( SUCCESS ) ;
MEI_CL_CS ( NOT_FOUND ) ;
MEI_CL_CS ( ALREADY_STARTED ) ;
MEI_CL_CS ( OUT_OF_RESOURCES ) ;
MEI_CL_CS ( MESSAGE_SMALL ) ;
2015-07-29 14:59:33 +03:00
MEI_CL_CS ( NOT_ALLOWED ) ;
2014-02-17 15:13:20 +02:00
default : return " unknown " ;
}
# undef MEI_CL_CCS
}
2014-09-29 16:31:33 +03:00
const char * mei_hbm_state_str ( enum mei_hbm_state state )
{
# define MEI_HBM_STATE(state) case MEI_HBM_##state: return #state
switch ( state ) {
MEI_HBM_STATE ( IDLE ) ;
MEI_HBM_STATE ( STARTING ) ;
MEI_HBM_STATE ( STARTED ) ;
2018-11-22 13:11:37 +02:00
MEI_HBM_STATE ( DR_SETUP ) ;
2014-09-29 16:31:33 +03:00
MEI_HBM_STATE ( ENUM_CLIENTS ) ;
MEI_HBM_STATE ( CLIENT_PROPERTIES ) ;
MEI_HBM_STATE ( STOPPED ) ;
default :
return " unknown " ;
}
# undef MEI_HBM_STATE
}
2014-02-17 15:13:20 +02:00
/**
* mei_cl_conn_status_to_errno - convert client connect response
* status to error code
*
* @ status : client connect response status
*
2014-09-29 16:31:49 +03:00
* Return : corresponding error code
2014-02-17 15:13:20 +02:00
*/
static int mei_cl_conn_status_to_errno ( enum mei_cl_connect_status status )
{
switch ( status ) {
case MEI_CL_CONN_SUCCESS : return 0 ;
case MEI_CL_CONN_NOT_FOUND : return - ENOTTY ;
case MEI_CL_CONN_ALREADY_STARTED : return - EBUSY ;
case MEI_CL_CONN_OUT_OF_RESOURCES : return - EBUSY ;
case MEI_CL_CONN_MESSAGE_SMALL : return - EINVAL ;
2015-07-29 14:59:33 +03:00
case MEI_CL_CONN_NOT_ALLOWED : return - EBUSY ;
2014-02-17 15:13:20 +02:00
default : return - EINVAL ;
}
}
2018-07-31 09:35:33 +03:00
/**
* mei_hbm_write_message - wrapper for sending hbm messages .
*
* @ dev : mei device
* @ hdr : mei header
* @ data : payload
*/
static inline int mei_hbm_write_message ( struct mei_device * dev ,
struct mei_msg_hdr * hdr ,
const void * data )
{
return mei_write_message ( dev , hdr , sizeof ( * hdr ) , data , hdr - > length ) ;
}
2014-05-07 16:51:28 +03:00
/**
* mei_hbm_idle - set hbm to idle state
*
* @ dev : the device structure
*/
void mei_hbm_idle ( struct mei_device * dev )
{
dev - > init_clients_timer = 0 ;
dev - > hbm_state = MEI_HBM_IDLE ;
}
2014-08-21 14:29:14 +03:00
/**
* mei_hbm_reset - reset hbm counters and book keeping data structurs
*
* @ dev : the device structure
*/
void mei_hbm_reset ( struct mei_device * dev )
{
2015-01-11 00:07:16 +02:00
mei_me_cl_rm_all ( dev ) ;
2014-05-07 16:51:28 +03:00
mei_hbm_idle ( dev ) ;
}
2014-09-29 16:31:40 +03:00
/**
* mei_hbm_hdr - construct hbm header
*
2020-08-18 14:51:38 +03:00
* @ mei_hdr : hbm header
2014-09-29 16:31:40 +03:00
* @ length : payload length
*/
2020-08-18 14:51:38 +03:00
static inline void mei_hbm_hdr ( struct mei_msg_hdr * mei_hdr , size_t length )
2014-09-29 16:31:40 +03:00
{
2020-08-18 14:51:38 +03:00
memset ( mei_hdr , 0 , sizeof ( * mei_hdr ) ) ;
mei_hdr - > length = length ;
mei_hdr - > msg_complete = 1 ;
2014-09-29 16:31:40 +03:00
}
2012-12-25 19:06:09 +02:00
/**
* mei_hbm_cl_hdr - construct client hbm header
2013-04-05 01:05:05 +09:00
*
2014-08-21 14:29:11 +03:00
* @ cl : client
2012-12-25 19:06:09 +02:00
* @ hbm_cmd : host bus message command
* @ buf : buffer for cl header
* @ len : buffer length
*/
static inline
void mei_hbm_cl_hdr ( struct mei_cl * cl , u8 hbm_cmd , void * buf , size_t len )
{
struct mei_hbm_cl_cmd * cmd = buf ;
memset ( cmd , 0 , len ) ;
cmd - > hbm_cmd = hbm_cmd ;
2015-05-04 09:43:56 +03:00
cmd - > host_addr = mei_cl_host_addr ( cl ) ;
2015-05-04 09:43:54 +03:00
cmd - > me_addr = mei_cl_me_id ( cl ) ;
2012-12-25 19:06:09 +02:00
}
2014-08-21 14:29:11 +03:00
/**
* mei_hbm_cl_write - write simple hbm client message
*
* @ dev : the device structure
* @ cl : client
* @ hbm_cmd : host bus message command
2016-06-16 17:58:53 +03:00
* @ buf : message buffer
2014-08-21 14:29:11 +03:00
* @ len : buffer length
2014-09-29 16:31:50 +03:00
*
* Return : 0 on success , < 0 on failure .
2014-08-21 14:29:11 +03:00
*/
2017-03-20 15:04:04 +02:00
static inline int mei_hbm_cl_write ( struct mei_device * dev , struct mei_cl * cl ,
u8 hbm_cmd , void * buf , size_t len )
2014-08-21 14:29:11 +03:00
{
2016-05-09 00:07:47 -04:00
struct mei_msg_hdr mei_hdr ;
2014-08-21 14:29:11 +03:00
2016-05-09 00:07:47 -04:00
mei_hbm_hdr ( & mei_hdr , len ) ;
mei_hbm_cl_hdr ( cl , hbm_cmd , buf , len ) ;
2014-08-21 14:29:11 +03:00
2018-07-31 09:35:33 +03:00
return mei_hbm_write_message ( dev , & mei_hdr , buf ) ;
2014-08-21 14:29:11 +03:00
}
2012-12-25 19:06:09 +02:00
/**
2014-08-21 14:29:20 +03:00
* mei_hbm_cl_addr_equal - check if the client ' s and
* the message address match
2012-12-25 19:06:09 +02:00
*
2014-08-21 14:29:20 +03:00
* @ cl : client
* @ cmd : hbm client message
2012-12-25 19:06:09 +02:00
*
2014-09-29 16:31:49 +03:00
* Return : true if addresses are the same
2012-12-25 19:06:09 +02:00
*/
static inline
2014-08-21 14:29:20 +03:00
bool mei_hbm_cl_addr_equal ( struct mei_cl * cl , struct mei_hbm_cl_cmd * cmd )
2012-12-25 19:06:09 +02:00
{
2015-05-04 09:43:56 +03:00
return mei_cl_host_addr ( cl ) = = cmd - > host_addr & &
2015-05-04 09:43:54 +03:00
mei_cl_me_id ( cl ) = = cmd - > me_addr ;
2012-12-25 19:06:09 +02:00
}
2014-08-21 14:29:20 +03:00
/**
* mei_hbm_cl_find_by_cmd - find recipient client
*
* @ dev : the device structure
* @ buf : a buffer with hbm cl command
*
2014-09-29 16:31:49 +03:00
* Return : the recipient client or NULL if not found
2014-08-21 14:29:20 +03:00
*/
static inline
struct mei_cl * mei_hbm_cl_find_by_cmd ( struct mei_device * dev , void * buf )
{
struct mei_hbm_cl_cmd * cmd = ( struct mei_hbm_cl_cmd * ) buf ;
struct mei_cl * cl ;
list_for_each_entry ( cl , & dev - > file_list , link )
if ( mei_hbm_cl_addr_equal ( cl , cmd ) )
return cl ;
return NULL ;
}
2014-08-21 14:29:19 +03:00
/**
* mei_hbm_start_wait - wait for start response message .
*
* @ dev : the device structure
*
2014-09-29 16:31:49 +03:00
* Return : 0 on success and < 0 on failure
2014-08-21 14:29:19 +03:00
*/
2013-04-18 23:03:48 +03:00
int mei_hbm_start_wait ( struct mei_device * dev )
{
int ret ;
2014-08-21 14:29:19 +03:00
if ( dev - > hbm_state > MEI_HBM_STARTING )
2013-04-18 23:03:48 +03:00
return 0 ;
mutex_unlock ( & dev - > device_lock ) ;
2014-08-21 14:29:19 +03:00
ret = wait_event_timeout ( dev - > wait_hbm_start ,
dev - > hbm_state ! = MEI_HBM_STARTING ,
2014-01-14 23:10:10 +02:00
mei_secs_to_jiffies ( MEI_HBM_TIMEOUT ) ) ;
2013-04-18 23:03:48 +03:00
mutex_lock ( & dev - > device_lock ) ;
2014-08-21 14:29:19 +03:00
if ( ret = = 0 & & ( dev - > hbm_state < = MEI_HBM_STARTING ) ) {
2013-04-18 23:03:48 +03:00
dev - > hbm_state = MEI_HBM_IDLE ;
2014-09-29 16:31:42 +03:00
dev_err ( dev - > dev , " waiting for mei start failed \n " ) ;
2014-02-19 17:35:49 +02:00
return - ETIME ;
2013-04-18 23:03:48 +03:00
}
return 0 ;
}
2012-12-25 19:06:07 +02:00
/**
2012-12-25 19:06:11 +02:00
* mei_hbm_start_req - sends start request message .
2012-12-25 19:06:07 +02:00
*
* @ dev : the device structure
2014-01-08 20:19:21 +02:00
*
2014-09-29 16:31:49 +03:00
* Return : 0 on success and < 0 on failure
2012-12-25 19:06:07 +02:00
*/
2013-04-18 23:03:48 +03:00
int mei_hbm_start_req ( struct mei_device * dev )
2012-12-25 19:06:07 +02:00
{
2016-05-09 00:07:47 -04:00
struct mei_msg_hdr mei_hdr ;
2020-07-23 17:59:22 +03:00
struct hbm_host_version_request req ;
2014-01-08 20:19:21 +02:00
int ret ;
2012-12-25 19:06:07 +02:00
2014-08-21 14:29:13 +03:00
mei_hbm_reset ( dev ) ;
2020-07-23 17:59:22 +03:00
mei_hbm_hdr ( & mei_hdr , sizeof ( req ) ) ;
2012-12-25 19:06:07 +02:00
/* host start message */
2020-07-23 17:59:22 +03:00
memset ( & req , 0 , sizeof ( req ) ) ;
req . hbm_cmd = HOST_START_REQ_CMD ;
req . host_version . major_version = HBM_MAJOR_VERSION ;
req . host_version . minor_version = HBM_MINOR_VERSION ;
2012-12-25 19:06:07 +02:00
2013-04-18 23:03:48 +03:00
dev - > hbm_state = MEI_HBM_IDLE ;
2020-07-23 17:59:22 +03:00
ret = mei_hbm_write_message ( dev , & mei_hdr , & req ) ;
2014-01-08 20:19:21 +02:00
if ( ret ) {
2014-09-29 16:31:42 +03:00
dev_err ( dev - > dev , " version message write failed: ret = %d \n " ,
2014-01-08 20:19:21 +02:00
ret ) ;
return ret ;
2012-12-25 19:06:07 +02:00
}
2014-01-08 20:19:21 +02:00
2014-08-21 14:29:19 +03:00
dev - > hbm_state = MEI_HBM_STARTING ;
2012-12-25 19:06:07 +02:00
dev - > init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT ;
2016-09-25 13:25:31 +03:00
mei_schedule_stall_timer ( dev ) ;
2013-04-18 23:03:48 +03:00
return 0 ;
2012-12-25 19:06:07 +02:00
}
2018-11-22 13:11:37 +02:00
/**
* mei_hbm_dma_setup_req ( ) - setup DMA request
* @ dev : the device structure
*
* Return : 0 on success and < 0 on failure
*/
static int mei_hbm_dma_setup_req ( struct mei_device * dev )
{
struct mei_msg_hdr mei_hdr ;
struct hbm_dma_setup_request req ;
unsigned int i ;
int ret ;
2020-07-23 17:59:22 +03:00
mei_hbm_hdr ( & mei_hdr , sizeof ( req ) ) ;
2018-11-22 13:11:37 +02:00
2020-07-23 17:59:22 +03:00
memset ( & req , 0 , sizeof ( req ) ) ;
2018-11-22 13:11:37 +02:00
req . hbm_cmd = MEI_HBM_DMA_SETUP_REQ_CMD ;
for ( i = 0 ; i < DMA_DSCR_NUM ; i + + ) {
phys_addr_t paddr ;
paddr = dev - > dr_dscr [ i ] . daddr ;
req . dma_dscr [ i ] . addr_hi = upper_32_bits ( paddr ) ;
req . dma_dscr [ i ] . addr_lo = lower_32_bits ( paddr ) ;
req . dma_dscr [ i ] . size = dev - > dr_dscr [ i ] . size ;
}
2018-11-22 13:11:38 +02:00
mei_dma_ring_reset ( dev ) ;
2018-11-22 13:11:37 +02:00
ret = mei_hbm_write_message ( dev , & mei_hdr , & req ) ;
if ( ret ) {
dev_err ( dev - > dev , " dma setup request write failed: ret = %d. \n " ,
ret ) ;
return ret ;
}
dev - > hbm_state = MEI_HBM_DR_SETUP ;
dev - > init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT ;
mei_schedule_stall_timer ( dev ) ;
return 0 ;
}
2020-08-18 14:51:35 +03:00
/**
* mei_hbm_capabilities_req - request capabilities
*
* @ dev : the device structure
*
* Return : 0 on success and < 0 on failure
*/
static int mei_hbm_capabilities_req ( struct mei_device * dev )
{
struct mei_msg_hdr mei_hdr ;
struct hbm_capability_request req ;
int ret ;
mei_hbm_hdr ( & mei_hdr , sizeof ( req ) ) ;
memset ( & req , 0 , sizeof ( req ) ) ;
req . hbm_cmd = MEI_HBM_CAPABILITIES_REQ_CMD ;
2020-08-18 14:51:36 +03:00
if ( dev - > hbm_f_vt_supported )
req . capability_requested [ 0 ] = HBM_CAP_VT ;
2020-08-18 14:51:35 +03:00
ret = mei_hbm_write_message ( dev , & mei_hdr , & req ) ;
if ( ret ) {
dev_err ( dev - > dev ,
" capabilities request write failed: ret = %d. \n " , ret ) ;
return ret ;
}
dev - > hbm_state = MEI_HBM_CAP_SETUP ;
dev - > init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT ;
mei_schedule_stall_timer ( dev ) ;
return 0 ;
}
2015-10-13 15:02:39 +03:00
/**
2012-12-25 19:06:11 +02:00
* mei_hbm_enum_clients_req - sends enumeration client request message .
2012-12-25 19:06:07 +02:00
*
* @ dev : the device structure
*
2014-09-29 16:31:49 +03:00
* Return : 0 on success and < 0 on failure
2012-12-25 19:06:07 +02:00
*/
2014-01-08 20:19:21 +02:00
static int mei_hbm_enum_clients_req ( struct mei_device * dev )
2012-12-25 19:06:07 +02:00
{
2016-05-09 00:07:47 -04:00
struct mei_msg_hdr mei_hdr ;
2020-07-23 17:59:22 +03:00
struct hbm_host_enum_request req ;
2014-01-08 20:19:21 +02:00
int ret ;
2012-12-25 19:06:07 +02:00
/* enumerate clients */
2020-07-23 17:59:22 +03:00
mei_hbm_hdr ( & mei_hdr , sizeof ( req ) ) ;
2012-12-25 19:06:07 +02:00
2020-07-23 17:59:22 +03:00
memset ( & req , 0 , sizeof ( req ) ) ;
req . hbm_cmd = HOST_ENUM_REQ_CMD ;
req . flags | = dev - > hbm_f_dc_supported ? MEI_HBM_ENUM_F_ALLOW_ADD : 0 ;
req . flags | = dev - > hbm_f_ie_supported ?
2016-05-09 00:07:47 -04:00
MEI_HBM_ENUM_F_IMMEDIATE_ENUM : 0 ;
2012-12-25 19:06:07 +02:00
2020-07-23 17:59:22 +03:00
ret = mei_hbm_write_message ( dev , & mei_hdr , & req ) ;
2014-01-08 20:19:21 +02:00
if ( ret ) {
2014-09-29 16:31:42 +03:00
dev_err ( dev - > dev , " enumeration request write failed: ret = %d. \n " ,
2014-01-08 20:19:21 +02:00
ret ) ;
return ret ;
2012-12-25 19:06:07 +02:00
}
2013-04-18 23:03:48 +03:00
dev - > hbm_state = MEI_HBM_ENUM_CLIENTS ;
2012-12-25 19:06:07 +02:00
dev - > init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT ;
2016-09-25 13:25:31 +03:00
mei_schedule_stall_timer ( dev ) ;
2014-01-08 20:19:21 +02:00
return 0 ;
2012-12-25 19:06:07 +02:00
}
2015-10-13 15:02:39 +03:00
/**
2014-08-21 14:29:13 +03:00
* mei_hbm_me_cl_add - add new me client to the list
*
* @ dev : the device structure
* @ res : hbm property response
*
2014-09-29 16:31:49 +03:00
* Return : 0 on success and - ENOMEM on allocation failure
2014-08-21 14:29:13 +03:00
*/
static int mei_hbm_me_cl_add ( struct mei_device * dev ,
struct hbm_props_response * res )
{
struct mei_me_client * me_cl ;
2015-01-11 00:07:16 +02:00
const uuid_le * uuid = & res - > client_properties . protocol_name ;
mei_me_cl_rm_by_uuid ( dev , uuid ) ;
2014-08-21 14:29:13 +03:00
2020-07-23 17:59:22 +03:00
me_cl = kzalloc ( sizeof ( * me_cl ) , GFP_KERNEL ) ;
2014-08-21 14:29:13 +03:00
if ( ! me_cl )
return - ENOMEM ;
2015-01-11 00:07:16 +02:00
mei_me_cl_init ( me_cl ) ;
2014-08-21 14:29:13 +03:00
me_cl - > props = res - > client_properties ;
me_cl - > client_id = res - > me_addr ;
2016-07-26 01:06:04 +03:00
me_cl - > tx_flow_ctrl_creds = 0 ;
2014-08-21 14:29:13 +03:00
2015-02-10 10:39:31 +02:00
mei_me_cl_add ( dev , me_cl ) ;
2014-08-21 14:29:13 +03:00
return 0 ;
}
2015-07-23 21:37:12 +03:00
/**
* 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 )
{
2016-05-09 00:07:47 -04:00
struct mei_msg_hdr mei_hdr ;
struct hbm_add_client_response resp ;
2015-07-23 21:37:12 +03:00
int ret ;
dev_dbg ( dev - > dev , " adding client response \n " ) ;
2020-07-23 17:59:22 +03:00
mei_hbm_hdr ( & mei_hdr , sizeof ( resp ) ) ;
2015-07-23 21:37:12 +03:00
2020-07-23 17:59:22 +03:00
memset ( & resp , 0 , sizeof ( resp ) ) ;
2016-05-09 00:07:47 -04:00
resp . hbm_cmd = MEI_HBM_ADD_CLIENT_RES_CMD ;
resp . me_addr = addr ;
resp . status = status ;
2015-07-23 21:37:12 +03:00
2018-07-31 09:35:33 +03:00
ret = mei_hbm_write_message ( dev , & mei_hdr , & resp ) ;
2015-07-23 21:37:12 +03:00
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 ;
2016-02-07 23:35:41 +02:00
if ( dev - > dev_state = = MEI_DEV_ENABLED )
schedule_work ( & dev - > bus_rescan_work ) ;
2015-07-23 21:37:12 +03:00
return mei_hbm_add_cl_resp ( dev , req - > me_addr , status ) ;
}
2015-07-26 09:54:16 +03:00
/**
* mei_hbm_cl_notify_req - send notification request
*
* @ dev : the device structure
* @ cl : a client to disconnect from
* @ start : true for start false for stop
*
* Return : 0 on success and - EIO on write failure
*/
int mei_hbm_cl_notify_req ( struct mei_device * dev ,
struct mei_cl * cl , u8 start )
{
2016-05-09 00:07:47 -04:00
struct mei_msg_hdr mei_hdr ;
struct hbm_notification_request req ;
2015-07-26 09:54:16 +03:00
int ret ;
2020-07-23 17:59:22 +03:00
mei_hbm_hdr ( & mei_hdr , sizeof ( req ) ) ;
mei_hbm_cl_hdr ( cl , MEI_HBM_NOTIFY_REQ_CMD , & req , sizeof ( req ) ) ;
2015-07-26 09:54:16 +03:00
2016-05-09 00:07:47 -04:00
req . start = start ;
2015-07-26 09:54:16 +03:00
2018-07-31 09:35:33 +03:00
ret = mei_hbm_write_message ( dev , & mei_hdr , & req ) ;
2015-07-26 09:54:16 +03:00
if ( ret )
dev_err ( dev - > dev , " notify request failed: ret = %d \n " , ret ) ;
return ret ;
}
/**
* notify_res_to_fop - convert notification response to the proper
* notification FOP
*
* @ cmd : client notification start response command
*
* Return : MEI_FOP_NOTIFY_START or MEI_FOP_NOTIFY_STOP ;
*/
static inline enum mei_cb_file_ops notify_res_to_fop ( struct mei_hbm_cl_cmd * cmd )
{
struct hbm_notification_response * rs =
( struct hbm_notification_response * ) cmd ;
2015-07-26 09:54:18 +03:00
return mei_cl_notify_req2fop ( rs - > start ) ;
2015-07-26 09:54:16 +03:00
}
/**
* mei_hbm_cl_notify_start_res - update the client state according
* notify start response
*
* @ dev : the device structure
* @ cl : mei host client
* @ cmd : client notification start response command
*/
static void mei_hbm_cl_notify_start_res ( struct mei_device * dev ,
struct mei_cl * cl ,
struct mei_hbm_cl_cmd * cmd )
{
struct hbm_notification_response * rs =
( struct hbm_notification_response * ) cmd ;
cl_dbg ( dev , cl , " hbm: notify start response status=%d \n " , rs - > status ) ;
if ( rs - > status = = MEI_HBMS_SUCCESS | |
rs - > status = = MEI_HBMS_ALREADY_STARTED ) {
cl - > notify_en = true ;
cl - > status = 0 ;
} else {
cl - > status = - EINVAL ;
}
}
/**
* mei_hbm_cl_notify_stop_res - update the client state according
* notify stop response
*
* @ dev : the device structure
* @ cl : mei host client
* @ cmd : client notification stop response command
*/
static void mei_hbm_cl_notify_stop_res ( struct mei_device * dev ,
struct mei_cl * cl ,
struct mei_hbm_cl_cmd * cmd )
{
struct hbm_notification_response * rs =
( struct hbm_notification_response * ) cmd ;
cl_dbg ( dev , cl , " hbm: notify stop response status=%d \n " , rs - > status ) ;
if ( rs - > status = = MEI_HBMS_SUCCESS | |
rs - > status = = MEI_HBMS_NOT_STARTED ) {
cl - > notify_en = false ;
cl - > status = 0 ;
} else {
/* TODO: spec is not clear yet about other possible issues */
cl - > status = - EINVAL ;
}
}
/**
* mei_hbm_cl_notify - signal notification event
*
* @ dev : the device structure
* @ cmd : notification client message
*/
static void mei_hbm_cl_notify ( struct mei_device * dev ,
struct mei_hbm_cl_cmd * cmd )
{
struct mei_cl * cl ;
cl = mei_hbm_cl_find_by_cmd ( dev , cmd ) ;
2015-07-26 09:54:22 +03:00
if ( cl )
mei_cl_notify ( cl ) ;
2015-07-26 09:54:16 +03:00
}
2012-12-25 19:06:11 +02:00
/**
2013-04-05 01:05:05 +09:00
* mei_hbm_prop_req - request property for a single client
2012-12-25 19:06:11 +02:00
*
* @ dev : the device structure
2016-04-17 12:16:02 -04:00
* @ start_idx : client index to start search
2012-12-25 19:06:11 +02:00
*
2014-09-29 16:31:49 +03:00
* Return : 0 on success and < 0 on failure
2012-12-25 19:06:11 +02:00
*/
2016-04-17 12:16:02 -04:00
static int mei_hbm_prop_req ( struct mei_device * dev , unsigned long start_idx )
2012-12-25 19:06:07 +02:00
{
2016-05-09 00:07:47 -04:00
struct mei_msg_hdr mei_hdr ;
2020-07-23 17:59:22 +03:00
struct hbm_props_request req ;
2016-04-17 12:16:02 -04:00
unsigned long addr ;
2014-01-08 20:19:21 +02:00
int ret ;
2012-12-25 19:06:07 +02:00
2016-04-17 12:16:02 -04:00
addr = find_next_bit ( dev - > me_clients_map , MEI_CLIENTS_MAX , start_idx ) ;
2012-12-25 19:06:07 +02:00
/* We got all client properties */
2016-04-17 12:16:02 -04:00
if ( addr = = MEI_CLIENTS_MAX ) {
2013-04-18 23:03:48 +03:00
dev - > hbm_state = MEI_HBM_STARTED ;
2016-02-07 23:35:43 +02:00
mei_host_client_init ( dev ) ;
2012-12-25 19:06:07 +02:00
return 0 ;
}
2020-07-23 17:59:22 +03:00
mei_hbm_hdr ( & mei_hdr , sizeof ( req ) ) ;
2012-12-25 19:06:07 +02:00
2020-07-23 17:59:22 +03:00
memset ( & req , 0 , sizeof ( req ) ) ;
2012-12-25 19:06:07 +02:00
2020-07-23 17:59:22 +03:00
req . hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD ;
req . me_addr = addr ;
2012-12-25 19:06:07 +02:00
2020-07-23 17:59:22 +03:00
ret = mei_hbm_write_message ( dev , & mei_hdr , & req ) ;
2014-01-08 20:19:21 +02:00
if ( ret ) {
2014-09-29 16:31:42 +03:00
dev_err ( dev - > dev , " properties request write failed: ret = %d \n " ,
2014-01-08 20:19:21 +02:00
ret ) ;
return ret ;
2012-12-25 19:06:07 +02:00
}
dev - > init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT ;
2016-09-25 13:25:31 +03:00
mei_schedule_stall_timer ( dev ) ;
2012-12-25 19:06:07 +02:00
return 0 ;
}
2015-10-13 15:02:39 +03:00
/**
2014-03-18 22:51:55 +02:00
* mei_hbm_pg - sends pg command
*
* @ dev : the device structure
* @ pg_cmd : the pg command code
*
2014-09-29 16:31:49 +03:00
* Return : - EIO on write failure
2014-08-21 14:29:21 +03:00
* - EOPNOTSUPP if the operation is not supported by the protocol
2014-03-18 22:51:55 +02:00
*/
int mei_hbm_pg ( struct mei_device * dev , u8 pg_cmd )
{
2016-05-09 00:07:47 -04:00
struct mei_msg_hdr mei_hdr ;
struct hbm_power_gate req ;
2014-03-18 22:51:55 +02:00
int ret ;
2014-08-21 14:29:21 +03:00
if ( ! dev - > hbm_f_pg_supported )
return - EOPNOTSUPP ;
2020-07-23 17:59:22 +03:00
mei_hbm_hdr ( & mei_hdr , sizeof ( req ) ) ;
2014-03-18 22:51:55 +02:00
2020-07-23 17:59:22 +03:00
memset ( & req , 0 , sizeof ( req ) ) ;
2016-05-09 00:07:47 -04:00
req . hbm_cmd = pg_cmd ;
2014-03-18 22:51:55 +02:00
2018-07-31 09:35:33 +03:00
ret = mei_hbm_write_message ( dev , & mei_hdr , & req ) ;
2014-03-18 22:51:55 +02:00
if ( ret )
2014-09-29 16:31:42 +03:00
dev_err ( dev - > dev , " power gate command write failed. \n " ) ;
2014-03-18 22:51:55 +02:00
return ret ;
}
EXPORT_SYMBOL_GPL ( mei_hbm_pg ) ;
2012-12-25 19:06:10 +02:00
/**
2014-02-12 21:41:52 +02:00
* mei_hbm_stop_req - send stop request message
2012-12-25 19:06:10 +02:00
*
2014-09-29 16:31:49 +03:00
* @ dev : mei device
2014-02-12 21:41:52 +02:00
*
2014-09-29 16:31:49 +03:00
* Return : - EIO on write failure
2012-12-25 19:06:10 +02:00
*/
2014-02-12 21:41:52 +02:00
static int mei_hbm_stop_req ( struct mei_device * dev )
2012-12-25 19:06:10 +02:00
{
2016-05-09 00:07:47 -04:00
struct mei_msg_hdr mei_hdr ;
struct hbm_host_stop_request req ;
2012-12-25 19:06:10 +02:00
2020-07-23 17:59:22 +03:00
mei_hbm_hdr ( & mei_hdr , sizeof ( req ) ) ;
2012-12-25 19:06:10 +02:00
2020-07-23 17:59:22 +03:00
memset ( & req , 0 , sizeof ( req ) ) ;
2016-05-09 00:07:47 -04:00
req . hbm_cmd = HOST_STOP_REQ_CMD ;
req . reason = DRIVER_STOP_REQUEST ;
2014-02-12 21:41:52 +02:00
2018-07-31 09:35:33 +03:00
return mei_hbm_write_message ( dev , & mei_hdr , & req ) ;
2012-12-25 19:06:10 +02:00
}
2012-12-25 19:06:07 +02:00
/**
2014-01-08 22:31:46 +02:00
* mei_hbm_cl_flow_control_req - sends flow control request .
2012-12-25 19:06:07 +02:00
*
* @ dev : the device structure
2012-12-25 19:06:11 +02:00
* @ cl : client info
2012-12-25 19:06:07 +02:00
*
2014-09-29 16:31:49 +03:00
* Return : - EIO on write failure
2012-12-25 19:06:07 +02:00
*/
2012-12-25 19:06:11 +02:00
int mei_hbm_cl_flow_control_req ( struct mei_device * dev , struct mei_cl * cl )
2012-12-25 19:06:07 +02:00
{
2017-03-20 15:04:04 +02:00
struct hbm_flow_control req ;
2014-09-29 16:31:37 +03:00
2014-03-16 14:35:55 +02:00
cl_dbg ( dev , cl , " sending flow control \n " ) ;
2017-03-20 15:04:04 +02:00
return mei_hbm_cl_write ( dev , cl , MEI_FLOW_CONTROL_CMD ,
& req , sizeof ( req ) ) ;
2012-12-25 19:06:07 +02:00
}
2012-12-25 19:06:12 +02:00
/**
2016-07-26 01:06:04 +03:00
* mei_hbm_add_single_tx_flow_ctrl_creds - adds single buffer credentials .
2012-12-25 19:06:12 +02:00
*
2013-04-05 01:05:05 +09:00
* @ dev : the device structure
2016-07-26 01:06:04 +03:00
* @ fctrl : flow control response bus message
2014-02-17 15:13:23 +02:00
*
2014-09-29 16:31:49 +03:00
* Return : 0 on success , < 0 otherwise
2012-12-25 19:06:12 +02:00
*/
2016-07-26 01:06:04 +03:00
static int mei_hbm_add_single_tx_flow_ctrl_creds ( struct mei_device * dev ,
struct hbm_flow_control * fctrl )
2012-12-25 19:06:12 +02:00
{
2014-02-17 15:13:23 +02:00
struct mei_me_client * me_cl ;
2015-01-11 00:07:16 +02:00
int rets ;
2014-02-17 15:13:23 +02:00
2016-07-26 01:06:04 +03:00
me_cl = mei_me_cl_by_id ( dev , fctrl - > me_addr ) ;
2014-08-24 12:08:55 +03:00
if ( ! me_cl ) {
2016-07-26 01:06:04 +03:00
dev_err ( dev - > dev , " no such me client %d \n " , fctrl - > me_addr ) ;
2014-08-24 12:08:55 +03:00
return - ENOENT ;
2014-02-17 15:13:23 +02:00
}
2015-01-11 00:07:16 +02:00
if ( WARN_ON ( me_cl - > props . single_recv_buf = = 0 ) ) {
rets = - EINVAL ;
goto out ;
}
2014-08-24 12:08:55 +03:00
2016-07-26 01:06:04 +03:00
me_cl - > tx_flow_ctrl_creds + + ;
2014-09-29 16:31:42 +03:00
dev_dbg ( dev - > dev , " recv flow ctrl msg ME %d (single) creds = %d. \n " ,
2016-07-26 01:06:04 +03:00
fctrl - > me_addr , me_cl - > tx_flow_ctrl_creds ) ;
2014-02-17 15:13:23 +02:00
2015-01-11 00:07:16 +02:00
rets = 0 ;
out :
mei_me_cl_put ( me_cl ) ;
return rets ;
2012-12-25 19:06:12 +02:00
}
/**
* mei_hbm_cl_flow_control_res - flow control response from me
*
* @ dev : the device structure
2016-07-26 01:06:04 +03:00
* @ fctrl : flow control response bus message
2012-12-25 19:06:12 +02:00
*/
2016-07-26 01:06:04 +03:00
static void mei_hbm_cl_tx_flow_ctrl_creds_res ( struct mei_device * dev ,
struct hbm_flow_control * fctrl )
2012-12-25 19:06:12 +02:00
{
2014-02-17 15:13:25 +02:00
struct mei_cl * cl ;
2012-12-25 19:06:12 +02:00
2016-07-26 01:06:04 +03:00
if ( ! fctrl - > host_addr ) {
2012-12-25 19:06:12 +02:00
/* single receive buffer */
2016-07-26 01:06:04 +03:00
mei_hbm_add_single_tx_flow_ctrl_creds ( dev , fctrl ) ;
2012-12-25 19:06:12 +02:00
return ;
}
2016-07-26 01:06:04 +03:00
cl = mei_hbm_cl_find_by_cmd ( dev , fctrl ) ;
2014-08-21 14:29:20 +03:00
if ( cl ) {
2016-07-26 01:06:04 +03:00
cl - > tx_flow_ctrl_creds + + ;
2014-08-21 14:29:20 +03:00
cl_dbg ( dev , cl , " flow control creds = %d. \n " ,
2016-07-26 01:06:04 +03:00
cl - > tx_flow_ctrl_creds ) ;
2012-12-25 19:06:12 +02:00
}
}
2012-12-25 19:06:07 +02:00
/**
2012-12-25 19:06:11 +02:00
* mei_hbm_cl_disconnect_req - sends disconnect message to fw .
2012-12-25 19:06:07 +02:00
*
* @ dev : the device structure
2012-12-25 19:06:11 +02:00
* @ cl : a client to disconnect from
2012-12-25 19:06:07 +02:00
*
2014-09-29 16:31:49 +03:00
* Return : - EIO on write failure
2012-12-25 19:06:07 +02:00
*/
2012-12-25 19:06:11 +02:00
int mei_hbm_cl_disconnect_req ( struct mei_device * dev , struct mei_cl * cl )
2012-12-25 19:06:07 +02:00
{
2017-03-20 15:04:04 +02:00
struct hbm_client_connect_request req ;
2014-09-29 16:31:37 +03:00
2017-03-20 15:04:04 +02:00
return mei_hbm_cl_write ( dev , cl , CLIENT_DISCONNECT_REQ_CMD ,
& req , sizeof ( req ) ) ;
2012-12-25 19:06:07 +02:00
}
2014-02-12 21:41:52 +02:00
/**
* mei_hbm_cl_disconnect_rsp - sends disconnect respose to the FW
*
* @ dev : the device structure
* @ cl : a client to disconnect from
*
2014-09-29 16:31:49 +03:00
* Return : - EIO on write failure
2014-02-12 21:41:52 +02:00
*/
int mei_hbm_cl_disconnect_rsp ( struct mei_device * dev , struct mei_cl * cl )
{
2017-03-20 15:04:04 +02:00
struct hbm_client_connect_response resp ;
2014-09-29 16:31:37 +03:00
2017-03-20 15:04:04 +02:00
return mei_hbm_cl_write ( dev , cl , CLIENT_DISCONNECT_RES_CMD ,
& resp , sizeof ( resp ) ) ;
2014-02-12 21:41:52 +02:00
}
2012-12-25 19:06:12 +02:00
/**
2014-08-21 14:29:18 +03:00
* mei_hbm_cl_disconnect_res - update the client state according
* disconnect response
2012-12-25 19:06:12 +02:00
*
2014-10-29 23:50:58 +02:00
* @ dev : the device structure
2014-08-21 14:29:18 +03:00
* @ cl : mei host client
* @ cmd : disconnect client response host bus message
2012-12-25 19:06:12 +02:00
*/
2014-10-29 23:50:58 +02:00
static void mei_hbm_cl_disconnect_res ( struct mei_device * dev , struct mei_cl * cl ,
2014-08-21 14:29:18 +03:00
struct mei_hbm_cl_cmd * cmd )
2012-12-25 19:06:12 +02:00
{
2014-08-21 14:29:18 +03:00
struct hbm_client_connect_response * rs =
( struct hbm_client_connect_response * ) cmd ;
2012-12-25 19:06:12 +02:00
2014-10-29 23:50:58 +02:00
cl_dbg ( dev , cl , " hbm: disconnect response status=%d \n " , rs - > status ) ;
2012-12-25 19:06:12 +02:00
2014-08-21 14:29:18 +03:00
if ( rs - > status = = MEI_CL_DISCONN_SUCCESS )
2015-05-04 09:43:52 +03:00
cl - > state = MEI_FILE_DISCONNECT_REPLY ;
2014-08-21 14:29:18 +03:00
cl - > status = 0 ;
2012-12-25 19:06:12 +02:00
}
2012-12-25 19:06:07 +02:00
/**
2012-12-25 19:06:11 +02:00
* mei_hbm_cl_connect_req - send connection request to specific me client
2012-12-25 19:06:07 +02:00
*
* @ dev : the device structure
2012-12-25 19:06:11 +02:00
* @ cl : a client to connect to
2012-12-25 19:06:07 +02:00
*
2014-09-29 16:31:49 +03:00
* Return : - EIO on write failure
2012-12-25 19:06:07 +02:00
*/
2012-12-25 19:06:11 +02:00
int mei_hbm_cl_connect_req ( struct mei_device * dev , struct mei_cl * cl )
2012-12-25 19:06:07 +02:00
{
2017-03-20 15:04:04 +02:00
struct hbm_client_connect_request req ;
2014-09-29 16:31:37 +03:00
2017-03-20 15:04:04 +02:00
return mei_hbm_cl_write ( dev , cl , CLIENT_CONNECT_REQ_CMD ,
& req , sizeof ( req ) ) ;
2012-12-25 19:06:07 +02:00
}
2012-12-25 19:06:12 +02:00
/**
2014-08-21 14:29:18 +03:00
* mei_hbm_cl_connect_res - update the client state according
* connection response
2012-12-25 19:06:12 +02:00
*
2014-10-29 23:50:58 +02:00
* @ dev : the device structure
2014-08-21 14:29:18 +03:00
* @ cl : mei host client
* @ cmd : connect client response host bus message
2012-12-25 19:06:12 +02:00
*/
2014-10-29 23:50:58 +02:00
static void mei_hbm_cl_connect_res ( struct mei_device * dev , struct mei_cl * cl ,
2014-08-21 14:29:18 +03:00
struct mei_hbm_cl_cmd * cmd )
2012-12-25 19:06:12 +02:00
{
2014-08-21 14:29:18 +03:00
struct hbm_client_connect_response * rs =
( struct hbm_client_connect_response * ) cmd ;
2012-12-25 19:06:12 +02:00
2014-10-29 23:50:58 +02:00
cl_dbg ( dev , cl , " hbm: connect response status=%s \n " ,
2014-02-17 15:13:20 +02:00
mei_cl_conn_status_str ( rs - > status ) ) ;
2012-12-25 19:06:12 +02:00
2014-08-21 14:29:18 +03:00
if ( rs - > status = = MEI_CL_CONN_SUCCESS )
cl - > state = MEI_FILE_CONNECTED ;
2015-07-23 21:37:12 +03:00
else {
2015-05-04 09:43:52 +03:00
cl - > state = MEI_FILE_DISCONNECT_REPLY ;
2016-02-07 23:35:41 +02:00
if ( rs - > status = = MEI_CL_CONN_NOT_FOUND ) {
2015-07-23 21:37:12 +03:00
mei_me_cl_del ( dev , cl - > me_cl ) ;
2016-02-07 23:35:41 +02:00
if ( dev - > dev_state = = MEI_DEV_ENABLED )
schedule_work ( & dev - > bus_rescan_work ) ;
}
2015-07-23 21:37:12 +03:00
}
2014-08-21 14:29:18 +03:00
cl - > status = mei_cl_conn_status_to_errno ( rs - > status ) ;
}
/**
* mei_hbm_cl_res - process hbm response received on behalf
* an client
*
* @ dev : the device structure
* @ rs : hbm client message
* @ fop_type : file operation type
*/
static void mei_hbm_cl_res ( struct mei_device * dev ,
struct mei_hbm_cl_cmd * rs ,
enum mei_cb_file_ops fop_type )
{
struct mei_cl * cl ;
struct mei_cl_cb * cb , * next ;
2012-12-25 19:06:12 +02:00
2014-08-21 14:29:18 +03:00
cl = NULL ;
2017-01-27 16:32:45 +02:00
list_for_each_entry_safe ( cb , next , & dev - > ctrl_rd_list , list ) {
2012-12-25 19:06:12 +02:00
2014-02-17 15:13:21 +02:00
cl = cb - > cl ;
2012-12-25 19:06:12 +02:00
2014-08-21 14:29:18 +03:00
if ( cb - > fop_type ! = fop_type )
2014-02-17 15:13:21 +02:00
continue ;
2012-12-25 19:06:12 +02:00
2014-02-17 15:13:21 +02:00
if ( mei_hbm_cl_addr_equal ( cl , rs ) ) {
2015-02-10 10:39:45 +02:00
list_del_init ( & cb - > list ) ;
2014-02-17 15:13:21 +02:00
break ;
2012-12-25 19:06:12 +02:00
}
}
2014-02-17 15:13:21 +02:00
if ( ! cl )
return ;
2014-08-21 14:29:18 +03:00
switch ( fop_type ) {
case MEI_FOP_CONNECT :
2014-10-29 23:50:58 +02:00
mei_hbm_cl_connect_res ( dev , cl , rs ) ;
2014-08-21 14:29:18 +03:00
break ;
case MEI_FOP_DISCONNECT :
2014-10-29 23:50:58 +02:00
mei_hbm_cl_disconnect_res ( dev , cl , rs ) ;
2014-08-21 14:29:18 +03:00
break ;
2015-07-26 09:54:16 +03:00
case MEI_FOP_NOTIFY_START :
mei_hbm_cl_notify_start_res ( dev , cl , rs ) ;
break ;
case MEI_FOP_NOTIFY_STOP :
mei_hbm_cl_notify_stop_res ( dev , cl , rs ) ;
break ;
2014-08-21 14:29:18 +03:00
default :
return ;
}
2014-02-17 15:13:21 +02:00
cl - > timer_count = 0 ;
2014-08-21 14:29:18 +03:00
wake_up ( & cl - > wait ) ;
2012-12-25 19:06:12 +02:00
}
2012-12-25 19:06:07 +02:00
/**
2014-01-08 22:31:46 +02:00
* mei_hbm_fw_disconnect_req - disconnect request initiated by ME firmware
* host sends disconnect response
2012-12-25 19:06:07 +02:00
*
* @ dev : the device structure .
2012-12-25 19:06:11 +02:00
* @ disconnect_req : disconnect request bus message from the me
2014-02-12 21:41:52 +02:00
*
2014-09-29 16:31:49 +03:00
* Return : - ENOMEM on allocation failure
2012-12-25 19:06:07 +02:00
*/
2014-02-12 21:41:52 +02:00
static int mei_hbm_fw_disconnect_req ( struct mei_device * dev ,
2012-12-25 19:06:07 +02:00
struct hbm_client_connect_request * disconnect_req )
{
2014-02-17 15:13:25 +02:00
struct mei_cl * cl ;
2014-02-12 21:41:52 +02:00
struct mei_cl_cb * cb ;
2012-12-25 19:06:07 +02:00
2014-08-21 14:29:20 +03:00
cl = mei_hbm_cl_find_by_cmd ( dev , disconnect_req ) ;
if ( cl ) {
2016-02-07 23:35:39 +02:00
cl_warn ( dev , cl , " fw disconnect request received \n " ) ;
2015-05-04 09:43:52 +03:00
cl - > state = MEI_FILE_DISCONNECTING ;
2014-08-21 14:29:20 +03:00
cl - > timer_count = 0 ;
2016-07-26 01:06:05 +03:00
cb = mei_cl_enqueue_ctrl_wr_cb ( cl , 0 , MEI_FOP_DISCONNECT_RSP ,
NULL ) ;
2014-08-21 14:29:20 +03:00
if ( ! cb )
return - ENOMEM ;
2012-12-25 19:06:07 +02:00
}
2014-02-12 21:41:52 +02:00
return 0 ;
2012-12-25 19:06:07 +02:00
}
2015-08-02 22:20:53 +03:00
/**
* mei_hbm_pg_enter_res - PG enter response received
*
* @ dev : the device structure .
*
* Return : 0 on success , - EPROTO on state mismatch
*/
static int mei_hbm_pg_enter_res ( struct mei_device * dev )
{
if ( mei_pg_state ( dev ) ! = MEI_PG_OFF | |
dev - > pg_event ! = MEI_PG_EVENT_WAIT ) {
dev_err ( dev - > dev , " hbm: pg entry response: state mismatch [%s, %d] \n " ,
mei_pg_state_str ( mei_pg_state ( dev ) ) , dev - > pg_event ) ;
return - EPROTO ;
}
dev - > pg_event = MEI_PG_EVENT_RECEIVED ;
wake_up ( & dev - > wait_pg ) ;
return 0 ;
}
2015-08-02 22:20:54 +03:00
/**
* mei_hbm_pg_resume - process with PG resume
*
* @ dev : the device structure .
*/
void mei_hbm_pg_resume ( struct mei_device * dev )
{
pm_request_resume ( dev - > dev ) ;
}
EXPORT_SYMBOL_GPL ( mei_hbm_pg_resume ) ;
2015-08-02 22:20:53 +03:00
/**
* mei_hbm_pg_exit_res - PG exit response received
*
* @ dev : the device structure .
*
* Return : 0 on success , - EPROTO on state mismatch
*/
static int mei_hbm_pg_exit_res ( struct mei_device * dev )
{
if ( mei_pg_state ( dev ) ! = MEI_PG_ON | |
( dev - > pg_event ! = MEI_PG_EVENT_WAIT & &
dev - > pg_event ! = MEI_PG_EVENT_IDLE ) ) {
dev_err ( dev - > dev , " hbm: pg exit response: state mismatch [%s, %d] \n " ,
mei_pg_state_str ( mei_pg_state ( dev ) ) , dev - > pg_event ) ;
return - EPROTO ;
}
switch ( dev - > pg_event ) {
case MEI_PG_EVENT_WAIT :
dev - > pg_event = MEI_PG_EVENT_RECEIVED ;
wake_up ( & dev - > wait_pg ) ;
break ;
case MEI_PG_EVENT_IDLE :
/*
* If the driver is not waiting on this then
* this is HW initiated exit from PG .
* Start runtime pm resume sequence to exit from PG .
*/
dev - > pg_event = MEI_PG_EVENT_RECEIVED ;
2015-08-02 22:20:54 +03:00
mei_hbm_pg_resume ( dev ) ;
2015-08-02 22:20:53 +03:00
break ;
default :
WARN ( 1 , " hbm: pg exit response: unexpected pg event = %d \n " ,
dev - > pg_event ) ;
return - EPROTO ;
}
return 0 ;
}
2014-08-21 14:29:21 +03:00
/**
2014-09-29 16:31:49 +03:00
* mei_hbm_config_features - check what hbm features and commands
2014-08-21 14:29:21 +03:00
* are supported by the fw
*
* @ dev : the device structure
*/
static void mei_hbm_config_features ( struct mei_device * dev )
{
/* Power Gating Isolation Support */
dev - > hbm_f_pg_supported = 0 ;
if ( dev - > version . major_version > HBM_MAJOR_VERSION_PGI )
dev - > hbm_f_pg_supported = 1 ;
if ( dev - > version . major_version = = HBM_MAJOR_VERSION_PGI & &
dev - > version . minor_version > = HBM_MINOR_VERSION_PGI )
dev - > hbm_f_pg_supported = 1 ;
2015-07-23 21:37:12 +03:00
2019-02-20 16:55:37 +02:00
dev - > hbm_f_dc_supported = 0 ;
2015-07-23 21:37:12 +03:00
if ( dev - > version . major_version > = HBM_MAJOR_VERSION_DC )
dev - > hbm_f_dc_supported = 1 ;
2015-07-23 21:37:13 +03:00
2019-02-20 16:55:37 +02:00
dev - > hbm_f_ie_supported = 0 ;
2016-02-07 23:35:42 +02:00
if ( dev - > version . major_version > = HBM_MAJOR_VERSION_IE )
dev - > hbm_f_ie_supported = 1 ;
2015-07-23 21:37:13 +03:00
/* disconnect on connect timeout instead of link reset */
2019-02-20 16:55:37 +02:00
dev - > hbm_f_dot_supported = 0 ;
2015-07-23 21:37:13 +03:00
if ( dev - > version . major_version > = HBM_MAJOR_VERSION_DOT )
dev - > hbm_f_dot_supported = 1 ;
2015-07-26 09:54:17 +03:00
/* Notification Event Support */
2019-02-20 16:55:37 +02:00
dev - > hbm_f_ev_supported = 0 ;
2015-07-26 09:54:17 +03:00
if ( dev - > version . major_version > = HBM_MAJOR_VERSION_EV )
dev - > hbm_f_ev_supported = 1 ;
2016-02-07 23:35:38 +02:00
/* Fixed Address Client Support */
2019-02-20 16:55:37 +02:00
dev - > hbm_f_fa_supported = 0 ;
2016-02-07 23:35:38 +02:00
if ( dev - > version . major_version > = HBM_MAJOR_VERSION_FA )
dev - > hbm_f_fa_supported = 1 ;
2017-01-11 01:27:21 +02:00
/* OS ver message Support */
2019-02-20 16:55:37 +02:00
dev - > hbm_f_os_supported = 0 ;
2017-01-11 01:27:21 +02:00
if ( dev - > version . major_version > = HBM_MAJOR_VERSION_OS )
dev - > hbm_f_os_supported = 1 ;
2018-07-31 09:35:36 +03:00
/* DMA Ring Support */
2019-02-20 16:55:37 +02:00
dev - > hbm_f_dr_supported = 0 ;
2018-07-31 09:35:36 +03:00
if ( dev - > version . major_version > HBM_MAJOR_VERSION_DR | |
( dev - > version . major_version = = HBM_MAJOR_VERSION_DR & &
dev - > version . minor_version > = HBM_MINOR_VERSION_DR ) )
dev - > hbm_f_dr_supported = 1 ;
2020-08-18 14:51:35 +03:00
2020-08-18 14:51:36 +03:00
/* VTag Support */
dev - > hbm_f_vt_supported = 0 ;
if ( dev - > version . major_version > HBM_MAJOR_VERSION_VT | |
( dev - > version . major_version = = HBM_MAJOR_VERSION_VT & &
dev - > version . minor_version > = HBM_MINOR_VERSION_VT ) )
dev - > hbm_f_vt_supported = 1 ;
/* Capability message Support */
2020-08-18 14:51:35 +03:00
dev - > hbm_f_cap_supported = 0 ;
if ( dev - > version . major_version > HBM_MAJOR_VERSION_CAP | |
( dev - > version . major_version = = HBM_MAJOR_VERSION_CAP & &
dev - > version . minor_version > = HBM_MINOR_VERSION_CAP ) )
dev - > hbm_f_cap_supported = 1 ;
2014-08-21 14:29:21 +03:00
}
2012-12-25 19:06:07 +02:00
2013-06-16 09:16:31 +03:00
/**
* mei_hbm_version_is_supported - checks whether the driver can
* support the hbm version of the device
*
* @ dev : the device structure
2014-09-29 16:31:49 +03:00
* Return : true if driver can support hbm version of the device
2013-06-16 09:16:31 +03:00
*/
bool mei_hbm_version_is_supported ( struct mei_device * dev )
{
return ( dev - > version . major_version < HBM_MAJOR_VERSION ) | |
( dev - > version . major_version = = HBM_MAJOR_VERSION & &
dev - > version . minor_version < = HBM_MINOR_VERSION ) ;
}
2012-12-25 19:06:07 +02:00
/**
* mei_hbm_dispatch - bottom half read routine after ISR to
* handle the read bus message cmd processing .
*
* @ dev : the device structure
2014-09-29 16:31:49 +03:00
* @ hdr : header of bus message
2014-01-08 20:19:21 +02:00
*
2014-09-29 16:31:49 +03:00
* Return : 0 on success and < 0 on failure
2012-12-25 19:06:07 +02:00
*/
2014-01-08 20:19:21 +02:00
int mei_hbm_dispatch ( struct mei_device * dev , struct mei_msg_hdr * hdr )
2012-12-25 19:06:07 +02:00
{
struct mei_bus_message * mei_msg ;
struct hbm_host_version_response * version_res ;
struct hbm_props_response * props_res ;
struct hbm_host_enum_response * enum_res ;
2018-11-22 13:11:37 +02:00
struct hbm_dma_setup_response * dma_setup_res ;
2015-07-23 21:37:12 +03:00
struct hbm_add_client_request * add_cl_req ;
2020-08-18 14:51:36 +03:00
struct hbm_capability_response * capability_res ;
2015-07-23 21:37:12 +03:00
int ret ;
2012-12-25 19:06:07 +02:00
2014-08-21 14:29:18 +03:00
struct mei_hbm_cl_cmd * cl_cmd ;
struct hbm_client_connect_request * disconnect_req ;
2016-07-26 01:06:04 +03:00
struct hbm_flow_control * fctrl ;
2014-08-21 14:29:18 +03:00
2012-12-25 19:06:07 +02:00
/* read the message to our buffer */
BUG_ON ( hdr - > length > = sizeof ( dev - > rd_msg_buf ) ) ;
mei_read_slots ( dev , dev - > rd_msg_buf , hdr - > length ) ;
mei_msg = ( struct mei_bus_message * ) dev - > rd_msg_buf ;
2014-08-21 14:29:18 +03:00
cl_cmd = ( struct mei_hbm_cl_cmd * ) mei_msg ;
2012-12-25 19:06:07 +02:00
2014-01-08 20:19:22 +02:00
/* ignore spurious message and prevent reset nesting
* hbm is put to idle during system reset
*/
if ( dev - > hbm_state = = MEI_HBM_IDLE ) {
2014-09-29 16:31:42 +03:00
dev_dbg ( dev - > dev , " hbm: state is idle ignore spurious messages \n " ) ;
2014-01-08 20:19:22 +02:00
return 0 ;
}
2012-12-25 19:06:07 +02:00
switch ( mei_msg - > hbm_cmd ) {
case HOST_START_RES_CMD :
2014-09-29 16:31:42 +03:00
dev_dbg ( dev - > dev , " hbm: start: response message received. \n " ) ;
2014-01-08 20:19:21 +02:00
dev - > init_clients_timer = 0 ;
2012-12-25 19:06:07 +02:00
version_res = ( struct hbm_host_version_response * ) mei_msg ;
2013-06-16 09:16:31 +03:00
2014-09-29 16:31:42 +03:00
dev_dbg ( dev - > dev , " HBM VERSION: DRIVER=%02d:%02d DEVICE=%02d:%02d \n " ,
2013-06-16 09:16:31 +03:00
HBM_MAJOR_VERSION , HBM_MINOR_VERSION ,
version_res - > me_max_version . major_version ,
version_res - > me_max_version . minor_version ) ;
if ( version_res - > host_version_supported ) {
dev - > version . major_version = HBM_MAJOR_VERSION ;
dev - > version . minor_version = HBM_MINOR_VERSION ;
} else {
dev - > version . major_version =
version_res - > me_max_version . major_version ;
dev - > version . minor_version =
version_res - > me_max_version . minor_version ;
}
if ( ! mei_hbm_version_is_supported ( dev ) ) {
2014-09-29 16:31:42 +03:00
dev_warn ( dev - > dev , " hbm: start: version mismatch - stopping the driver. \n " ) ;
2012-12-25 19:06:07 +02:00
2014-01-08 20:19:21 +02:00
dev - > hbm_state = MEI_HBM_STOPPED ;
2014-02-12 21:41:52 +02:00
if ( mei_hbm_stop_req ( dev ) ) {
2014-09-29 16:31:42 +03:00
dev_err ( dev - > dev , " hbm: start: failed to send stop request \n " ) ;
2014-01-08 20:19:21 +02:00
return - EIO ;
}
break ;
}
2013-04-18 23:03:48 +03:00
2014-08-21 14:29:21 +03:00
mei_hbm_config_features ( dev ) ;
2014-01-08 20:19:21 +02:00
if ( dev - > dev_state ! = MEI_DEV_INIT_CLIENTS | |
2014-08-21 14:29:19 +03:00
dev - > hbm_state ! = MEI_HBM_STARTING ) {
2014-09-29 16:31:42 +03:00
dev_err ( dev - > dev , " hbm: start: state mismatch, [%d, %d] \n " ,
2014-01-08 20:19:21 +02:00
dev - > dev_state , dev - > hbm_state ) ;
return - EPROTO ;
2012-12-25 19:06:10 +02:00
}
2012-12-25 19:06:07 +02:00
2020-08-18 14:51:35 +03:00
if ( dev - > hbm_f_cap_supported ) {
if ( mei_hbm_capabilities_req ( dev ) )
return - EIO ;
wake_up ( & dev - > wait_hbm_start ) ;
break ;
}
2018-11-22 13:11:37 +02:00
if ( dev - > hbm_f_dr_supported ) {
if ( mei_dmam_ring_alloc ( dev ) )
dev_info ( dev - > dev , " running w/o dma ring \n " ) ;
if ( mei_dma_ring_is_allocated ( dev ) ) {
if ( mei_hbm_dma_setup_req ( dev ) )
return - EIO ;
wake_up ( & dev - > wait_hbm_start ) ;
break ;
}
2012-12-25 19:06:07 +02:00
}
2018-11-22 13:11:37 +02:00
dev - > hbm_f_dr_supported = 0 ;
mei_dmam_ring_free ( dev ) ;
if ( mei_hbm_enum_clients_req ( dev ) )
return - EIO ;
2014-08-21 14:29:19 +03:00
wake_up ( & dev - > wait_hbm_start ) ;
2012-12-25 19:06:07 +02:00
break ;
2020-08-18 14:51:35 +03:00
case MEI_HBM_CAPABILITIES_RES_CMD :
dev_dbg ( dev - > dev , " hbm: capabilities response: message received. \n " ) ;
dev - > init_clients_timer = 0 ;
if ( dev - > hbm_state ! = MEI_HBM_CAP_SETUP ) {
dev_err ( dev - > dev , " hbm: capabilities response: state mismatch, [%d, %d] \n " ,
dev - > dev_state , dev - > hbm_state ) ;
return - EPROTO ;
}
2020-08-18 14:51:36 +03:00
capability_res = ( struct hbm_capability_response * ) mei_msg ;
if ( ! ( capability_res - > capability_granted [ 0 ] & HBM_CAP_VT ) )
dev - > hbm_f_vt_supported = 0 ;
2020-08-18 14:51:35 +03:00
if ( dev - > hbm_f_dr_supported ) {
if ( mei_dmam_ring_alloc ( dev ) )
dev_info ( dev - > dev , " running w/o dma ring \n " ) ;
if ( mei_dma_ring_is_allocated ( dev ) ) {
if ( mei_hbm_dma_setup_req ( dev ) )
return - EIO ;
break ;
}
}
dev - > hbm_f_dr_supported = 0 ;
mei_dmam_ring_free ( dev ) ;
if ( mei_hbm_enum_clients_req ( dev ) )
return - EIO ;
break ;
2018-11-22 13:11:37 +02:00
case MEI_HBM_DMA_SETUP_RES_CMD :
dev_dbg ( dev - > dev , " hbm: dma setup response: message received. \n " ) ;
dev - > init_clients_timer = 0 ;
if ( dev - > hbm_state ! = MEI_HBM_DR_SETUP ) {
dev_err ( dev - > dev , " hbm: dma setup response: state mismatch, [%d, %d] \n " ,
dev - > dev_state , dev - > hbm_state ) ;
return - EPROTO ;
}
dma_setup_res = ( struct hbm_dma_setup_response * ) mei_msg ;
if ( dma_setup_res - > status ) {
2019-01-13 14:24:46 +02:00
u8 status = dma_setup_res - > status ;
if ( status = = MEI_HBMS_NOT_ALLOWED ) {
dev_dbg ( dev - > dev , " hbm: dma setup not allowed \n " ) ;
} else {
dev_info ( dev - > dev , " hbm: dma setup response: failure = %d %s \n " ,
status ,
mei_hbm_status_str ( status ) ) ;
}
2018-11-22 13:11:37 +02:00
dev - > hbm_f_dr_supported = 0 ;
mei_dmam_ring_free ( dev ) ;
}
if ( mei_hbm_enum_clients_req ( dev ) )
return - EIO ;
break ;
2012-12-25 19:06:07 +02:00
case CLIENT_CONNECT_RES_CMD :
2014-09-29 16:31:42 +03:00
dev_dbg ( dev - > dev , " hbm: client connect response: message received. \n " ) ;
2014-08-21 14:29:18 +03:00
mei_hbm_cl_res ( dev , cl_cmd , MEI_FOP_CONNECT ) ;
2012-12-25 19:06:07 +02:00
break ;
case CLIENT_DISCONNECT_RES_CMD :
2014-09-29 16:31:42 +03:00
dev_dbg ( dev - > dev , " hbm: client disconnect response: message received. \n " ) ;
2014-08-21 14:29:18 +03:00
mei_hbm_cl_res ( dev , cl_cmd , MEI_FOP_DISCONNECT ) ;
2012-12-25 19:06:07 +02:00
break ;
case MEI_FLOW_CONTROL_CMD :
2014-09-29 16:31:42 +03:00
dev_dbg ( dev - > dev , " hbm: client flow control response: message received. \n " ) ;
2014-01-08 20:19:21 +02:00
2016-07-26 01:06:04 +03:00
fctrl = ( struct hbm_flow_control * ) mei_msg ;
mei_hbm_cl_tx_flow_ctrl_creds_res ( dev , fctrl ) ;
2012-12-25 19:06:07 +02:00
break ;
2014-03-18 22:51:55 +02:00
case MEI_PG_ISOLATION_ENTRY_RES_CMD :
2015-08-02 22:20:53 +03:00
dev_dbg ( dev - > dev , " hbm: power gate isolation entry response received \n " ) ;
ret = mei_hbm_pg_enter_res ( dev ) ;
if ( ret )
return ret ;
2014-03-18 22:51:55 +02:00
break ;
case MEI_PG_ISOLATION_EXIT_REQ_CMD :
2015-08-02 22:20:53 +03:00
dev_dbg ( dev - > dev , " hbm: power gate isolation exit request received \n " ) ;
ret = mei_hbm_pg_exit_res ( dev ) ;
if ( ret )
return ret ;
2014-03-18 22:51:55 +02:00
break ;
2012-12-25 19:06:07 +02:00
case HOST_CLIENT_PROPERTIES_RES_CMD :
2014-09-29 16:31:42 +03:00
dev_dbg ( dev - > dev , " hbm: properties response: message received. \n " ) ;
2014-01-08 20:19:21 +02:00
dev - > init_clients_timer = 0 ;
2014-08-21 14:29:13 +03:00
if ( dev - > dev_state ! = MEI_DEV_INIT_CLIENTS | |
dev - > hbm_state ! = MEI_HBM_CLIENT_PROPERTIES ) {
2014-09-29 16:31:42 +03:00
dev_err ( dev - > dev , " hbm: properties response: state mismatch, [%d, %d] \n " ,
2014-08-21 14:29:13 +03:00
dev - > dev_state , dev - > hbm_state ) ;
2014-01-08 20:19:21 +02:00
return - EPROTO ;
}
2012-12-25 19:06:07 +02:00
props_res = ( struct hbm_props_response * ) mei_msg ;
2018-08-06 17:47:33 +03:00
if ( props_res - > status = = MEI_HBMS_CLIENT_NOT_FOUND ) {
dev_dbg ( dev - > dev , " hbm: properties response: %d CLIENT_NOT_FOUND \n " ,
props_res - > me_addr ) ;
} else if ( props_res - > status ) {
2014-09-29 16:31:42 +03:00
dev_err ( dev - > dev , " hbm: properties response: wrong status = %d %s \n " ,
2014-08-21 14:29:16 +03:00
props_res - > status ,
mei_hbm_status_str ( props_res - > status ) ) ;
2014-01-08 20:19:21 +02:00
return - EPROTO ;
2018-08-06 17:47:33 +03:00
} else {
mei_hbm_me_cl_add ( dev , props_res ) ;
2012-12-25 19:06:07 +02:00
}
2012-12-25 19:06:11 +02:00
/* request property for the next client */
2016-04-17 12:16:02 -04:00
if ( mei_hbm_prop_req ( dev , props_res - > me_addr + 1 ) )
2014-01-08 20:19:21 +02:00
return - EIO ;
2012-12-25 19:06:07 +02:00
break ;
case HOST_ENUM_RES_CMD :
2014-09-29 16:31:42 +03:00
dev_dbg ( dev - > dev , " hbm: enumeration response: message received \n " ) ;
2014-01-08 20:19:21 +02:00
dev - > init_clients_timer = 0 ;
2012-12-25 19:06:07 +02:00
enum_res = ( struct hbm_host_enum_response * ) mei_msg ;
2013-09-02 03:11:01 +03:00
BUILD_BUG_ON ( sizeof ( dev - > me_clients_map )
< sizeof ( enum_res - > valid_addresses ) ) ;
memcpy ( dev - > me_clients_map , enum_res - > valid_addresses ,
2014-08-21 14:29:13 +03:00
sizeof ( enum_res - > valid_addresses ) ) ;
2014-01-08 20:19:21 +02:00
if ( dev - > dev_state ! = MEI_DEV_INIT_CLIENTS | |
dev - > hbm_state ! = MEI_HBM_ENUM_CLIENTS ) {
2014-09-29 16:31:42 +03:00
dev_err ( dev - > dev , " hbm: enumeration response: state mismatch, [%d, %d] \n " ,
2014-01-08 20:19:21 +02:00
dev - > dev_state , dev - > hbm_state ) ;
return - EPROTO ;
2012-12-25 19:06:07 +02:00
}
2014-01-08 20:19:21 +02:00
dev - > hbm_state = MEI_HBM_CLIENT_PROPERTIES ;
/* first property request */
2016-04-17 12:16:02 -04:00
if ( mei_hbm_prop_req ( dev , 0 ) )
2014-01-08 20:19:21 +02:00
return - EIO ;
2012-12-25 19:06:07 +02:00
break ;
case HOST_STOP_RES_CMD :
2014-09-29 16:31:42 +03:00
dev_dbg ( dev - > dev , " hbm: stop response: message received \n " ) ;
2014-01-08 20:19:21 +02:00
dev - > init_clients_timer = 0 ;
if ( dev - > hbm_state ! = MEI_HBM_STOPPED ) {
2014-09-29 16:31:42 +03:00
dev_err ( dev - > dev , " hbm: stop response: state mismatch, [%d, %d] \n " ,
2014-01-08 20:19:21 +02:00
dev - > dev_state , dev - > hbm_state ) ;
return - EPROTO ;
}
2013-04-18 23:03:48 +03:00
2014-01-12 00:36:09 +02:00
dev - > dev_state = MEI_DEV_POWER_DOWN ;
2014-09-29 16:31:42 +03:00
dev_info ( dev - > dev , " hbm: stop response: resetting. \n " ) ;
2014-01-08 20:19:21 +02:00
/* force the reset */
return - EPROTO ;
2012-12-25 19:06:07 +02:00
case CLIENT_DISCONNECT_REQ_CMD :
2014-09-29 16:31:42 +03:00
dev_dbg ( dev - > dev , " hbm: disconnect request: message received \n " ) ;
2014-01-08 20:19:21 +02:00
2012-12-25 19:06:07 +02:00
disconnect_req = ( struct hbm_client_connect_request * ) mei_msg ;
2012-12-25 19:06:11 +02:00
mei_hbm_fw_disconnect_req ( dev , disconnect_req ) ;
2012-12-25 19:06:07 +02:00
break ;
case ME_STOP_REQ_CMD :
2014-09-29 16:31:42 +03:00
dev_dbg ( dev - > dev , " hbm: stop request: message received \n " ) ;
2014-01-08 20:19:21 +02:00
dev - > hbm_state = MEI_HBM_STOPPED ;
2014-02-12 21:41:52 +02:00
if ( mei_hbm_stop_req ( dev ) ) {
2014-09-29 16:31:42 +03:00
dev_err ( dev - > dev , " hbm: stop request: failed to send stop request \n " ) ;
2014-02-12 21:41:52 +02:00
return - EIO ;
}
2012-12-25 19:06:07 +02:00
break ;
2015-07-23 21:37:12 +03:00
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
*/
2015-09-21 11:45:32 +03:00
if ( dev - > hbm_state < = MEI_HBM_ENUM_CLIENTS | |
2015-07-23 21:37:12 +03:00
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 ;
2015-07-26 09:54:16 +03:00
case MEI_HBM_NOTIFY_RES_CMD :
dev_dbg ( dev - > dev , " hbm: notify response received \n " ) ;
mei_hbm_cl_res ( dev , cl_cmd , notify_res_to_fop ( cl_cmd ) ) ;
break ;
case MEI_HBM_NOTIFICATION_CMD :
dev_dbg ( dev - > dev , " hbm: notification \n " ) ;
mei_hbm_cl_notify ( dev , cl_cmd ) ;
break ;
2012-12-25 19:06:07 +02:00
default :
2018-11-06 12:04:38 +02:00
WARN ( 1 , " hbm: wrong command %d \n " , mei_msg - > hbm_cmd ) ;
return - EPROTO ;
2012-12-25 19:06:07 +02:00
}
2014-01-08 20:19:21 +02:00
return 0 ;
2012-12-25 19:06:07 +02:00
}