2015-10-26 11:02:25 +02:00
/* QLogic qed NIC Driver
* Copyright ( c ) 2015 QLogic Corporation
*
* This software is available under the terms of the GNU General Public License
* ( GPL ) Version 2 , available from the file COPYING in the main directory of
* this source tree .
*/
# include <linux/types.h>
# include <asm/byteorder.h>
# include <linux/bitops.h>
# include <linux/errno.h>
# include <linux/kernel.h>
# include <linux/string.h>
# include "qed.h"
# include <linux/qed/qed_chain.h>
# include "qed_cxt.h"
# include "qed_hsi.h"
# include "qed_hw.h"
# include "qed_int.h"
# include "qed_reg_addr.h"
# include "qed_sp.h"
2016-05-11 16:36:14 +03:00
# include "qed_sriov.h"
2015-10-26 11:02:25 +02:00
int qed_sp_init_request ( struct qed_hwfn * p_hwfn ,
struct qed_spq_entry * * pp_ent ,
u8 cmd ,
u8 protocol ,
2016-02-21 11:40:09 +02:00
struct qed_sp_init_data * p_data )
2015-10-26 11:02:25 +02:00
{
2016-02-21 11:40:09 +02:00
u32 opaque_cid = p_data - > opaque_fid < < 16 | p_data - > cid ;
2015-10-26 11:02:25 +02:00
struct qed_spq_entry * p_ent = NULL ;
2016-02-21 11:40:09 +02:00
int rc ;
2015-10-26 11:02:25 +02:00
if ( ! pp_ent )
return - ENOMEM ;
rc = qed_spq_get_entry ( p_hwfn , pp_ent ) ;
if ( rc ! = 0 )
return rc ;
p_ent = * pp_ent ;
p_ent - > elem . hdr . cid = cpu_to_le32 ( opaque_cid ) ;
p_ent - > elem . hdr . cmd_id = cmd ;
p_ent - > elem . hdr . protocol_id = protocol ;
p_ent - > priority = QED_SPQ_PRIORITY_NORMAL ;
2016-02-21 11:40:09 +02:00
p_ent - > comp_mode = p_data - > comp_mode ;
2015-10-26 11:02:25 +02:00
p_ent - > comp_done . done = 0 ;
switch ( p_ent - > comp_mode ) {
case QED_SPQ_MODE_EBLOCK :
p_ent - > comp_cb . cookie = & p_ent - > comp_done ;
break ;
case QED_SPQ_MODE_BLOCK :
2016-02-21 11:40:09 +02:00
if ( ! p_data - > p_comp_data )
2015-10-26 11:02:25 +02:00
return - EINVAL ;
2016-02-21 11:40:09 +02:00
p_ent - > comp_cb . cookie = p_data - > p_comp_data - > cookie ;
2015-10-26 11:02:25 +02:00
break ;
case QED_SPQ_MODE_CB :
2016-02-21 11:40:09 +02:00
if ( ! p_data - > p_comp_data )
2015-10-26 11:02:25 +02:00
p_ent - > comp_cb . function = NULL ;
else
2016-02-21 11:40:09 +02:00
p_ent - > comp_cb = * p_data - > p_comp_data ;
2015-10-26 11:02:25 +02:00
break ;
default :
DP_NOTICE ( p_hwfn , " Unknown SPQE completion mode %d \n " ,
p_ent - > comp_mode ) ;
return - EINVAL ;
}
DP_VERBOSE ( p_hwfn , QED_MSG_SPQ ,
" Initialized: CID %08x cmd %02x protocol %02x data_addr %lu comp_mode [%s] \n " ,
opaque_cid , cmd , protocol ,
( unsigned long ) & p_ent - > ramrod ,
D_TRINE ( p_ent - > comp_mode , QED_SPQ_MODE_EBLOCK ,
QED_SPQ_MODE_BLOCK , " MODE_EBLOCK " , " MODE_BLOCK " ,
" MODE_CB " ) ) ;
2016-02-21 11:40:09 +02:00
memset ( & p_ent - > ramrod , 0 , sizeof ( p_ent - > ramrod ) ) ;
2015-10-26 11:02:25 +02:00
return 0 ;
}
2016-04-14 01:38:29 -04:00
static enum tunnel_clss qed_tunn_get_clss_type ( u8 type )
{
switch ( type ) {
case QED_TUNN_CLSS_MAC_VLAN :
return TUNNEL_CLSS_MAC_VLAN ;
case QED_TUNN_CLSS_MAC_VNI :
return TUNNEL_CLSS_MAC_VNI ;
case QED_TUNN_CLSS_INNER_MAC_VLAN :
return TUNNEL_CLSS_INNER_MAC_VLAN ;
case QED_TUNN_CLSS_INNER_MAC_VNI :
return TUNNEL_CLSS_INNER_MAC_VNI ;
default :
return TUNNEL_CLSS_MAC_VLAN ;
}
}
static void
qed_tunn_set_pf_fix_tunn_mode ( struct qed_hwfn * p_hwfn ,
struct qed_tunn_update_params * p_src ,
struct pf_update_tunnel_config * p_tunn_cfg )
{
unsigned long cached_tunn_mode = p_hwfn - > cdev - > tunn_mode ;
unsigned long update_mask = p_src - > tunn_mode_update_mask ;
unsigned long tunn_mode = p_src - > tunn_mode ;
unsigned long new_tunn_mode = 0 ;
if ( test_bit ( QED_MODE_L2GRE_TUNN , & update_mask ) ) {
if ( test_bit ( QED_MODE_L2GRE_TUNN , & tunn_mode ) )
__set_bit ( QED_MODE_L2GRE_TUNN , & new_tunn_mode ) ;
} else {
if ( test_bit ( QED_MODE_L2GRE_TUNN , & cached_tunn_mode ) )
__set_bit ( QED_MODE_L2GRE_TUNN , & new_tunn_mode ) ;
}
if ( test_bit ( QED_MODE_IPGRE_TUNN , & update_mask ) ) {
if ( test_bit ( QED_MODE_IPGRE_TUNN , & tunn_mode ) )
__set_bit ( QED_MODE_IPGRE_TUNN , & new_tunn_mode ) ;
} else {
if ( test_bit ( QED_MODE_IPGRE_TUNN , & cached_tunn_mode ) )
__set_bit ( QED_MODE_IPGRE_TUNN , & new_tunn_mode ) ;
}
if ( test_bit ( QED_MODE_VXLAN_TUNN , & update_mask ) ) {
if ( test_bit ( QED_MODE_VXLAN_TUNN , & tunn_mode ) )
__set_bit ( QED_MODE_VXLAN_TUNN , & new_tunn_mode ) ;
} else {
if ( test_bit ( QED_MODE_VXLAN_TUNN , & cached_tunn_mode ) )
__set_bit ( QED_MODE_VXLAN_TUNN , & new_tunn_mode ) ;
}
if ( p_src - > update_geneve_udp_port ) {
p_tunn_cfg - > set_geneve_udp_port_flg = 1 ;
p_tunn_cfg - > geneve_udp_port =
cpu_to_le16 ( p_src - > geneve_udp_port ) ;
}
if ( test_bit ( QED_MODE_L2GENEVE_TUNN , & update_mask ) ) {
if ( test_bit ( QED_MODE_L2GENEVE_TUNN , & tunn_mode ) )
__set_bit ( QED_MODE_L2GENEVE_TUNN , & new_tunn_mode ) ;
} else {
if ( test_bit ( QED_MODE_L2GENEVE_TUNN , & cached_tunn_mode ) )
__set_bit ( QED_MODE_L2GENEVE_TUNN , & new_tunn_mode ) ;
}
if ( test_bit ( QED_MODE_IPGENEVE_TUNN , & update_mask ) ) {
if ( test_bit ( QED_MODE_IPGENEVE_TUNN , & tunn_mode ) )
__set_bit ( QED_MODE_IPGENEVE_TUNN , & new_tunn_mode ) ;
} else {
if ( test_bit ( QED_MODE_IPGENEVE_TUNN , & cached_tunn_mode ) )
__set_bit ( QED_MODE_IPGENEVE_TUNN , & new_tunn_mode ) ;
}
p_src - > tunn_mode = new_tunn_mode ;
}
static void
qed_tunn_set_pf_update_params ( struct qed_hwfn * p_hwfn ,
struct qed_tunn_update_params * p_src ,
struct pf_update_tunnel_config * p_tunn_cfg )
{
unsigned long tunn_mode = p_src - > tunn_mode ;
enum tunnel_clss type ;
qed_tunn_set_pf_fix_tunn_mode ( p_hwfn , p_src , p_tunn_cfg ) ;
p_tunn_cfg - > update_rx_pf_clss = p_src - > update_rx_pf_clss ;
p_tunn_cfg - > update_tx_pf_clss = p_src - > update_tx_pf_clss ;
type = qed_tunn_get_clss_type ( p_src - > tunn_clss_vxlan ) ;
p_tunn_cfg - > tunnel_clss_vxlan = type ;
type = qed_tunn_get_clss_type ( p_src - > tunn_clss_l2gre ) ;
p_tunn_cfg - > tunnel_clss_l2gre = type ;
type = qed_tunn_get_clss_type ( p_src - > tunn_clss_ipgre ) ;
p_tunn_cfg - > tunnel_clss_ipgre = type ;
if ( p_src - > update_vxlan_udp_port ) {
p_tunn_cfg - > set_vxlan_udp_port_flg = 1 ;
p_tunn_cfg - > vxlan_udp_port = cpu_to_le16 ( p_src - > vxlan_udp_port ) ;
}
if ( test_bit ( QED_MODE_L2GRE_TUNN , & tunn_mode ) )
p_tunn_cfg - > tx_enable_l2gre = 1 ;
if ( test_bit ( QED_MODE_IPGRE_TUNN , & tunn_mode ) )
p_tunn_cfg - > tx_enable_ipgre = 1 ;
if ( test_bit ( QED_MODE_VXLAN_TUNN , & tunn_mode ) )
p_tunn_cfg - > tx_enable_vxlan = 1 ;
if ( p_src - > update_geneve_udp_port ) {
p_tunn_cfg - > set_geneve_udp_port_flg = 1 ;
p_tunn_cfg - > geneve_udp_port =
cpu_to_le16 ( p_src - > geneve_udp_port ) ;
}
if ( test_bit ( QED_MODE_L2GENEVE_TUNN , & tunn_mode ) )
p_tunn_cfg - > tx_enable_l2geneve = 1 ;
if ( test_bit ( QED_MODE_IPGENEVE_TUNN , & tunn_mode ) )
p_tunn_cfg - > tx_enable_ipgeneve = 1 ;
type = qed_tunn_get_clss_type ( p_src - > tunn_clss_l2geneve ) ;
p_tunn_cfg - > tunnel_clss_l2geneve = type ;
type = qed_tunn_get_clss_type ( p_src - > tunn_clss_ipgeneve ) ;
p_tunn_cfg - > tunnel_clss_ipgeneve = type ;
}
static void qed_set_hw_tunn_mode ( struct qed_hwfn * p_hwfn ,
struct qed_ptt * p_ptt ,
unsigned long tunn_mode )
{
u8 l2gre_enable = 0 , ipgre_enable = 0 , vxlan_enable = 0 ;
u8 l2geneve_enable = 0 , ipgeneve_enable = 0 ;
if ( test_bit ( QED_MODE_L2GRE_TUNN , & tunn_mode ) )
l2gre_enable = 1 ;
if ( test_bit ( QED_MODE_IPGRE_TUNN , & tunn_mode ) )
ipgre_enable = 1 ;
if ( test_bit ( QED_MODE_VXLAN_TUNN , & tunn_mode ) )
vxlan_enable = 1 ;
qed_set_gre_enable ( p_hwfn , p_ptt , l2gre_enable , ipgre_enable ) ;
qed_set_vxlan_enable ( p_hwfn , p_ptt , vxlan_enable ) ;
if ( test_bit ( QED_MODE_L2GENEVE_TUNN , & tunn_mode ) )
l2geneve_enable = 1 ;
if ( test_bit ( QED_MODE_IPGENEVE_TUNN , & tunn_mode ) )
ipgeneve_enable = 1 ;
qed_set_geneve_enable ( p_hwfn , p_ptt , l2geneve_enable ,
ipgeneve_enable ) ;
}
static void
qed_tunn_set_pf_start_params ( struct qed_hwfn * p_hwfn ,
struct qed_tunn_start_params * p_src ,
struct pf_start_tunnel_config * p_tunn_cfg )
{
unsigned long tunn_mode ;
enum tunnel_clss type ;
if ( ! p_src )
return ;
tunn_mode = p_src - > tunn_mode ;
type = qed_tunn_get_clss_type ( p_src - > tunn_clss_vxlan ) ;
p_tunn_cfg - > tunnel_clss_vxlan = type ;
type = qed_tunn_get_clss_type ( p_src - > tunn_clss_l2gre ) ;
p_tunn_cfg - > tunnel_clss_l2gre = type ;
type = qed_tunn_get_clss_type ( p_src - > tunn_clss_ipgre ) ;
p_tunn_cfg - > tunnel_clss_ipgre = type ;
if ( p_src - > update_vxlan_udp_port ) {
p_tunn_cfg - > set_vxlan_udp_port_flg = 1 ;
p_tunn_cfg - > vxlan_udp_port = cpu_to_le16 ( p_src - > vxlan_udp_port ) ;
}
if ( test_bit ( QED_MODE_L2GRE_TUNN , & tunn_mode ) )
p_tunn_cfg - > tx_enable_l2gre = 1 ;
if ( test_bit ( QED_MODE_IPGRE_TUNN , & tunn_mode ) )
p_tunn_cfg - > tx_enable_ipgre = 1 ;
if ( test_bit ( QED_MODE_VXLAN_TUNN , & tunn_mode ) )
p_tunn_cfg - > tx_enable_vxlan = 1 ;
if ( p_src - > update_geneve_udp_port ) {
p_tunn_cfg - > set_geneve_udp_port_flg = 1 ;
p_tunn_cfg - > geneve_udp_port =
cpu_to_le16 ( p_src - > geneve_udp_port ) ;
}
if ( test_bit ( QED_MODE_L2GENEVE_TUNN , & tunn_mode ) )
p_tunn_cfg - > tx_enable_l2geneve = 1 ;
if ( test_bit ( QED_MODE_IPGENEVE_TUNN , & tunn_mode ) )
p_tunn_cfg - > tx_enable_ipgeneve = 1 ;
type = qed_tunn_get_clss_type ( p_src - > tunn_clss_l2geneve ) ;
p_tunn_cfg - > tunnel_clss_l2geneve = type ;
type = qed_tunn_get_clss_type ( p_src - > tunn_clss_ipgeneve ) ;
p_tunn_cfg - > tunnel_clss_ipgeneve = type ;
}
2015-10-26 11:02:25 +02:00
int qed_sp_pf_start ( struct qed_hwfn * p_hwfn ,
2016-04-14 01:38:29 -04:00
struct qed_tunn_start_params * p_tunn ,
2016-02-15 13:22:35 -05:00
enum qed_mf_mode mode )
2015-10-26 11:02:25 +02:00
{
struct pf_start_ramrod_data * p_ramrod = NULL ;
u16 sb = qed_int_get_sp_sb_id ( p_hwfn ) ;
u8 sb_index = p_hwfn - > p_eq - > eq_sb_index ;
struct qed_spq_entry * p_ent = NULL ;
2016-02-21 11:40:09 +02:00
struct qed_sp_init_data init_data ;
2015-10-26 11:02:25 +02:00
int rc = - EINVAL ;
/* update initial eq producer */
qed_eq_prod_update ( p_hwfn ,
qed_chain_get_prod_idx ( & p_hwfn - > p_eq - > chain ) ) ;
2016-02-21 11:40:09 +02:00
memset ( & init_data , 0 , sizeof ( init_data ) ) ;
init_data . cid = qed_spq_get_cid ( p_hwfn ) ;
init_data . opaque_fid = p_hwfn - > hw_info . opaque_fid ;
init_data . comp_mode = QED_SPQ_MODE_EBLOCK ;
2015-10-26 11:02:25 +02:00
2016-02-21 11:40:09 +02:00
rc = qed_sp_init_request ( p_hwfn , & p_ent ,
2015-10-26 11:02:25 +02:00
COMMON_RAMROD_PF_START ,
PROTOCOLID_COMMON ,
2016-02-21 11:40:09 +02:00
& init_data ) ;
2015-10-26 11:02:25 +02:00
if ( rc )
return rc ;
p_ramrod = & p_ent - > ramrod . pf_start ;
p_ramrod - > event_ring_sb_id = cpu_to_le16 ( sb ) ;
p_ramrod - > event_ring_sb_index = sb_index ;
p_ramrod - > path_id = QED_PATH_ID ( p_hwfn ) ;
p_ramrod - > dont_log_ramrods = 0 ;
p_ramrod - > log_type_mask = cpu_to_le16 ( 0xf ) ;
p_ramrod - > mf_mode = mode ;
2016-02-15 13:22:35 -05:00
switch ( mode ) {
case QED_MF_DEFAULT :
case QED_MF_NPAR :
p_ramrod - > mf_mode = MF_NPAR ;
break ;
case QED_MF_OVLAN :
p_ramrod - > mf_mode = MF_OVLAN ;
break ;
default :
DP_NOTICE ( p_hwfn , " Unsupported MF mode, init as DEFAULT \n " ) ;
p_ramrod - > mf_mode = MF_NPAR ;
}
2015-10-26 11:02:25 +02:00
p_ramrod - > outer_tag = p_hwfn - > hw_info . ovlan ;
/* Place EQ address in RAMROD */
2016-02-21 11:40:10 +02:00
DMA_REGPAIR_LE ( p_ramrod - > event_ring_pbl_addr ,
p_hwfn - > p_eq - > chain . pbl . p_phys_table ) ;
2015-10-26 11:02:25 +02:00
p_ramrod - > event_ring_num_pages = ( u8 ) p_hwfn - > p_eq - > chain . page_cnt ;
2016-02-21 11:40:10 +02:00
DMA_REGPAIR_LE ( p_ramrod - > consolid_q_pbl_addr ,
p_hwfn - > p_consq - > chain . pbl . p_phys_table ) ;
2015-10-26 11:02:25 +02:00
2016-04-14 01:38:30 -04:00
qed_tunn_set_pf_start_params ( p_hwfn , p_tunn ,
& p_ramrod - > tunnel_config ) ;
2015-10-26 11:02:25 +02:00
p_hwfn - > hw_info . personality = PERSONALITY_ETH ;
2016-05-11 16:36:14 +03:00
if ( p_hwfn - > cdev - > p_iov_info ) {
struct qed_hw_sriov_info * p_iov = p_hwfn - > cdev - > p_iov_info ;
p_ramrod - > base_vf_id = ( u8 ) p_iov - > first_vf_in_pf ;
p_ramrod - > num_vfs = ( u8 ) p_iov - > total_vfs ;
}
2015-10-26 11:02:25 +02:00
DP_VERBOSE ( p_hwfn , QED_MSG_SPQ ,
2016-02-15 13:22:35 -05:00
" Setting event_ring_sb [id %04x index %02x], outer_tag [%d] \n " ,
2015-10-26 11:02:25 +02:00
sb , sb_index ,
p_ramrod - > outer_tag ) ;
2016-05-02 06:16:04 -04:00
rc = qed_spq_post ( p_hwfn , p_ent , NULL ) ;
if ( p_tunn ) {
qed_set_hw_tunn_mode ( p_hwfn , p_hwfn - > p_main_ptt ,
p_tunn - > tunn_mode ) ;
p_hwfn - > cdev - > tunn_mode = p_tunn - > tunn_mode ;
}
return rc ;
2015-10-26 11:02:25 +02:00
}
2016-04-14 01:38:29 -04:00
/* Set pf update ramrod command params */
int qed_sp_pf_update_tunn_cfg ( struct qed_hwfn * p_hwfn ,
struct qed_tunn_update_params * p_tunn ,
enum spq_mode comp_mode ,
struct qed_spq_comp_cb * p_comp_data )
{
struct qed_spq_entry * p_ent = NULL ;
struct qed_sp_init_data init_data ;
int rc = - EINVAL ;
/* Get SPQ entry */
memset ( & init_data , 0 , sizeof ( init_data ) ) ;
init_data . cid = qed_spq_get_cid ( p_hwfn ) ;
init_data . opaque_fid = p_hwfn - > hw_info . opaque_fid ;
init_data . comp_mode = comp_mode ;
init_data . p_comp_data = p_comp_data ;
rc = qed_sp_init_request ( p_hwfn , & p_ent ,
COMMON_RAMROD_PF_UPDATE , PROTOCOLID_COMMON ,
& init_data ) ;
if ( rc )
return rc ;
qed_tunn_set_pf_update_params ( p_hwfn , p_tunn ,
& p_ent - > ramrod . pf_update . tunnel_config ) ;
rc = qed_spq_post ( p_hwfn , p_ent , NULL ) ;
if ( rc )
return rc ;
if ( p_tunn - > update_vxlan_udp_port )
qed_set_vxlan_dest_port ( p_hwfn , p_hwfn - > p_main_ptt ,
p_tunn - > vxlan_udp_port ) ;
if ( p_tunn - > update_geneve_udp_port )
qed_set_geneve_dest_port ( p_hwfn , p_hwfn - > p_main_ptt ,
p_tunn - > geneve_udp_port ) ;
qed_set_hw_tunn_mode ( p_hwfn , p_hwfn - > p_main_ptt , p_tunn - > tunn_mode ) ;
p_hwfn - > cdev - > tunn_mode = p_tunn - > tunn_mode ;
return rc ;
}
2015-10-26 11:02:25 +02:00
int qed_sp_pf_stop ( struct qed_hwfn * p_hwfn )
{
struct qed_spq_entry * p_ent = NULL ;
2016-02-21 11:40:09 +02:00
struct qed_sp_init_data init_data ;
2015-10-26 11:02:25 +02:00
int rc = - EINVAL ;
2016-02-21 11:40:09 +02:00
/* Get SPQ entry */
memset ( & init_data , 0 , sizeof ( init_data ) ) ;
init_data . cid = qed_spq_get_cid ( p_hwfn ) ;
init_data . opaque_fid = p_hwfn - > hw_info . opaque_fid ;
init_data . comp_mode = QED_SPQ_MODE_EBLOCK ;
2015-10-26 11:02:25 +02:00
2016-02-21 11:40:09 +02:00
rc = qed_sp_init_request ( p_hwfn , & p_ent ,
2015-10-26 11:02:25 +02:00
COMMON_RAMROD_PF_STOP , PROTOCOLID_COMMON ,
2016-02-21 11:40:09 +02:00
& init_data ) ;
2015-10-26 11:02:25 +02:00
if ( rc )
return rc ;
return qed_spq_post ( p_hwfn , p_ent , NULL ) ;
}
2016-04-28 20:20:52 -04:00
int qed_sp_heartbeat_ramrod ( struct qed_hwfn * p_hwfn )
{
struct qed_spq_entry * p_ent = NULL ;
struct qed_sp_init_data init_data ;
int rc ;
/* Get SPQ entry */
memset ( & init_data , 0 , sizeof ( init_data ) ) ;
init_data . cid = qed_spq_get_cid ( p_hwfn ) ;
init_data . opaque_fid = p_hwfn - > hw_info . opaque_fid ;
init_data . comp_mode = QED_SPQ_MODE_EBLOCK ;
rc = qed_sp_init_request ( p_hwfn , & p_ent ,
COMMON_RAMROD_EMPTY , PROTOCOLID_COMMON ,
& init_data ) ;
if ( rc )
return rc ;
return qed_spq_post ( p_hwfn , p_ent , NULL ) ;
}