2009-04-07 14:37:34 +00:00
/*******************************************************************************
Intel ( R ) 82576 Virtual Function Linux driver
2012-01-17 04:09:05 +00:00
Copyright ( c ) 2009 - 2012 Intel Corporation .
2009-04-07 14:37:34 +00: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 .
You should have received a copy of the GNU General Public License along with
2015-01-21 09:57:50 +00:00
this program ; if not , see < http : //www.gnu.org/licenses/>.
2009-04-07 14:37:34 +00:00
The full GNU General Public License is included in this distribution in
the file called " COPYING " .
Contact Information :
e1000 - devel Mailing List < e1000 - devel @ lists . sourceforge . net >
Intel Corporation , 5200 N . E . Elam Young Parkway , Hillsboro , OR 97124 - 6497
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "mbx.h"
/**
* e1000_poll_for_msg - Wait for message notification
* @ hw : pointer to the HW structure
*
* returns SUCCESS if it successfully received a message notification
* */
static s32 e1000_poll_for_msg ( struct e1000_hw * hw )
{
struct e1000_mbx_info * mbx = & hw - > mbx ;
int countdown = mbx - > timeout ;
if ( ! mbx - > ops . check_for_msg )
goto out ;
while ( countdown & & mbx - > ops . check_for_msg ( hw ) ) {
countdown - - ;
udelay ( mbx - > usec_delay ) ;
}
/* if we failed, all future posted messages fail until reset */
if ( ! countdown )
mbx - > timeout = 0 ;
out :
return countdown ? E1000_SUCCESS : - E1000_ERR_MBX ;
}
/**
2015-01-21 09:57:50 +00:00
* e1000_poll_for_ack - Wait for message acknowledgment
2009-04-07 14:37:34 +00:00
* @ hw : pointer to the HW structure
*
2015-01-21 09:57:50 +00:00
* returns SUCCESS if it successfully received a message acknowledgment
2009-04-07 14:37:34 +00:00
* */
static s32 e1000_poll_for_ack ( struct e1000_hw * hw )
{
struct e1000_mbx_info * mbx = & hw - > mbx ;
int countdown = mbx - > timeout ;
if ( ! mbx - > ops . check_for_ack )
goto out ;
while ( countdown & & mbx - > ops . check_for_ack ( hw ) ) {
countdown - - ;
udelay ( mbx - > usec_delay ) ;
}
/* if we failed, all future posted messages fail until reset */
if ( ! countdown )
mbx - > timeout = 0 ;
out :
return countdown ? E1000_SUCCESS : - E1000_ERR_MBX ;
}
/**
* e1000_read_posted_mbx - Wait for message notification and receive message
* @ hw : pointer to the HW structure
* @ msg : The message buffer
* @ size : Length of buffer
*
* returns SUCCESS if it successfully received a message notification and
* copied it into the receive buffer .
* */
static s32 e1000_read_posted_mbx ( struct e1000_hw * hw , u32 * msg , u16 size )
{
struct e1000_mbx_info * mbx = & hw - > mbx ;
s32 ret_val = - E1000_ERR_MBX ;
if ( ! mbx - > ops . read )
goto out ;
ret_val = e1000_poll_for_msg ( hw ) ;
/* if ack received read message, otherwise we timed out */
if ( ! ret_val )
ret_val = mbx - > ops . read ( hw , msg , size ) ;
out :
return ret_val ;
}
/**
* e1000_write_posted_mbx - Write a message to the mailbox , wait for ack
* @ hw : pointer to the HW structure
* @ msg : The message buffer
* @ size : Length of buffer
*
* returns SUCCESS if it successfully copied message into the buffer and
* received an ack to that message within delay * timeout period
* */
static s32 e1000_write_posted_mbx ( struct e1000_hw * hw , u32 * msg , u16 size )
{
struct e1000_mbx_info * mbx = & hw - > mbx ;
s32 ret_val = - E1000_ERR_MBX ;
/* exit if we either can't write or there isn't a defined timeout */
if ( ! mbx - > ops . write | | ! mbx - > timeout )
goto out ;
/* send msg*/
ret_val = mbx - > ops . write ( hw , msg , size ) ;
/* if msg sent wait until we receive an ack */
if ( ! ret_val )
ret_val = e1000_poll_for_ack ( hw ) ;
out :
return ret_val ;
}
/**
* e1000_read_v2p_mailbox - read v2p mailbox
* @ hw : pointer to the HW structure
*
* This function is used to read the v2p mailbox without losing the read to
* clear status bits .
* */
static u32 e1000_read_v2p_mailbox ( struct e1000_hw * hw )
{
u32 v2p_mailbox = er32 ( V2PMAILBOX ( 0 ) ) ;
v2p_mailbox | = hw - > dev_spec . vf . v2p_mailbox ;
hw - > dev_spec . vf . v2p_mailbox | = v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS ;
return v2p_mailbox ;
}
/**
* e1000_check_for_bit_vf - Determine if a status bit was set
* @ hw : pointer to the HW structure
* @ mask : bitmask for bits to be tested and cleared
*
* This function is used to check for the read to clear bits within
* the V2P mailbox .
* */
static s32 e1000_check_for_bit_vf ( struct e1000_hw * hw , u32 mask )
{
u32 v2p_mailbox = e1000_read_v2p_mailbox ( hw ) ;
s32 ret_val = - E1000_ERR_MBX ;
if ( v2p_mailbox & mask )
ret_val = E1000_SUCCESS ;
hw - > dev_spec . vf . v2p_mailbox & = ~ mask ;
return ret_val ;
}
/**
* e1000_check_for_msg_vf - checks to see if the PF has sent mail
* @ hw : pointer to the HW structure
*
* returns SUCCESS if the PF has set the Status bit or else ERR_MBX
* */
static s32 e1000_check_for_msg_vf ( struct e1000_hw * hw )
{
s32 ret_val = - E1000_ERR_MBX ;
if ( ! e1000_check_for_bit_vf ( hw , E1000_V2PMAILBOX_PFSTS ) ) {
ret_val = E1000_SUCCESS ;
hw - > mbx . stats . reqs + + ;
}
return ret_val ;
}
/**
* e1000_check_for_ack_vf - checks to see if the PF has ACK ' d
* @ hw : pointer to the HW structure
*
* returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
* */
static s32 e1000_check_for_ack_vf ( struct e1000_hw * hw )
{
s32 ret_val = - E1000_ERR_MBX ;
if ( ! e1000_check_for_bit_vf ( hw , E1000_V2PMAILBOX_PFACK ) ) {
ret_val = E1000_SUCCESS ;
hw - > mbx . stats . acks + + ;
}
return ret_val ;
}
/**
* e1000_check_for_rst_vf - checks to see if the PF has reset
* @ hw : pointer to the HW structure
*
* returns true if the PF has set the reset done bit or else false
* */
static s32 e1000_check_for_rst_vf ( struct e1000_hw * hw )
{
s32 ret_val = - E1000_ERR_MBX ;
if ( ! e1000_check_for_bit_vf ( hw , ( E1000_V2PMAILBOX_RSTD |
2015-01-21 09:57:50 +00:00
E1000_V2PMAILBOX_RSTI ) ) ) {
2009-04-07 14:37:34 +00:00
ret_val = E1000_SUCCESS ;
hw - > mbx . stats . rsts + + ;
}
return ret_val ;
}
/**
* e1000_obtain_mbx_lock_vf - obtain mailbox lock
* @ hw : pointer to the HW structure
*
* return SUCCESS if we obtained the mailbox lock
* */
static s32 e1000_obtain_mbx_lock_vf ( struct e1000_hw * hw )
{
s32 ret_val = - E1000_ERR_MBX ;
2015-12-11 16:45:38 -08:00
int count = 10 ;
do {
/* Take ownership of the buffer */
ew32 ( V2PMAILBOX ( 0 ) , E1000_V2PMAILBOX_VFU ) ;
/* reserve mailbox for VF use */
if ( e1000_read_v2p_mailbox ( hw ) & E1000_V2PMAILBOX_VFU ) {
ret_val = 0 ;
break ;
}
udelay ( 1000 ) ;
} while ( count - - > 0 ) ;
2009-04-07 14:37:34 +00:00
return ret_val ;
}
/**
* e1000_write_mbx_vf - Write a message to the mailbox
* @ hw : pointer to the HW structure
* @ msg : The message buffer
* @ size : Length of buffer
*
* returns SUCCESS if it successfully copied message into the buffer
* */
static s32 e1000_write_mbx_vf ( struct e1000_hw * hw , u32 * msg , u16 size )
{
s32 err ;
u16 i ;
/* lock the mailbox to prevent pf/vf race condition */
err = e1000_obtain_mbx_lock_vf ( hw ) ;
if ( err )
goto out_no_write ;
/* flush any ack or msg as we are going to overwrite mailbox */
e1000_check_for_ack_vf ( hw ) ;
e1000_check_for_msg_vf ( hw ) ;
/* copy the caller specified message to the mailbox memory buffer */
for ( i = 0 ; i < size ; i + + )
array_ew32 ( VMBMEM ( 0 ) , i , msg [ i ] ) ;
/* update stats */
hw - > mbx . stats . msgs_tx + + ;
/* Drop VFU and interrupt the PF to tell it a message has been sent */
ew32 ( V2PMAILBOX ( 0 ) , E1000_V2PMAILBOX_REQ ) ;
out_no_write :
return err ;
}
/**
2015-01-21 09:57:50 +00:00
* e1000_read_mbx_vf - Reads a message from the inbox intended for VF
2009-04-07 14:37:34 +00:00
* @ hw : pointer to the HW structure
* @ msg : The message buffer
* @ size : Length of buffer
*
2011-08-17 06:58:04 -07:00
* returns SUCCESS if it successfully read message from buffer
2009-04-07 14:37:34 +00:00
* */
static s32 e1000_read_mbx_vf ( struct e1000_hw * hw , u32 * msg , u16 size )
{
s32 err ;
u16 i ;
/* lock the mailbox to prevent pf/vf race condition */
err = e1000_obtain_mbx_lock_vf ( hw ) ;
if ( err )
goto out_no_read ;
/* copy the message from the mailbox memory buffer */
for ( i = 0 ; i < size ; i + + )
msg [ i ] = array_er32 ( VMBMEM ( 0 ) , i ) ;
/* Acknowledge receipt and release mailbox, then we're done */
ew32 ( V2PMAILBOX ( 0 ) , E1000_V2PMAILBOX_ACK ) ;
/* update stats */
hw - > mbx . stats . msgs_rx + + ;
out_no_read :
return err ;
}
/**
2015-01-21 09:57:50 +00:00
* e1000_init_mbx_params_vf - set initial values for VF mailbox
2009-04-07 14:37:34 +00:00
* @ hw : pointer to the HW structure
*
2015-01-21 09:57:50 +00:00
* Initializes the hw - > mbx struct to correct values for VF mailbox
2009-04-07 14:37:34 +00:00
*/
s32 e1000_init_mbx_params_vf ( struct e1000_hw * hw )
{
struct e1000_mbx_info * mbx = & hw - > mbx ;
/* start mailbox as timed out and let the reset_hw call set the timeout
2015-01-21 09:57:50 +00:00
* value to being communications
*/
2009-04-07 14:37:34 +00:00
mbx - > timeout = 0 ;
mbx - > usec_delay = E1000_VF_MBX_INIT_DELAY ;
mbx - > size = E1000_VFMAILBOX_SIZE ;
mbx - > ops . read = e1000_read_mbx_vf ;
mbx - > ops . write = e1000_write_mbx_vf ;
mbx - > ops . read_posted = e1000_read_posted_mbx ;
mbx - > ops . write_posted = e1000_write_posted_mbx ;
mbx - > ops . check_for_msg = e1000_check_for_msg_vf ;
mbx - > ops . check_for_ack = e1000_check_for_ack_vf ;
mbx - > ops . check_for_rst = e1000_check_for_rst_vf ;
mbx - > stats . msgs_tx = 0 ;
mbx - > stats . msgs_rx = 0 ;
mbx - > stats . reqs = 0 ;
mbx - > stats . acks = 0 ;
mbx - > stats . rsts = 0 ;
return E1000_SUCCESS ;
}