2009-11-29 18:15:25 +03:00
/****************************************************************************
2013-08-30 02:32:48 +04:00
* Driver for Solarflare network controllers and boards
* Copyright 2008 - 2013 Solarflare Communications Inc .
2009-11-29 18:15:25 +03:00
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation , incorporated herein by reference .
*/
# ifndef EFX_MCDI_H
# define EFX_MCDI_H
/**
2012-10-26 20:53:11 +04:00
* enum efx_mcdi_state - MCDI request handling state
2009-11-29 18:15:25 +03:00
* @ MCDI_STATE_QUIESCENT : No pending MCDI requests . If the caller holds the
2012-10-26 20:53:11 +04:00
* mcdi @ iface_lock then they are able to move to % MCDI_STATE_RUNNING
2013-08-28 02:12:31 +04:00
* @ MCDI_STATE_RUNNING_SYNC : There is a synchronous MCDI request pending .
* Only the thread that moved into this state is allowed to move out of it .
* @ MCDI_STATE_RUNNING_ASYNC : There is an asynchronous MCDI request pending .
2015-12-23 11:57:18 +03:00
* @ MCDI_STATE_PROXY_WAIT : An MCDI request has completed with a response that
* indicates we must wait for a proxy try again message .
2009-11-29 18:15:25 +03:00
* @ MCDI_STATE_COMPLETED : An MCDI request has completed , but the owning thread
* has not yet consumed the result . For all other threads , equivalent to
2012-10-26 20:53:11 +04:00
* % MCDI_STATE_RUNNING .
2009-11-29 18:15:25 +03:00
*/
enum efx_mcdi_state {
MCDI_STATE_QUIESCENT ,
2013-08-28 02:12:31 +04:00
MCDI_STATE_RUNNING_SYNC ,
MCDI_STATE_RUNNING_ASYNC ,
2015-12-23 11:57:18 +03:00
MCDI_STATE_PROXY_WAIT ,
2009-11-29 18:15:25 +03:00
MCDI_STATE_COMPLETED ,
} ;
sfc:On MCDI timeout, issue an FLR (and mark MCDI to fail-fast)
When an MCDI command times out (whether or not we find it
completed when we poll), call efx_mcdi_abandon(), which tells
all subsequent MCDI calls to fail-fast, and queues up an FLR.
Because an FLR doesn't lead to receiving any reboot even from
the MC (unlike most other types of reset), we have to call
efx_ef10_reset_mc_allocations.
In efx_start_all(), if a reset (of any kind) is pending, we
bail out.
Without this, attempts to reconfigure (e.g. change mtu) can
cause driver/mc state inconsistency if the first MCDI call
triggers an FLR.
For similar reasons, on EF10, in
efx_reset_down(method=RESET_TYPE_MCDI_TIMEOUT), set the number
of active queues to zero before calling efx_stop_all().
And, on farch, in efx_reset_up(method=RESET_TYPE_MCDI_TIMEOUT),
set active_queues and flushes pending & outstanding to zero.
efx_mcdi_mode_{poll,event}() should not take us out of fail-fast
mode. Instead, this is done by efx_mcdi_reset() after the FLR
completes.
The new FLR reset_type RESET_TYPE_MCDI_TIMEOUT doesn't really
fit into the hierarchy of reset 'scopes' whereby efx_reset()
decides some resets subsume others. Thus, it uses separate logic.
Also, fixed up some inconsistency around RESET_TYPE_MC_BIST,
which was in the wrong place in that hierarchy.
Signed-off-by: Shradha Shah <sshah@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-04-16 22:27:48 +04:00
/**
* enum efx_mcdi_mode - MCDI transaction mode
* @ MCDI_MODE_POLL : poll for MCDI completion , until timeout
* @ MCDI_MODE_EVENTS : wait for an mcdi_event . On timeout , poll once
* @ MCDI_MODE_FAIL : we think MCDI is dead , so fail - fast all calls
*/
2009-11-29 18:15:25 +03:00
enum efx_mcdi_mode {
MCDI_MODE_POLL ,
MCDI_MODE_EVENTS ,
sfc:On MCDI timeout, issue an FLR (and mark MCDI to fail-fast)
When an MCDI command times out (whether or not we find it
completed when we poll), call efx_mcdi_abandon(), which tells
all subsequent MCDI calls to fail-fast, and queues up an FLR.
Because an FLR doesn't lead to receiving any reboot even from
the MC (unlike most other types of reset), we have to call
efx_ef10_reset_mc_allocations.
In efx_start_all(), if a reset (of any kind) is pending, we
bail out.
Without this, attempts to reconfigure (e.g. change mtu) can
cause driver/mc state inconsistency if the first MCDI call
triggers an FLR.
For similar reasons, on EF10, in
efx_reset_down(method=RESET_TYPE_MCDI_TIMEOUT), set the number
of active queues to zero before calling efx_stop_all().
And, on farch, in efx_reset_up(method=RESET_TYPE_MCDI_TIMEOUT),
set active_queues and flushes pending & outstanding to zero.
efx_mcdi_mode_{poll,event}() should not take us out of fail-fast
mode. Instead, this is done by efx_mcdi_reset() after the FLR
completes.
The new FLR reset_type RESET_TYPE_MCDI_TIMEOUT doesn't really
fit into the hierarchy of reset 'scopes' whereby efx_reset()
decides some resets subsume others. Thus, it uses separate logic.
Also, fixed up some inconsistency around RESET_TYPE_MC_BIST,
which was in the wrong place in that hierarchy.
Signed-off-by: Shradha Shah <sshah@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-04-16 22:27:48 +04:00
MCDI_MODE_FAIL ,
2009-11-29 18:15:25 +03:00
} ;
/**
2012-10-26 20:53:11 +04:00
* struct efx_mcdi_iface - MCDI protocol context
2013-08-28 02:12:31 +04:00
* @ efx : The associated NIC .
2012-10-26 20:53:11 +04:00
* @ state : Request handling state . Waited for by @ wq .
2009-11-29 18:15:25 +03:00
* @ mode : Poll for mcdi completion , or wait for an mcdi_event .
2012-10-26 20:53:11 +04:00
* @ wq : Wait queue for threads waiting for @ state ! = % MCDI_STATE_RUNNING
2013-06-20 14:40:07 +04:00
* @ new_epoch : Indicates start of day or start of MC reboot recovery
2013-08-28 02:12:31 +04:00
* @ iface_lock : Serialises access to @ seqno , @ credits and response metadata
2009-11-29 18:15:25 +03:00
* @ seqno : The next sequence number to use for mcdi requests .
* @ credits : Number of spurious MCDI completion events allowed before we
2012-10-26 20:53:11 +04:00
* trigger a fatal error
2012-10-09 00:43:00 +04:00
* @ resprc : Response error / success code ( Linux numbering )
2012-09-19 03:56:18 +04:00
* @ resp_hdr_len : Response header length
* @ resp_data_len : Response data ( SDU or error ) length
2013-08-28 02:12:31 +04:00
* @ async_lock : Serialises access to @ async_list while event processing is
* enabled
* @ async_list : Queue of asynchronous requests
* @ async_timer : Timer for asynchronous request timeout
2015-05-27 15:13:54 +03:00
* @ logging_buffer : buffer that may be used to build MCDI tracing messages
2015-05-27 15:14:01 +03:00
* @ logging_enabled : whether to trace MCDI
2015-12-23 11:57:18 +03:00
* @ proxy_rx_handle : Most recently received proxy authorisation handle
* @ proxy_rx_status : Status of most recent proxy authorisation
* @ proxy_rx_wq : Wait queue for updates to proxy_rx_handle
2009-11-29 18:15:25 +03:00
*/
struct efx_mcdi_iface {
2013-08-28 02:12:31 +04:00
struct efx_nic * efx ;
2013-08-28 02:04:29 +04:00
enum efx_mcdi_state state ;
2012-10-26 20:53:11 +04:00
enum efx_mcdi_mode mode ;
2009-11-29 18:15:25 +03:00
wait_queue_head_t wq ;
spinlock_t iface_lock ;
2013-06-20 14:40:07 +04:00
bool new_epoch ;
2009-11-29 18:15:25 +03:00
unsigned int credits ;
unsigned int seqno ;
2012-10-09 00:43:00 +04:00
int resprc ;
2015-12-23 11:56:40 +03:00
int resprc_raw ;
2012-09-19 03:56:18 +04:00
size_t resp_hdr_len ;
size_t resp_data_len ;
2013-08-28 02:12:31 +04:00
spinlock_t async_lock ;
struct list_head async_list ;
struct timer_list async_timer ;
2015-05-27 15:13:54 +03:00
# ifdef CONFIG_SFC_MCDI_LOGGING
char * logging_buffer ;
2015-05-27 15:14:01 +03:00
bool logging_enabled ;
2015-05-27 15:13:54 +03:00
# endif
2015-12-23 11:57:18 +03:00
unsigned int proxy_rx_handle ;
int proxy_rx_status ;
wait_queue_head_t proxy_rx_wq ;
2009-11-29 18:15:25 +03:00
} ;
2012-01-07 00:25:39 +04:00
struct efx_mcdi_mon {
struct efx_buffer dma_buf ;
struct mutex update_lock ;
unsigned long last_update ;
struct device * device ;
struct efx_mcdi_mon_attribute * attrs ;
2013-11-28 06:54:31 +04:00
struct attribute_group group ;
const struct attribute_group * groups [ 2 ] ;
2012-01-07 00:25:39 +04:00
unsigned int n_attrs ;
} ;
2012-11-28 08:38:14 +04:00
struct efx_mcdi_mtd_partition {
struct efx_mtd_partition common ;
bool updating ;
2013-08-29 22:19:29 +04:00
u16 nvram_type ;
2012-11-28 08:38:14 +04:00
u16 fw_subtype ;
} ;
# define to_efx_mcdi_mtd_partition(mtd) \
container_of ( mtd , struct efx_mcdi_mtd_partition , common . mtd )
2012-09-18 05:33:56 +04:00
/**
* struct efx_mcdi_data - extra state for NICs that implement MCDI
* @ iface : Interface / protocol state
* @ hwmon : Hardware monitor state
2013-10-16 21:32:34 +04:00
* @ fn_flags : Flags for this function , as returned by % MC_CMD_DRV_ATTACH .
2012-09-18 05:33:56 +04:00
*/
struct efx_mcdi_data {
struct efx_mcdi_iface iface ;
# ifdef CONFIG_SFC_MCDI_MON
struct efx_mcdi_mon hwmon ;
# endif
2013-10-16 21:32:34 +04:00
u32 fn_flags ;
2012-09-18 05:33:56 +04:00
} ;
sfc:On MCDI timeout, issue an FLR (and mark MCDI to fail-fast)
When an MCDI command times out (whether or not we find it
completed when we poll), call efx_mcdi_abandon(), which tells
all subsequent MCDI calls to fail-fast, and queues up an FLR.
Because an FLR doesn't lead to receiving any reboot even from
the MC (unlike most other types of reset), we have to call
efx_ef10_reset_mc_allocations.
In efx_start_all(), if a reset (of any kind) is pending, we
bail out.
Without this, attempts to reconfigure (e.g. change mtu) can
cause driver/mc state inconsistency if the first MCDI call
triggers an FLR.
For similar reasons, on EF10, in
efx_reset_down(method=RESET_TYPE_MCDI_TIMEOUT), set the number
of active queues to zero before calling efx_stop_all().
And, on farch, in efx_reset_up(method=RESET_TYPE_MCDI_TIMEOUT),
set active_queues and flushes pending & outstanding to zero.
efx_mcdi_mode_{poll,event}() should not take us out of fail-fast
mode. Instead, this is done by efx_mcdi_reset() after the FLR
completes.
The new FLR reset_type RESET_TYPE_MCDI_TIMEOUT doesn't really
fit into the hierarchy of reset 'scopes' whereby efx_reset()
decides some resets subsume others. Thus, it uses separate logic.
Also, fixed up some inconsistency around RESET_TYPE_MC_BIST,
which was in the wrong place in that hierarchy.
Signed-off-by: Shradha Shah <sshah@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-04-16 22:27:48 +04:00
static inline struct efx_mcdi_iface * efx_mcdi ( struct efx_nic * efx )
{
2016-12-02 18:51:33 +03:00
EFX_WARN_ON_PARANOID ( ! efx - > mcdi ) ;
sfc:On MCDI timeout, issue an FLR (and mark MCDI to fail-fast)
When an MCDI command times out (whether or not we find it
completed when we poll), call efx_mcdi_abandon(), which tells
all subsequent MCDI calls to fail-fast, and queues up an FLR.
Because an FLR doesn't lead to receiving any reboot even from
the MC (unlike most other types of reset), we have to call
efx_ef10_reset_mc_allocations.
In efx_start_all(), if a reset (of any kind) is pending, we
bail out.
Without this, attempts to reconfigure (e.g. change mtu) can
cause driver/mc state inconsistency if the first MCDI call
triggers an FLR.
For similar reasons, on EF10, in
efx_reset_down(method=RESET_TYPE_MCDI_TIMEOUT), set the number
of active queues to zero before calling efx_stop_all().
And, on farch, in efx_reset_up(method=RESET_TYPE_MCDI_TIMEOUT),
set active_queues and flushes pending & outstanding to zero.
efx_mcdi_mode_{poll,event}() should not take us out of fail-fast
mode. Instead, this is done by efx_mcdi_reset() after the FLR
completes.
The new FLR reset_type RESET_TYPE_MCDI_TIMEOUT doesn't really
fit into the hierarchy of reset 'scopes' whereby efx_reset()
decides some resets subsume others. Thus, it uses separate logic.
Also, fixed up some inconsistency around RESET_TYPE_MC_BIST,
which was in the wrong place in that hierarchy.
Signed-off-by: Shradha Shah <sshah@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-04-16 22:27:48 +04:00
return & efx - > mcdi - > iface ;
}
2012-09-18 05:33:56 +04:00
# ifdef CONFIG_SFC_MCDI_MON
static inline struct efx_mcdi_mon * efx_mcdi_mon ( struct efx_nic * efx )
{
2016-12-02 18:51:33 +03:00
EFX_WARN_ON_PARANOID ( ! efx - > mcdi ) ;
2012-09-18 05:33:56 +04:00
return & efx - > mcdi - > hwmon ;
}
# endif
2013-09-23 22:37:59 +04:00
int efx_mcdi_init ( struct efx_nic * efx ) ;
2017-02-08 19:52:10 +03:00
void efx_mcdi_detach ( struct efx_nic * efx ) ;
2013-09-23 22:37:59 +04:00
void efx_mcdi_fini ( struct efx_nic * efx ) ;
2009-11-29 18:15:25 +03:00
2013-09-23 22:37:59 +04:00
int efx_mcdi_rpc ( struct efx_nic * efx , unsigned cmd , const efx_dword_t * inbuf ,
size_t inlen , efx_dword_t * outbuf , size_t outlen ,
size_t * outlen_actual ) ;
2013-05-31 21:36:12 +04:00
int efx_mcdi_rpc_quiet ( struct efx_nic * efx , unsigned cmd ,
const efx_dword_t * inbuf , size_t inlen ,
efx_dword_t * outbuf , size_t outlen ,
size_t * outlen_actual ) ;
2013-09-23 22:37:59 +04:00
int efx_mcdi_rpc_start ( struct efx_nic * efx , unsigned cmd ,
const efx_dword_t * inbuf , size_t inlen ) ;
int efx_mcdi_rpc_finish ( struct efx_nic * efx , unsigned cmd , size_t inlen ,
2012-09-14 20:31:41 +04:00
efx_dword_t * outbuf , size_t outlen ,
2009-11-29 18:15:25 +03:00
size_t * outlen_actual ) ;
2013-05-31 21:36:12 +04:00
int efx_mcdi_rpc_finish_quiet ( struct efx_nic * efx , unsigned cmd ,
size_t inlen , efx_dword_t * outbuf ,
size_t outlen , size_t * outlen_actual ) ;
2009-11-29 18:15:25 +03:00
2013-08-28 02:12:31 +04:00
typedef void efx_mcdi_async_completer ( struct efx_nic * efx ,
unsigned long cookie , int rc ,
efx_dword_t * outbuf ,
size_t outlen_actual ) ;
2013-09-23 22:37:59 +04:00
int efx_mcdi_rpc_async ( struct efx_nic * efx , unsigned int cmd ,
const efx_dword_t * inbuf , size_t inlen , size_t outlen ,
efx_mcdi_async_completer * complete ,
unsigned long cookie ) ;
2013-05-31 21:36:12 +04:00
int efx_mcdi_rpc_async_quiet ( struct efx_nic * efx , unsigned int cmd ,
const efx_dword_t * inbuf , size_t inlen ,
size_t outlen ,
efx_mcdi_async_completer * complete ,
unsigned long cookie ) ;
void efx_mcdi_display_error ( struct efx_nic * efx , unsigned cmd ,
size_t inlen , efx_dword_t * outbuf ,
size_t outlen , int rc ) ;
2012-09-14 20:31:41 +04:00
2013-09-23 22:37:59 +04:00
int efx_mcdi_poll_reboot ( struct efx_nic * efx ) ;
void efx_mcdi_mode_poll ( struct efx_nic * efx ) ;
void efx_mcdi_mode_event ( struct efx_nic * efx ) ;
void efx_mcdi_flush_async ( struct efx_nic * efx ) ;
2009-11-29 18:15:25 +03:00
2013-09-23 22:37:59 +04:00
void efx_mcdi_process_event ( struct efx_channel * channel , efx_qword_t * event ) ;
void efx_mcdi_sensor_event ( struct efx_nic * efx , efx_qword_t * ev ) ;
2009-11-29 18:15:25 +03:00
2012-09-14 20:31:41 +04:00
/* We expect that 16- and 32-bit fields in MCDI requests and responses
2012-10-11 02:20:17 +04:00
* are appropriately aligned , but 64 - bit fields are only
* 32 - bit - aligned . Also , on Siena we must copy to the MC shared
* memory strictly 32 bits at a time , so add any necessary padding .
2012-09-14 20:31:41 +04:00
*/
2015-05-20 13:10:41 +03:00
# define _MCDI_DECLARE_BUF(_name, _len) \
2012-09-14 20:31:41 +04:00
efx_dword_t _name [ DIV_ROUND_UP ( _len , 4 ) ]
2015-05-20 13:10:41 +03:00
# define MCDI_DECLARE_BUF(_name, _len) \
_MCDI_DECLARE_BUF ( _name , _len ) = { { { 0 } } }
# define MCDI_DECLARE_BUF_ERR(_name) \
MCDI_DECLARE_BUF ( _name , 8 )
2012-09-14 20:30:58 +04:00
# define _MCDI_PTR(_buf, _offset) \
( ( u8 * ) ( _buf ) + ( _offset ) )
2012-09-14 20:30:44 +04:00
# define MCDI_PTR(_buf, _field) \
2012-09-14 20:30:58 +04:00
_MCDI_PTR ( _buf , MC_CMD_ # # _field # # _OFST )
2012-09-14 20:31:41 +04:00
# define _MCDI_CHECK_ALIGN(_ofst, _align) \
( ( _ofst ) + BUILD_BUG_ON_ZERO ( ( _ofst ) & ( _align - 1 ) ) )
2012-09-14 20:30:44 +04:00
# define _MCDI_DWORD(_buf, _field) \
2012-09-14 20:31:41 +04:00
( ( _buf ) + ( _MCDI_CHECK_ALIGN ( MC_CMD_ # # _field # # _OFST , 4 ) > > 2 ) )
2012-09-14 20:30:10 +04:00
2013-08-29 22:19:29 +04:00
# define MCDI_WORD(_buf, _field) \
( ( u16 ) BUILD_BUG_ON_ZERO ( MC_CMD_ # # _field # # _LEN ! = 2 ) + \
le16_to_cpu ( * ( __force const __le16 * ) MCDI_PTR ( _buf , _field ) ) )
2012-09-14 20:30:44 +04:00
# define MCDI_SET_DWORD(_buf, _field, _value) \
EFX_POPULATE_DWORD_1 ( * _MCDI_DWORD ( _buf , _field ) , EFX_DWORD_0 , _value )
# define MCDI_DWORD(_buf, _field) \
EFX_DWORD_FIELD ( * _MCDI_DWORD ( _buf , _field ) , EFX_DWORD_0 )
2012-10-11 02:24:51 +04:00
# define MCDI_POPULATE_DWORD_1(_buf, _field, _name1, _value1) \
EFX_POPULATE_DWORD_1 ( * _MCDI_DWORD ( _buf , _field ) , \
MC_CMD_ # # _name1 , _value1 )
# define MCDI_POPULATE_DWORD_2(_buf, _field, _name1, _value1, \
_name2 , _value2 ) \
EFX_POPULATE_DWORD_2 ( * _MCDI_DWORD ( _buf , _field ) , \
MC_CMD_ # # _name1 , _value1 , \
MC_CMD_ # # _name2 , _value2 )
# define MCDI_POPULATE_DWORD_3(_buf, _field, _name1, _value1, \
_name2 , _value2 , _name3 , _value3 ) \
EFX_POPULATE_DWORD_3 ( * _MCDI_DWORD ( _buf , _field ) , \
MC_CMD_ # # _name1 , _value1 , \
MC_CMD_ # # _name2 , _value2 , \
MC_CMD_ # # _name3 , _value3 )
# define MCDI_POPULATE_DWORD_4(_buf, _field, _name1, _value1, \
_name2 , _value2 , _name3 , _value3 , \
_name4 , _value4 ) \
EFX_POPULATE_DWORD_4 ( * _MCDI_DWORD ( _buf , _field ) , \
MC_CMD_ # # _name1 , _value1 , \
MC_CMD_ # # _name2 , _value2 , \
MC_CMD_ # # _name3 , _value3 , \
MC_CMD_ # # _name4 , _value4 )
# define MCDI_POPULATE_DWORD_5(_buf, _field, _name1, _value1, \
_name2 , _value2 , _name3 , _value3 , \
_name4 , _value4 , _name5 , _value5 ) \
EFX_POPULATE_DWORD_5 ( * _MCDI_DWORD ( _buf , _field ) , \
MC_CMD_ # # _name1 , _value1 , \
MC_CMD_ # # _name2 , _value2 , \
MC_CMD_ # # _name3 , _value3 , \
MC_CMD_ # # _name4 , _value4 , \
MC_CMD_ # # _name5 , _value5 )
# define MCDI_POPULATE_DWORD_6(_buf, _field, _name1, _value1, \
_name2 , _value2 , _name3 , _value3 , \
_name4 , _value4 , _name5 , _value5 , \
_name6 , _value6 ) \
EFX_POPULATE_DWORD_6 ( * _MCDI_DWORD ( _buf , _field ) , \
MC_CMD_ # # _name1 , _value1 , \
MC_CMD_ # # _name2 , _value2 , \
MC_CMD_ # # _name3 , _value3 , \
MC_CMD_ # # _name4 , _value4 , \
MC_CMD_ # # _name5 , _value5 , \
MC_CMD_ # # _name6 , _value6 )
# define MCDI_POPULATE_DWORD_7(_buf, _field, _name1, _value1, \
_name2 , _value2 , _name3 , _value3 , \
_name4 , _value4 , _name5 , _value5 , \
_name6 , _value6 , _name7 , _value7 ) \
EFX_POPULATE_DWORD_7 ( * _MCDI_DWORD ( _buf , _field ) , \
MC_CMD_ # # _name1 , _value1 , \
MC_CMD_ # # _name2 , _value2 , \
MC_CMD_ # # _name3 , _value3 , \
MC_CMD_ # # _name4 , _value4 , \
MC_CMD_ # # _name5 , _value5 , \
MC_CMD_ # # _name6 , _value6 , \
MC_CMD_ # # _name7 , _value7 )
2012-10-11 02:20:17 +04:00
# define MCDI_SET_QWORD(_buf, _field, _value) \
do { \
EFX_POPULATE_DWORD_1 ( _MCDI_DWORD ( _buf , _field ) [ 0 ] , \
EFX_DWORD_0 , ( u32 ) ( _value ) ) ; \
EFX_POPULATE_DWORD_1 ( _MCDI_DWORD ( _buf , _field ) [ 1 ] , \
EFX_DWORD_0 , ( u64 ) ( _value ) > > 32 ) ; \
} while ( 0 )
2012-09-14 20:30:44 +04:00
# define MCDI_QWORD(_buf, _field) \
( EFX_DWORD_FIELD ( _MCDI_DWORD ( _buf , _field ) [ 0 ] , EFX_DWORD_0 ) | \
( u64 ) EFX_DWORD_FIELD ( _MCDI_DWORD ( _buf , _field ) [ 1 ] , EFX_DWORD_0 ) < < 32 )
2012-09-14 20:30:58 +04:00
# define MCDI_FIELD(_ptr, _type, _field) \
EFX_EXTRACT_DWORD ( \
* ( efx_dword_t * ) \
_MCDI_PTR ( _ptr , MC_CMD_ # # _type # # _ # # _field # # _OFST & ~ 3 ) , \
MC_CMD_ # # _type # # _ # # _field # # _LBN & 0x1f , \
( MC_CMD_ # # _type # # _ # # _field # # _LBN & 0x1f ) + \
MC_CMD_ # # _type # # _ # # _field # # _WIDTH - 1 )
2012-09-14 20:30:44 +04:00
2012-09-14 20:31:41 +04:00
# define _MCDI_ARRAY_PTR(_buf, _field, _index, _align) \
( _MCDI_PTR ( _buf , _MCDI_CHECK_ALIGN ( MC_CMD_ # # _field # # _OFST , _align ) ) \
+ ( _index ) * _MCDI_CHECK_ALIGN ( MC_CMD_ # # _field # # _LEN , _align ) )
2012-09-14 20:30:58 +04:00
# define MCDI_DECLARE_STRUCT_PTR(_name) \
2012-09-14 20:31:41 +04:00
efx_dword_t * _name
# define MCDI_ARRAY_STRUCT_PTR(_buf, _field, _index) \
( ( efx_dword_t * ) _MCDI_ARRAY_PTR ( _buf , _field , _index , 4 ) )
2012-09-14 20:30:58 +04:00
# define MCDI_VAR_ARRAY_LEN(_len, _field) \
min_t ( size_t , MC_CMD_ # # _field # # _MAXNUM , \
( ( _len ) - MC_CMD_ # # _field # # _OFST ) / MC_CMD_ # # _field # # _LEN )
# define MCDI_ARRAY_WORD(_buf, _field, _index) \
( BUILD_BUG_ON_ZERO ( MC_CMD_ # # _field # # _LEN ! = 2 ) + \
le16_to_cpu ( * ( __force const __le16 * ) \
2012-09-14 20:31:41 +04:00
_MCDI_ARRAY_PTR ( _buf , _field , _index , 2 ) ) )
2012-09-14 20:30:58 +04:00
# define _MCDI_ARRAY_DWORD(_buf, _field, _index) \
( BUILD_BUG_ON_ZERO ( MC_CMD_ # # _field # # _LEN ! = 4 ) + \
2012-09-14 20:31:41 +04:00
( efx_dword_t * ) _MCDI_ARRAY_PTR ( _buf , _field , _index , 4 ) )
2012-09-14 20:30:58 +04:00
# define MCDI_SET_ARRAY_DWORD(_buf, _field, _index, _value) \
EFX_SET_DWORD_FIELD ( * _MCDI_ARRAY_DWORD ( _buf , _field , _index ) , \
EFX_DWORD_0 , _value )
# define MCDI_ARRAY_DWORD(_buf, _field, _index) \
EFX_DWORD_FIELD ( * _MCDI_ARRAY_DWORD ( _buf , _field , _index ) , EFX_DWORD_0 )
2012-10-11 02:20:17 +04:00
# define _MCDI_ARRAY_QWORD(_buf, _field, _index) \
( BUILD_BUG_ON_ZERO ( MC_CMD_ # # _field # # _LEN ! = 8 ) + \
( efx_dword_t * ) _MCDI_ARRAY_PTR ( _buf , _field , _index , 4 ) )
# define MCDI_SET_ARRAY_QWORD(_buf, _field, _index, _value) \
do { \
EFX_SET_DWORD_FIELD ( _MCDI_ARRAY_QWORD ( _buf , _field , _index ) [ 0 ] , \
EFX_DWORD_0 , ( u32 ) ( _value ) ) ; \
EFX_SET_DWORD_FIELD ( _MCDI_ARRAY_QWORD ( _buf , _field , _index ) [ 1 ] , \
EFX_DWORD_0 , ( u64 ) ( _value ) > > 32 ) ; \
} while ( 0 )
2012-01-07 00:25:39 +04:00
# define MCDI_ARRAY_FIELD(_buf, _field1, _type, _index, _field2) \
2012-09-14 20:30:58 +04:00
MCDI_FIELD ( MCDI_ARRAY_STRUCT_PTR ( _buf , _field1 , _index ) , \
_type # # _TYPEDEF , _field2 )
2009-11-29 18:15:25 +03:00
2012-09-14 20:30:44 +04:00
# define MCDI_EVENT_FIELD(_ev, _field) \
EFX_QWORD_FIELD ( _ev , MCDI_EVENT_ # # _field )
2013-09-23 22:37:59 +04:00
void efx_mcdi_print_fwver ( struct efx_nic * efx , char * buf , size_t len ) ;
int efx_mcdi_get_board_cfg ( struct efx_nic * efx , u8 * mac_address ,
u16 * fw_subtype_list , u32 * capabilities ) ;
int efx_mcdi_log_ctrl ( struct efx_nic * efx , bool evq , bool uart , u32 dest_evq ) ;
int efx_mcdi_nvram_types ( struct efx_nic * efx , u32 * nvram_types_out ) ;
int efx_mcdi_nvram_info ( struct efx_nic * efx , unsigned int type ,
size_t * size_out , size_t * erase_size_out ,
bool * protected_out ) ;
int efx_mcdi_nvram_test_all ( struct efx_nic * efx ) ;
int efx_mcdi_handle_assertion ( struct efx_nic * efx ) ;
void efx_mcdi_set_id_led ( struct efx_nic * efx , enum efx_led_mode mode ) ;
int efx_mcdi_wol_filter_set_magic ( struct efx_nic * efx , const u8 * mac ,
int * id_out ) ;
int efx_mcdi_wol_filter_get_magic ( struct efx_nic * efx , int * id_out ) ;
int efx_mcdi_wol_filter_remove ( struct efx_nic * efx , int id ) ;
int efx_mcdi_wol_filter_reset ( struct efx_nic * efx ) ;
int efx_mcdi_flush_rxqs ( struct efx_nic * efx ) ;
int efx_mcdi_port_probe ( struct efx_nic * efx ) ;
void efx_mcdi_port_remove ( struct efx_nic * efx ) ;
int efx_mcdi_port_reconfigure ( struct efx_nic * efx ) ;
int efx_mcdi_port_get_number ( struct efx_nic * efx ) ;
u32 efx_mcdi_phy_get_caps ( struct efx_nic * efx ) ;
void efx_mcdi_process_link_change ( struct efx_nic * efx , efx_qword_t * ev ) ;
int efx_mcdi_set_mac ( struct efx_nic * efx ) ;
2012-09-18 05:33:54 +04:00
# define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1))
2013-09-23 22:37:59 +04:00
void efx_mcdi_mac_start_stats ( struct efx_nic * efx ) ;
void efx_mcdi_mac_stop_stats ( struct efx_nic * efx ) ;
2013-09-30 20:36:50 +04:00
void efx_mcdi_mac_pull_stats ( struct efx_nic * efx ) ;
2013-09-23 22:37:59 +04:00
bool efx_mcdi_mac_check_fault ( struct efx_nic * efx ) ;
enum reset_type efx_mcdi_map_reset_reason ( enum reset_type reason ) ;
int efx_mcdi_reset ( struct efx_nic * efx , enum reset_type method ) ;
2015-07-21 17:09:43 +03:00
int efx_mcdi_set_workaround ( struct efx_nic * efx , u32 type , bool enabled ,
unsigned int * flags ) ;
sfc: Cope with permissions enforcement added to firmware for SR-IOV
* Accept EPERM in some simple cases, the following cases are handled:
1) efx_mcdi_read_assertion()
Unprivileged PCI functions aren't allowed to GET_ASSERTS.
We return success as it's up to the primary PF to deal with asserts.
2) efx_mcdi_mon_probe() in efx_ef10_probe()
Unprivileged PCI functions aren't allowed to read sensor info, and
worrying about sensor data is the primary PF's job.
3) phy_op->reconfigure() in efx_init_port() and efx_reset_up()
Unprivileged functions aren't allowed to MC_CMD_SET_LINK, they just have
to accept the settings (including flow-control, which is what
efx_init_port() is worried about) they've been given.
4) Fallback to GET_WORKAROUNDS in efx_ef10_probe()
Unprivileged PCI functions aren't allowed to set workarounds. So if
efx_mcdi_set_workaround() fails EPERM, use efx_mcdi_get_workarounds()
to find out if workaround_35388 is enabled.
5) If DRV_ATTACH gets EPERM, try without specifying fw-variant
Unprivileged PCI functions have to use a FIRMWARE_ID of 0xffffffff
(MC_CMD_FW_DONT_CARE).
6) Don't try to exit_assertion unless one had fired
Previously we called efx_mcdi_exit_assertion even if
efx_mcdi_read_assertion had received MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS.
This is unnecessary, and the resulting MC_CMD_REBOOT, even if the
AFTER_ASSERTION flag made it a no-op, would fail EPERM for unprivileged
PCI functions.
So make efx_mcdi_read_assertion return whether an assert happened, and only
call efx_mcdi_exit_assertion if it has.
Signed-off-by: Shradha Shah <sshah@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2015-05-06 02:59:18 +03:00
int efx_mcdi_get_workarounds ( struct efx_nic * efx , unsigned int * impl_out ,
unsigned int * enabled_out ) ;
2009-11-29 18:15:25 +03:00
2012-01-07 00:25:39 +04:00
# ifdef CONFIG_SFC_MCDI_MON
2013-09-23 22:37:59 +04:00
int efx_mcdi_mon_probe ( struct efx_nic * efx ) ;
void efx_mcdi_mon_remove ( struct efx_nic * efx ) ;
2012-01-07 00:25:39 +04:00
# else
static inline int efx_mcdi_mon_probe ( struct efx_nic * efx ) { return 0 ; }
static inline void efx_mcdi_mon_remove ( struct efx_nic * efx ) { }
# endif
2012-11-28 08:38:14 +04:00
# ifdef CONFIG_SFC_MTD
2013-09-23 22:37:59 +04:00
int efx_mcdi_mtd_read ( struct mtd_info * mtd , loff_t start , size_t len ,
size_t * retlen , u8 * buffer ) ;
int efx_mcdi_mtd_erase ( struct mtd_info * mtd , loff_t start , size_t len ) ;
int efx_mcdi_mtd_write ( struct mtd_info * mtd , loff_t start , size_t len ,
size_t * retlen , const u8 * buffer ) ;
int efx_mcdi_mtd_sync ( struct mtd_info * mtd ) ;
void efx_mcdi_mtd_rename ( struct efx_mtd_partition * part ) ;
2012-11-28 08:38:14 +04:00
# endif
2009-11-29 18:15:25 +03:00
# endif /* EFX_MCDI_H */