2011-05-15 13:43:43 +03:00
/*
*
* Intel Management Engine Interface ( Intel MEI ) Linux driver
2012-02-09 19:25:53 +02:00
* Copyright ( c ) 2003 - 2012 , Intel Corporation .
2011-05-15 13:43:43 +03:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms and conditions of the GNU General Public License ,
* version 2 , as published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
*/
# include <linux/pci.h>
2013-02-06 14:06:42 +02:00
# include <linux/kthread.h>
# include <linux/interrupt.h>
2012-12-25 19:06:03 +02:00
# include "mei_dev.h"
2013-01-08 23:07:17 +02:00
# include "hw-me.h"
2011-05-15 13:43:43 +03:00
2013-02-06 14:06:42 +02:00
# include "hbm.h"
2012-12-25 19:06:06 +02:00
/**
2013-03-27 16:58:29 +02:00
* mei_me_reg_read - Reads 32 bit data from the mei device
2012-12-25 19:06:06 +02:00
*
* @ dev : the device structure
* @ offset : offset from which to read the data
*
* returns register value ( u32 )
*/
2013-03-27 16:58:29 +02:00
static inline u32 mei_me_reg_read ( const struct mei_me_hw * hw ,
2012-12-25 19:06:06 +02:00
unsigned long offset )
{
2013-02-06 14:06:40 +02:00
return ioread32 ( hw - > mem_addr + offset ) ;
2012-12-25 19:06:06 +02:00
}
/**
2013-03-27 16:58:29 +02:00
* mei_me_reg_write - Writes 32 bit data to the mei device
2012-12-25 19:06:06 +02:00
*
* @ dev : the device structure
* @ offset : offset from which to write the data
* @ value : register value to write ( u32 )
*/
2013-03-27 16:58:29 +02:00
static inline void mei_me_reg_write ( const struct mei_me_hw * hw ,
2012-12-25 19:06:06 +02:00
unsigned long offset , u32 value )
{
2013-02-06 14:06:40 +02:00
iowrite32 ( value , hw - > mem_addr + offset ) ;
2012-12-25 19:06:06 +02:00
}
2011-05-15 13:43:43 +03:00
2012-12-25 19:06:06 +02:00
/**
2013-03-27 16:58:29 +02:00
* mei_me_mecbrw_read - Reads 32 bit data from ME circular buffer
2013-01-08 23:07:24 +02:00
* read window register
2012-12-25 19:06:06 +02:00
*
* @ dev : the device structure
*
2013-01-08 23:07:24 +02:00
* returns ME_CB_RW register value ( u32 )
2012-12-25 19:06:06 +02:00
*/
2013-02-06 14:06:41 +02:00
static u32 mei_me_mecbrw_read ( const struct mei_device * dev )
2012-12-25 19:06:06 +02:00
{
2013-03-27 16:58:29 +02:00
return mei_me_reg_read ( to_me_hw ( dev ) , ME_CB_RW ) ;
2012-12-25 19:06:06 +02:00
}
/**
2013-03-27 16:58:29 +02:00
* mei_me_mecsr_read - Reads 32 bit data from the ME CSR
2012-12-25 19:06:06 +02:00
*
* @ dev : the device structure
*
* returns ME_CSR_HA register value ( u32 )
*/
2013-03-27 16:58:29 +02:00
static inline u32 mei_me_mecsr_read ( const struct mei_me_hw * hw )
2012-12-25 19:06:06 +02:00
{
2013-03-27 16:58:29 +02:00
return mei_me_reg_read ( hw , ME_CSR_HA ) ;
2012-12-25 19:06:06 +02:00
}
2011-05-15 13:43:43 +03:00
/**
2013-01-08 23:07:24 +02:00
* mei_hcsr_read - Reads 32 bit data from the host CSR
*
* @ dev : the device structure
*
* returns H_CSR register value ( u32 )
*/
2013-02-06 14:06:40 +02:00
static inline u32 mei_hcsr_read ( const struct mei_me_hw * hw )
2013-01-08 23:07:24 +02:00
{
2013-03-27 16:58:29 +02:00
return mei_me_reg_read ( hw , H_CSR ) ;
2013-01-08 23:07:24 +02:00
}
/**
* mei_hcsr_set - writes H_CSR register to the mei device ,
2011-05-15 13:43:43 +03:00
* and ignores the H_IS bit for it is write - one - to - zero .
*
* @ dev : the device structure
*/
2013-02-06 14:06:40 +02:00
static inline void mei_hcsr_set ( struct mei_me_hw * hw , u32 hcsr )
2011-05-15 13:43:43 +03:00
{
2013-01-08 23:07:30 +02:00
hcsr & = ~ H_IS ;
2013-03-27 16:58:29 +02:00
mei_me_reg_write ( hw , H_CSR , hcsr ) ;
2011-05-15 13:43:43 +03:00
}
2013-01-08 23:07:31 +02:00
/**
2013-04-05 01:05:05 +09:00
* mei_me_hw_config - configure hw dependent settings
2013-01-08 23:07:31 +02:00
*
* @ dev : mei device
*/
2013-02-06 14:06:41 +02:00
static void mei_me_hw_config ( struct mei_device * dev )
2013-01-08 23:07:31 +02:00
{
2013-02-06 14:06:40 +02:00
u32 hcsr = mei_hcsr_read ( to_me_hw ( dev ) ) ;
2013-01-08 23:07:31 +02:00
/* Doesn't change in runtime */
dev - > hbuf_depth = ( hcsr & H_CBD ) > > 24 ;
}
2011-05-15 13:43:43 +03:00
/**
2013-01-08 23:07:24 +02:00
* mei_clear_interrupts - clear and stop interrupts
2012-12-25 19:06:06 +02:00
*
* @ dev : the device structure
*/
2013-02-06 14:06:41 +02:00
static void mei_me_intr_clear ( struct mei_device * dev )
2012-12-25 19:06:06 +02:00
{
2013-02-06 14:06:40 +02:00
struct mei_me_hw * hw = to_me_hw ( dev ) ;
u32 hcsr = mei_hcsr_read ( hw ) ;
2013-01-08 23:07:28 +02:00
if ( ( hcsr & H_IS ) = = H_IS )
2013-03-27 16:58:29 +02:00
mei_me_reg_write ( hw , H_CSR , hcsr ) ;
2012-12-25 19:06:06 +02:00
}
/**
2013-02-06 14:06:41 +02:00
* mei_me_intr_enable - enables mei device interrupts
2011-05-15 13:43:43 +03:00
*
* @ dev : the device structure
*/
2013-02-06 14:06:41 +02:00
static void mei_me_intr_enable ( struct mei_device * dev )
2011-05-15 13:43:43 +03:00
{
2013-02-06 14:06:40 +02:00
struct mei_me_hw * hw = to_me_hw ( dev ) ;
u32 hcsr = mei_hcsr_read ( hw ) ;
2013-01-08 23:07:28 +02:00
hcsr | = H_IE ;
2013-02-06 14:06:40 +02:00
mei_hcsr_set ( hw , hcsr ) ;
2011-05-15 13:43:43 +03:00
}
/**
2012-12-25 19:06:06 +02:00
* mei_disable_interrupts - disables mei device interrupts
2011-05-15 13:43:43 +03:00
*
* @ dev : the device structure
*/
2013-02-06 14:06:41 +02:00
static void mei_me_intr_disable ( struct mei_device * dev )
2011-05-15 13:43:43 +03:00
{
2013-02-06 14:06:40 +02:00
struct mei_me_hw * hw = to_me_hw ( dev ) ;
u32 hcsr = mei_hcsr_read ( hw ) ;
2013-01-08 23:07:28 +02:00
hcsr & = ~ H_IE ;
2013-02-06 14:06:40 +02:00
mei_hcsr_set ( hw , hcsr ) ;
2011-05-15 13:43:43 +03:00
}
2013-03-10 13:56:07 +02:00
/**
* mei_me_hw_reset_release - release device from the reset
*
* @ dev : the device structure
*/
static void mei_me_hw_reset_release ( struct mei_device * dev )
{
struct mei_me_hw * hw = to_me_hw ( dev ) ;
u32 hcsr = mei_hcsr_read ( hw ) ;
hcsr | = H_IG ;
hcsr & = ~ H_RST ;
mei_hcsr_set ( hw , hcsr ) ;
}
2013-01-08 23:07:27 +02:00
/**
2013-02-06 14:06:41 +02:00
* mei_me_hw_reset - resets fw via mei csr register .
2013-01-08 23:07:27 +02:00
*
* @ dev : the device structure
2013-04-05 01:05:05 +09:00
* @ intr_enable : if interrupt should be enabled after reset .
2013-01-08 23:07:27 +02:00
*/
2013-06-23 10:42:49 +03:00
static int mei_me_hw_reset ( struct mei_device * dev , bool intr_enable )
2013-01-08 23:07:27 +02:00
{
2013-02-06 14:06:40 +02:00
struct mei_me_hw * hw = to_me_hw ( dev ) ;
u32 hcsr = mei_hcsr_read ( hw ) ;
2013-01-08 23:07:27 +02:00
2013-07-30 14:11:51 +03:00
hcsr | = H_RST | H_IG | H_IS ;
2013-01-08 23:07:27 +02:00
if ( intr_enable )
hcsr | = H_IE ;
else
2013-07-30 14:11:51 +03:00
hcsr & = ~ H_IE ;
2013-01-08 23:07:27 +02:00
2013-07-30 14:11:51 +03:00
mei_me_reg_write ( hw , H_CSR , hcsr ) ;
2013-01-08 23:07:27 +02:00
2014-01-12 00:36:09 +02:00
if ( intr_enable = = false )
2013-03-10 13:56:07 +02:00
mei_me_hw_reset_release ( dev ) ;
2013-01-08 23:07:27 +02:00
2013-06-23 10:42:49 +03:00
return 0 ;
2013-01-08 23:07:27 +02:00
}
2013-01-08 23:07:29 +02:00
/**
2013-02-06 14:06:41 +02:00
* mei_me_host_set_ready - enable device
2013-01-08 23:07:29 +02:00
*
* @ dev - mei device
* returns bool
*/
2013-02-06 14:06:41 +02:00
static void mei_me_host_set_ready ( struct mei_device * dev )
2013-01-08 23:07:29 +02:00
{
2013-02-06 14:06:40 +02:00
struct mei_me_hw * hw = to_me_hw ( dev ) ;
hw - > host_hw_state | = H_IE | H_IG | H_RDY ;
mei_hcsr_set ( hw , hw - > host_hw_state ) ;
2013-01-08 23:07:29 +02:00
}
/**
2013-02-06 14:06:41 +02:00
* mei_me_host_is_ready - check whether the host has turned ready
2013-01-08 23:07:29 +02:00
*
* @ dev - mei device
* returns bool
*/
2013-02-06 14:06:41 +02:00
static bool mei_me_host_is_ready ( struct mei_device * dev )
2013-01-08 23:07:29 +02:00
{
2013-02-06 14:06:40 +02:00
struct mei_me_hw * hw = to_me_hw ( dev ) ;
hw - > host_hw_state = mei_hcsr_read ( hw ) ;
return ( hw - > host_hw_state & H_RDY ) = = H_RDY ;
2013-01-08 23:07:29 +02:00
}
/**
2013-02-06 14:06:41 +02:00
* mei_me_hw_is_ready - check whether the me ( hw ) has turned ready
2013-01-08 23:07:29 +02:00
*
* @ dev - mei device
* returns bool
*/
2013-02-06 14:06:41 +02:00
static bool mei_me_hw_is_ready ( struct mei_device * dev )
2013-01-08 23:07:29 +02:00
{
2013-02-06 14:06:40 +02:00
struct mei_me_hw * hw = to_me_hw ( dev ) ;
2013-03-27 16:58:29 +02:00
hw - > me_hw_state = mei_me_mecsr_read ( hw ) ;
2013-02-06 14:06:40 +02:00
return ( hw - > me_hw_state & ME_RDY_HRA ) = = ME_RDY_HRA ;
2013-01-08 23:07:29 +02:00
}
2012-12-25 19:06:06 +02:00
2013-03-11 18:27:03 +02:00
static int mei_me_hw_ready_wait ( struct mei_device * dev )
{
int err ;
if ( mei_me_hw_is_ready ( dev ) )
return 0 ;
2013-07-17 15:13:17 +03:00
dev - > recvd_hw_ready = false ;
2013-03-11 18:27:03 +02:00
mutex_unlock ( & dev - > device_lock ) ;
err = wait_event_interruptible_timeout ( dev - > wait_hw_ready ,
2013-07-17 15:13:17 +03:00
dev - > recvd_hw_ready ,
2014-01-14 23:10:10 +02:00
mei_secs_to_jiffies ( MEI_HW_READY_TIMEOUT ) ) ;
2013-03-11 18:27:03 +02:00
mutex_lock ( & dev - > device_lock ) ;
if ( ! err & & ! dev - > recvd_hw_ready ) {
2013-07-17 15:13:17 +03:00
if ( ! err )
err = - ETIMEDOUT ;
2013-03-11 18:27:03 +02:00
dev_err ( & dev - > pdev - > dev ,
2013-07-17 15:13:17 +03:00
" wait hw ready failed. status = %d \n " , err ) ;
return err ;
2013-03-11 18:27:03 +02:00
}
dev - > recvd_hw_ready = false ;
return 0 ;
}
static int mei_me_hw_start ( struct mei_device * dev )
{
int ret = mei_me_hw_ready_wait ( dev ) ;
if ( ret )
return ret ;
dev_dbg ( & dev - > pdev - > dev , " hw is ready \n " ) ;
mei_me_host_set_ready ( dev ) ;
return ret ;
}
2011-05-15 13:43:43 +03:00
/**
2012-06-25 23:46:28 +03:00
* mei_hbuf_filled_slots - gets number of device filled buffer slots
2011-05-15 13:43:43 +03:00
*
2013-01-17 19:54:15 +01:00
* @ dev : the device structure
2011-05-15 13:43:43 +03:00
*
* returns number of filled slots
*/
2012-06-25 23:46:28 +03:00
static unsigned char mei_hbuf_filled_slots ( struct mei_device * dev )
2011-05-15 13:43:43 +03:00
{
2013-02-06 14:06:40 +02:00
struct mei_me_hw * hw = to_me_hw ( dev ) ;
2011-05-15 13:43:43 +03:00
char read_ptr , write_ptr ;
2013-02-06 14:06:40 +02:00
hw - > host_hw_state = mei_hcsr_read ( hw ) ;
2012-06-25 23:46:28 +03:00
2013-02-06 14:06:40 +02:00
read_ptr = ( char ) ( ( hw - > host_hw_state & H_CBRP ) > > 8 ) ;
write_ptr = ( char ) ( ( hw - > host_hw_state & H_CBWP ) > > 16 ) ;
2011-05-15 13:43:43 +03:00
return ( unsigned char ) ( write_ptr - read_ptr ) ;
}
/**
2013-04-05 01:05:05 +09:00
* mei_me_hbuf_is_empty - checks if host buffer is empty .
2011-05-15 13:43:43 +03:00
*
* @ dev : the device structure
*
2012-06-25 23:46:28 +03:00
* returns true if empty , false - otherwise .
2011-05-15 13:43:43 +03:00
*/
2013-02-06 14:06:41 +02:00
static bool mei_me_hbuf_is_empty ( struct mei_device * dev )
2011-05-15 13:43:43 +03:00
{
2012-06-25 23:46:28 +03:00
return mei_hbuf_filled_slots ( dev ) = = 0 ;
2011-05-15 13:43:43 +03:00
}
/**
2013-02-06 14:06:41 +02:00
* mei_me_hbuf_empty_slots - counts write empty slots .
2011-05-15 13:43:43 +03:00
*
* @ dev : the device structure
*
* returns - 1 ( ESLOTS_OVERFLOW ) if overflow , otherwise empty slots count
*/
2013-02-06 14:06:41 +02:00
static int mei_me_hbuf_empty_slots ( struct mei_device * dev )
2011-05-15 13:43:43 +03:00
{
2012-06-25 23:46:27 +03:00
unsigned char filled_slots , empty_slots ;
2011-05-15 13:43:43 +03:00
2012-06-25 23:46:28 +03:00
filled_slots = mei_hbuf_filled_slots ( dev ) ;
2012-06-25 23:46:27 +03:00
empty_slots = dev - > hbuf_depth - filled_slots ;
2011-05-15 13:43:43 +03:00
/* check for overflow */
2012-06-25 23:46:27 +03:00
if ( filled_slots > dev - > hbuf_depth )
2011-05-15 13:43:43 +03:00
return - EOVERFLOW ;
return empty_slots ;
}
2013-02-06 14:06:41 +02:00
static size_t mei_me_hbuf_max_len ( const struct mei_device * dev )
{
return dev - > hbuf_depth * sizeof ( u32 ) - sizeof ( struct mei_msg_hdr ) ;
}
2011-05-15 13:43:43 +03:00
/**
* mei_write_message - writes a message to mei device .
*
* @ dev : the device structure
2013-01-17 19:54:15 +01:00
* @ header : mei HECI header of message
2012-12-25 19:05:59 +02:00
* @ buf : message payload will be written
2011-05-15 13:43:43 +03:00
*
2012-03-14 14:39:42 +02:00
* This function returns - EIO if write has failed
2011-05-15 13:43:43 +03:00
*/
2013-02-06 14:06:41 +02:00
static int mei_me_write_message ( struct mei_device * dev ,
struct mei_msg_hdr * header ,
unsigned char * buf )
2011-05-15 13:43:43 +03:00
{
2013-02-06 14:06:40 +02:00
struct mei_me_hw * hw = to_me_hw ( dev ) ;
2013-03-11 18:27:02 +02:00
unsigned long rem ;
2012-12-25 19:05:59 +02:00
unsigned long length = header - > length ;
2012-06-19 09:13:35 +03:00
u32 * reg_buf = ( u32 * ) buf ;
2013-01-08 23:07:30 +02:00
u32 hcsr ;
2013-03-11 18:27:02 +02:00
u32 dw_cnt ;
2012-06-19 09:13:35 +03:00
int i ;
int empty_slots ;
2011-05-15 13:43:43 +03:00
2012-12-25 19:06:00 +02:00
dev_dbg ( & dev - > pdev - > dev , MEI_HDR_FMT , MEI_HDR_PRM ( header ) ) ;
2011-05-15 13:43:43 +03:00
2012-06-25 23:46:28 +03:00
empty_slots = mei_hbuf_empty_slots ( dev ) ;
2012-06-19 09:13:35 +03:00
dev_dbg ( & dev - > pdev - > dev , " empty slots = %hu. \n " , empty_slots ) ;
2011-05-15 13:43:43 +03:00
2012-07-04 19:24:52 +03:00
dw_cnt = mei_data2slots ( length ) ;
2012-06-19 09:13:35 +03:00
if ( empty_slots < 0 | | dw_cnt > empty_slots )
2012-03-14 14:39:42 +02:00
return - EIO ;
2011-05-15 13:43:43 +03:00
2013-03-27 16:58:29 +02:00
mei_me_reg_write ( hw , H_CB_WW , * ( ( u32 * ) header ) ) ;
2011-05-15 13:43:43 +03:00
2012-06-19 09:13:35 +03:00
for ( i = 0 ; i < length / 4 ; i + + )
2013-03-27 16:58:29 +02:00
mei_me_reg_write ( hw , H_CB_WW , reg_buf [ i ] ) ;
2011-05-15 13:43:43 +03:00
2012-06-19 09:13:35 +03:00
rem = length & 0x3 ;
if ( rem > 0 ) {
u32 reg = 0 ;
memcpy ( & reg , & buf [ length - rem ] , rem ) ;
2013-03-27 16:58:29 +02:00
mei_me_reg_write ( hw , H_CB_WW , reg ) ;
2011-05-15 13:43:43 +03:00
}
2013-02-06 14:06:40 +02:00
hcsr = mei_hcsr_read ( hw ) | H_IG ;
mei_hcsr_set ( hw , hcsr ) ;
2013-02-06 14:06:41 +02:00
if ( ! mei_me_hw_is_ready ( dev ) )
2012-03-14 14:39:42 +02:00
return - EIO ;
2011-05-15 13:43:43 +03:00
2012-03-14 14:39:42 +02:00
return 0 ;
2011-05-15 13:43:43 +03:00
}
/**
2013-02-06 14:06:41 +02:00
* mei_me_count_full_read_slots - counts read full slots .
2011-05-15 13:43:43 +03:00
*
* @ dev : the device structure
*
* returns - 1 ( ESLOTS_OVERFLOW ) if overflow , otherwise filled slots count
*/
2013-02-06 14:06:41 +02:00
static int mei_me_count_full_read_slots ( struct mei_device * dev )
2011-05-15 13:43:43 +03:00
{
2013-02-06 14:06:40 +02:00
struct mei_me_hw * hw = to_me_hw ( dev ) ;
2011-05-15 13:43:43 +03:00
char read_ptr , write_ptr ;
unsigned char buffer_depth , filled_slots ;
2013-03-27 16:58:29 +02:00
hw - > me_hw_state = mei_me_mecsr_read ( hw ) ;
2013-02-06 14:06:40 +02:00
buffer_depth = ( unsigned char ) ( ( hw - > me_hw_state & ME_CBD_HRA ) > > 24 ) ;
read_ptr = ( char ) ( ( hw - > me_hw_state & ME_CBRP_HRA ) > > 8 ) ;
write_ptr = ( char ) ( ( hw - > me_hw_state & ME_CBWP_HRA ) > > 16 ) ;
2011-05-15 13:43:43 +03:00
filled_slots = ( unsigned char ) ( write_ptr - read_ptr ) ;
/* check for overflow */
if ( filled_slots > buffer_depth )
return - EOVERFLOW ;
dev_dbg ( & dev - > pdev - > dev , " filled_slots =%08x \n " , filled_slots ) ;
return ( int ) filled_slots ;
}
/**
2013-02-06 14:06:41 +02:00
* mei_me_read_slots - reads a message from mei device .
2011-05-15 13:43:43 +03:00
*
* @ dev : the device structure
* @ buffer : message buffer will be written
* @ buffer_length : message size will be read
*/
2013-02-06 14:06:41 +02:00
static int mei_me_read_slots ( struct mei_device * dev , unsigned char * buffer ,
2012-02-09 19:25:54 +02:00
unsigned long buffer_length )
2011-05-15 13:43:43 +03:00
{
2013-02-06 14:06:40 +02:00
struct mei_me_hw * hw = to_me_hw ( dev ) ;
2012-02-09 19:25:54 +02:00
u32 * reg_buf = ( u32 * ) buffer ;
2013-01-08 23:07:30 +02:00
u32 hcsr ;
2011-05-15 13:43:43 +03:00
2012-02-09 19:25:54 +02:00
for ( ; buffer_length > = sizeof ( u32 ) ; buffer_length - = sizeof ( u32 ) )
2013-02-06 14:06:41 +02:00
* reg_buf + + = mei_me_mecbrw_read ( dev ) ;
2011-05-15 13:43:43 +03:00
if ( buffer_length > 0 ) {
2013-02-06 14:06:41 +02:00
u32 reg = mei_me_mecbrw_read ( dev ) ;
2012-02-09 19:25:54 +02:00
memcpy ( reg_buf , & reg , buffer_length ) ;
2011-05-15 13:43:43 +03:00
}
2013-02-06 14:06:40 +02:00
hcsr = mei_hcsr_read ( hw ) | H_IG ;
mei_hcsr_set ( hw , hcsr ) ;
2013-02-06 14:06:41 +02:00
return 0 ;
2011-05-15 13:43:43 +03:00
}
2013-02-06 14:06:42 +02:00
/**
* mei_me_irq_quick_handler - The ISR of the MEI device
*
* @ irq : The irq number
* @ dev_id : pointer to the device structure
*
* returns irqreturn_t
*/
irqreturn_t mei_me_irq_quick_handler ( int irq , void * dev_id )
{
struct mei_device * dev = ( struct mei_device * ) dev_id ;
struct mei_me_hw * hw = to_me_hw ( dev ) ;
u32 csr_reg = mei_hcsr_read ( hw ) ;
if ( ( csr_reg & H_IS ) ! = H_IS )
return IRQ_NONE ;
/* clear H_IS bit in H_CSR */
2013-03-27 16:58:29 +02:00
mei_me_reg_write ( hw , H_CSR , csr_reg ) ;
2013-02-06 14:06:42 +02:00
return IRQ_WAKE_THREAD ;
}
/**
* mei_me_irq_thread_handler - function called after ISR to handle the interrupt
* processing .
*
* @ irq : The irq number
* @ dev_id : pointer to the device structure
*
* returns irqreturn_t
*
*/
irqreturn_t mei_me_irq_thread_handler ( int irq , void * dev_id )
{
struct mei_device * dev = ( struct mei_device * ) dev_id ;
struct mei_cl_cb complete_list ;
s32 slots ;
2014-01-08 20:19:21 +02:00
int rets = 0 ;
2013-02-06 14:06:42 +02:00
dev_dbg ( & dev - > pdev - > dev , " function called after ISR to handle the interrupt processing. \n " ) ;
/* initialize our complete list */
mutex_lock ( & dev - > device_lock ) ;
mei_io_list_init ( & complete_list ) ;
/* Ack the interrupt here
* In case of MSI we don ' t go through the quick handler */
if ( pci_dev_msi_enabled ( dev - > pdev ) )
mei_clear_interrupts ( dev ) ;
/* check if ME wants a reset */
2014-01-12 00:36:09 +02:00
if ( ! mei_hw_is_ready ( dev ) & & dev - > dev_state ! = MEI_DEV_RESETTING ) {
2014-01-08 20:19:21 +02:00
dev_warn ( & dev - > pdev - > dev , " FW not ready: resetting. \n " ) ;
schedule_work ( & dev - > reset_work ) ;
goto end ;
2013-02-06 14:06:42 +02:00
}
/* check if we need to start the dev */
if ( ! mei_host_is_ready ( dev ) ) {
if ( mei_hw_is_ready ( dev ) ) {
dev_dbg ( & dev - > pdev - > dev , " we need to start the dev. \n " ) ;
2013-03-11 18:27:03 +02:00
dev - > recvd_hw_ready = true ;
wake_up_interruptible ( & dev - > wait_hw_ready ) ;
2013-02-06 14:06:42 +02:00
} else {
2014-01-08 20:19:21 +02:00
2013-03-10 13:56:07 +02:00
dev_dbg ( & dev - > pdev - > dev , " Reset Completed. \n " ) ;
mei_me_hw_reset_release ( dev ) ;
2013-02-06 14:06:42 +02:00
}
2014-01-08 20:19:21 +02:00
goto end ;
2013-02-06 14:06:42 +02:00
}
/* check slots available for reading */
slots = mei_count_full_read_slots ( dev ) ;
while ( slots > 0 ) {
2014-01-08 20:19:21 +02:00
dev_dbg ( & dev - > pdev - > dev , " slots to read = %08x \n " , slots ) ;
2013-02-06 14:06:42 +02:00
rets = mei_irq_read_handler ( dev , & complete_list , & slots ) ;
2014-01-12 00:36:09 +02:00
if ( rets & & dev - > dev_state ! = MEI_DEV_RESETTING ) {
2014-01-08 20:19:21 +02:00
schedule_work ( & dev - > reset_work ) ;
2013-02-06 14:06:42 +02:00
goto end ;
2014-01-08 20:19:21 +02:00
}
2013-02-06 14:06:42 +02:00
}
2014-01-08 20:19:21 +02:00
2013-02-06 14:06:42 +02:00
rets = mei_irq_write_handler ( dev , & complete_list ) ;
2014-01-08 20:19:21 +02:00
dev - > hbuf_is_ready = mei_hbuf_is_ready ( dev ) ;
2013-02-06 14:06:42 +02:00
2013-03-17 11:41:20 +02:00
mei_irq_compl_handler ( dev , & complete_list ) ;
2013-02-06 14:06:42 +02:00
2014-01-08 20:19:21 +02:00
end :
dev_dbg ( & dev - > pdev - > dev , " interrupt thread end ret = %d \n " , rets ) ;
mutex_unlock ( & dev - > device_lock ) ;
2013-02-06 14:06:42 +02:00
return IRQ_HANDLED ;
}
2013-02-06 14:06:41 +02:00
static const struct mei_hw_ops mei_me_hw_ops = {
. host_is_ready = mei_me_host_is_ready ,
. hw_is_ready = mei_me_hw_is_ready ,
. hw_reset = mei_me_hw_reset ,
2013-03-11 18:27:03 +02:00
. hw_config = mei_me_hw_config ,
. hw_start = mei_me_hw_start ,
2013-02-06 14:06:41 +02:00
. intr_clear = mei_me_intr_clear ,
. intr_enable = mei_me_intr_enable ,
. intr_disable = mei_me_intr_disable ,
. hbuf_free_slots = mei_me_hbuf_empty_slots ,
. hbuf_is_ready = mei_me_hbuf_is_empty ,
. hbuf_max_len = mei_me_hbuf_max_len ,
. write = mei_me_write_message ,
. rdbuf_full_slots = mei_me_count_full_read_slots ,
. read_hdr = mei_me_mecbrw_read ,
. read = mei_me_read_slots
} ;
2013-02-06 14:06:40 +02:00
/**
2013-04-05 01:05:05 +09:00
* mei_me_dev_init - allocates and initializes the mei device structure
2013-02-06 14:06:40 +02:00
*
* @ pdev : The pci device structure
*
* returns The mei_device_device pointer on success , NULL on failure .
*/
struct mei_device * mei_me_dev_init ( struct pci_dev * pdev )
{
struct mei_device * dev ;
dev = kzalloc ( sizeof ( struct mei_device ) +
sizeof ( struct mei_me_hw ) , GFP_KERNEL ) ;
if ( ! dev )
return NULL ;
mei_device_init ( dev ) ;
2013-02-06 14:06:41 +02:00
dev - > ops = & mei_me_hw_ops ;
2013-02-06 14:06:40 +02:00
dev - > pdev = pdev ;
return dev ;
}
2013-02-06 14:06:42 +02:00