2010-01-13 00:37:25 +00:00
/*
2010-12-02 20:41:56 +00:00
* QLogic qlcnic NIC Driver
* Copyright ( c ) 2009 - 2010 QLogic Corporation
2010-01-13 00:37:25 +00:00
*
2010-12-02 20:41:56 +00:00
* See LICENSE . qlcnic for copyright and licensing details .
2010-01-13 00:37:25 +00:00
*/
# include "qlcnic.h"
static u32
qlcnic_poll_rsp ( struct qlcnic_adapter * adapter )
{
u32 rsp ;
int timeout = 0 ;
do {
/* give atleast 1ms for firmware to respond */
msleep ( 1 ) ;
if ( + + timeout > QLCNIC_OS_CRB_RETRY_COUNT )
return QLCNIC_CDRP_RSP_TIMEOUT ;
rsp = QLCRD32 ( adapter , QLCNIC_CDRP_CRB_OFFSET ) ;
} while ( ! QLCNIC_CDRP_IS_RSP ( rsp ) ) ;
return rsp ;
}
2010-02-01 05:24:59 +00:00
u32
2010-01-13 00:37:25 +00:00
qlcnic_issue_cmd ( struct qlcnic_adapter * adapter ,
u32 pci_fn , u32 version , u32 arg1 , u32 arg2 , u32 arg3 , u32 cmd )
{
u32 rsp ;
u32 signature ;
u32 rcode = QLCNIC_RCODE_SUCCESS ;
struct pci_dev * pdev = adapter - > pdev ;
signature = QLCNIC_CDRP_SIGNATURE_MAKE ( pci_fn , version ) ;
/* Acquire semaphore before accessing CRB */
if ( qlcnic_api_lock ( adapter ) )
return QLCNIC_RCODE_TIMEOUT ;
QLCWR32 ( adapter , QLCNIC_SIGN_CRB_OFFSET , signature ) ;
QLCWR32 ( adapter , QLCNIC_ARG1_CRB_OFFSET , arg1 ) ;
QLCWR32 ( adapter , QLCNIC_ARG2_CRB_OFFSET , arg2 ) ;
QLCWR32 ( adapter , QLCNIC_ARG3_CRB_OFFSET , arg3 ) ;
QLCWR32 ( adapter , QLCNIC_CDRP_CRB_OFFSET , QLCNIC_CDRP_FORM_CMD ( cmd ) ) ;
rsp = qlcnic_poll_rsp ( adapter ) ;
if ( rsp = = QLCNIC_CDRP_RSP_TIMEOUT ) {
dev_err ( & pdev - > dev , " card response timeout. \n " ) ;
rcode = QLCNIC_RCODE_TIMEOUT ;
} else if ( rsp = = QLCNIC_CDRP_RSP_FAIL ) {
rcode = QLCRD32 ( adapter , QLCNIC_ARG1_CRB_OFFSET ) ;
dev_err ( & pdev - > dev , " failed card response code:0x%x \n " ,
rcode ) ;
}
/* Release semaphore */
qlcnic_api_unlock ( adapter ) ;
return rcode ;
}
int
qlcnic_fw_cmd_set_mtu ( struct qlcnic_adapter * adapter , int mtu )
{
2011-04-01 14:28:05 +00:00
struct qlcnic_recv_context * recv_ctx = adapter - > recv_ctx ;
2010-01-13 00:37:25 +00:00
if ( recv_ctx - > state = = QLCNIC_HOST_CTX_STATE_ACTIVE ) {
if ( qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-06-01 11:28:51 +00:00
adapter - > fw_hal_version ,
recv_ctx - > context_id ,
mtu ,
0 ,
QLCNIC_CDRP_CMD_SET_MTU ) ) {
2010-01-13 00:37:25 +00:00
dev_err ( & adapter - > pdev - > dev , " Failed to set mtu \n " ) ;
return - EIO ;
}
}
return 0 ;
}
static int
qlcnic_fw_cmd_create_rx_ctx ( struct qlcnic_adapter * adapter )
{
void * addr ;
struct qlcnic_hostrq_rx_ctx * prq ;
struct qlcnic_cardrsp_rx_ctx * prsp ;
struct qlcnic_hostrq_rds_ring * prq_rds ;
struct qlcnic_hostrq_sds_ring * prq_sds ;
struct qlcnic_cardrsp_rds_ring * prsp_rds ;
struct qlcnic_cardrsp_sds_ring * prsp_sds ;
struct qlcnic_host_rds_ring * rds_ring ;
struct qlcnic_host_sds_ring * sds_ring ;
dma_addr_t hostrq_phys_addr , cardrsp_phys_addr ;
u64 phys_addr ;
2011-04-01 14:28:05 +00:00
u8 i , nrds_rings , nsds_rings ;
2010-01-13 00:37:25 +00:00
size_t rq_size , rsp_size ;
2010-06-01 11:28:51 +00:00
u32 cap , reg , val , reg2 ;
2010-01-13 00:37:25 +00:00
int err ;
2011-04-01 14:28:05 +00:00
struct qlcnic_recv_context * recv_ctx = adapter - > recv_ctx ;
2010-01-13 00:37:25 +00:00
nrds_rings = adapter - > max_rds_rings ;
nsds_rings = adapter - > max_sds_rings ;
rq_size =
SIZEOF_HOSTRQ_RX ( struct qlcnic_hostrq_rx_ctx , nrds_rings ,
nsds_rings ) ;
rsp_size =
SIZEOF_CARDRSP_RX ( struct qlcnic_cardrsp_rx_ctx , nrds_rings ,
nsds_rings ) ;
2011-04-01 14:28:05 +00:00
addr = dma_alloc_coherent ( & adapter - > pdev - > dev , rq_size ,
& hostrq_phys_addr , GFP_KERNEL ) ;
2010-01-13 00:37:25 +00:00
if ( addr = = NULL )
return - ENOMEM ;
prq = ( struct qlcnic_hostrq_rx_ctx * ) addr ;
2011-04-01 14:28:05 +00:00
addr = dma_alloc_coherent ( & adapter - > pdev - > dev , rsp_size ,
& cardrsp_phys_addr , GFP_KERNEL ) ;
2010-01-13 00:37:25 +00:00
if ( addr = = NULL ) {
err = - ENOMEM ;
goto out_free_rq ;
}
prsp = ( struct qlcnic_cardrsp_rx_ctx * ) addr ;
prq - > host_rsp_dma_addr = cpu_to_le64 ( cardrsp_phys_addr ) ;
2010-06-17 02:56:40 +00:00
cap = ( QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN
| QLCNIC_CAP0_VALIDOFF ) ;
2010-01-13 00:37:25 +00:00
cap | = ( QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS ) ;
2010-06-17 02:56:40 +00:00
prq - > valid_field_offset = offsetof ( struct qlcnic_hostrq_rx_ctx ,
msix_handler ) ;
prq - > txrx_sds_binding = nsds_rings - 1 ;
2010-01-13 00:37:25 +00:00
prq - > capabilities [ 0 ] = cpu_to_le32 ( cap ) ;
prq - > host_int_crb_mode =
cpu_to_le32 ( QLCNIC_HOST_INT_CRB_MODE_SHARED ) ;
prq - > host_rds_crb_mode =
cpu_to_le32 ( QLCNIC_HOST_RDS_CRB_MODE_UNIQUE ) ;
prq - > num_rds_rings = cpu_to_le16 ( nrds_rings ) ;
prq - > num_sds_rings = cpu_to_le16 ( nsds_rings ) ;
2011-04-01 14:28:05 +00:00
prq - > rds_ring_offset = 0 ;
2010-01-13 00:37:25 +00:00
val = le32_to_cpu ( prq - > rds_ring_offset ) +
( sizeof ( struct qlcnic_hostrq_rds_ring ) * nrds_rings ) ;
prq - > sds_ring_offset = cpu_to_le32 ( val ) ;
prq_rds = ( struct qlcnic_hostrq_rds_ring * ) ( prq - > data +
le32_to_cpu ( prq - > rds_ring_offset ) ) ;
for ( i = 0 ; i < nrds_rings ; i + + ) {
rds_ring = & recv_ctx - > rds_rings [ i ] ;
2010-06-22 03:19:01 +00:00
rds_ring - > producer = 0 ;
2010-01-13 00:37:25 +00:00
prq_rds [ i ] . host_phys_addr = cpu_to_le64 ( rds_ring - > phys_addr ) ;
prq_rds [ i ] . ring_size = cpu_to_le32 ( rds_ring - > num_desc ) ;
prq_rds [ i ] . ring_kind = cpu_to_le32 ( i ) ;
prq_rds [ i ] . buff_size = cpu_to_le64 ( rds_ring - > dma_size ) ;
}
prq_sds = ( struct qlcnic_hostrq_sds_ring * ) ( prq - > data +
le32_to_cpu ( prq - > sds_ring_offset ) ) ;
for ( i = 0 ; i < nsds_rings ; i + + ) {
sds_ring = & recv_ctx - > sds_rings [ i ] ;
2010-06-22 03:19:01 +00:00
sds_ring - > consumer = 0 ;
memset ( sds_ring - > desc_head , 0 , STATUS_DESC_RINGSIZE ( sds_ring ) ) ;
2010-01-13 00:37:25 +00:00
prq_sds [ i ] . host_phys_addr = cpu_to_le64 ( sds_ring - > phys_addr ) ;
prq_sds [ i ] . ring_size = cpu_to_le32 ( sds_ring - > num_desc ) ;
prq_sds [ i ] . msi_index = cpu_to_le16 ( i ) ;
}
phys_addr = hostrq_phys_addr ;
err = qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-06-01 11:28:51 +00:00
adapter - > fw_hal_version ,
2010-01-13 00:37:25 +00:00
( u32 ) ( phys_addr > > 32 ) ,
( u32 ) ( phys_addr & 0xffffffff ) ,
rq_size ,
QLCNIC_CDRP_CMD_CREATE_RX_CTX ) ;
if ( err ) {
dev_err ( & adapter - > pdev - > dev ,
" Failed to create rx ctx in firmware%d \n " , err ) ;
goto out_free_rsp ;
}
prsp_rds = ( ( struct qlcnic_cardrsp_rds_ring * )
& prsp - > data [ le32_to_cpu ( prsp - > rds_ring_offset ) ] ) ;
for ( i = 0 ; i < le16_to_cpu ( prsp - > num_rds_rings ) ; i + + ) {
rds_ring = & recv_ctx - > rds_rings [ i ] ;
reg = le32_to_cpu ( prsp_rds [ i ] . host_producer_crb ) ;
2011-04-01 14:28:05 +00:00
rds_ring - > crb_rcv_producer = adapter - > ahw - > pci_base0 + reg ;
2010-01-13 00:37:25 +00:00
}
prsp_sds = ( ( struct qlcnic_cardrsp_sds_ring * )
& prsp - > data [ le32_to_cpu ( prsp - > sds_ring_offset ) ] ) ;
for ( i = 0 ; i < le16_to_cpu ( prsp - > num_sds_rings ) ; i + + ) {
sds_ring = & recv_ctx - > sds_rings [ i ] ;
reg = le32_to_cpu ( prsp_sds [ i ] . host_consumer_crb ) ;
2010-06-01 11:28:51 +00:00
reg2 = le32_to_cpu ( prsp_sds [ i ] . interrupt_crb ) ;
2010-01-13 00:37:25 +00:00
2011-04-01 14:28:05 +00:00
sds_ring - > crb_sts_consumer = adapter - > ahw - > pci_base0 + reg ;
sds_ring - > crb_intr_mask = adapter - > ahw - > pci_base0 + reg2 ;
2010-01-13 00:37:25 +00:00
}
recv_ctx - > state = le32_to_cpu ( prsp - > host_ctx_state ) ;
recv_ctx - > context_id = le16_to_cpu ( prsp - > context_id ) ;
recv_ctx - > virt_port = prsp - > virt_port ;
out_free_rsp :
2011-04-01 14:28:05 +00:00
dma_free_coherent ( & adapter - > pdev - > dev , rsp_size , prsp ,
cardrsp_phys_addr ) ;
2010-01-13 00:37:25 +00:00
out_free_rq :
2011-04-01 14:28:05 +00:00
dma_free_coherent ( & adapter - > pdev - > dev , rq_size , prq , hostrq_phys_addr ) ;
2010-01-13 00:37:25 +00:00
return err ;
}
static void
qlcnic_fw_cmd_destroy_rx_ctx ( struct qlcnic_adapter * adapter )
{
2011-04-01 14:28:05 +00:00
struct qlcnic_recv_context * recv_ctx = adapter - > recv_ctx ;
2010-01-13 00:37:25 +00:00
if ( qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-06-01 11:28:51 +00:00
adapter - > fw_hal_version ,
2010-01-13 00:37:25 +00:00
recv_ctx - > context_id ,
QLCNIC_DESTROY_CTX_RESET ,
0 ,
QLCNIC_CDRP_CMD_DESTROY_RX_CTX ) ) {
dev_err ( & adapter - > pdev - > dev ,
" Failed to destroy rx ctx in firmware \n " ) ;
}
2010-06-22 03:19:04 +00:00
recv_ctx - > state = QLCNIC_HOST_CTX_STATE_FREED ;
2010-01-13 00:37:25 +00:00
}
static int
qlcnic_fw_cmd_create_tx_ctx ( struct qlcnic_adapter * adapter )
{
struct qlcnic_hostrq_tx_ctx * prq ;
struct qlcnic_hostrq_cds_ring * prq_cds ;
struct qlcnic_cardrsp_tx_ctx * prsp ;
void * rq_addr , * rsp_addr ;
size_t rq_size , rsp_size ;
u32 temp ;
int err ;
u64 phys_addr ;
dma_addr_t rq_phys_addr , rsp_phys_addr ;
struct qlcnic_host_tx_ring * tx_ring = adapter - > tx_ring ;
2010-06-22 03:19:01 +00:00
/* reset host resources */
tx_ring - > producer = 0 ;
tx_ring - > sw_consumer = 0 ;
* ( tx_ring - > hw_consumer ) = 0 ;
2010-01-13 00:37:25 +00:00
rq_size = SIZEOF_HOSTRQ_TX ( struct qlcnic_hostrq_tx_ctx ) ;
2011-04-01 14:28:05 +00:00
rq_addr = dma_alloc_coherent ( & adapter - > pdev - > dev , rq_size ,
& rq_phys_addr , GFP_KERNEL ) ;
2010-01-13 00:37:25 +00:00
if ( ! rq_addr )
return - ENOMEM ;
rsp_size = SIZEOF_CARDRSP_TX ( struct qlcnic_cardrsp_tx_ctx ) ;
2011-04-01 14:28:05 +00:00
rsp_addr = dma_alloc_coherent ( & adapter - > pdev - > dev , rsp_size ,
& rsp_phys_addr , GFP_KERNEL ) ;
2010-01-13 00:37:25 +00:00
if ( ! rsp_addr ) {
err = - ENOMEM ;
goto out_free_rq ;
}
memset ( rq_addr , 0 , rq_size ) ;
prq = ( struct qlcnic_hostrq_tx_ctx * ) rq_addr ;
memset ( rsp_addr , 0 , rsp_size ) ;
prsp = ( struct qlcnic_cardrsp_tx_ctx * ) rsp_addr ;
prq - > host_rsp_dma_addr = cpu_to_le64 ( rsp_phys_addr ) ;
temp = ( QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN |
QLCNIC_CAP0_LSO ) ;
prq - > capabilities [ 0 ] = cpu_to_le32 ( temp ) ;
prq - > host_int_crb_mode =
cpu_to_le32 ( QLCNIC_HOST_INT_CRB_MODE_SHARED ) ;
prq - > interrupt_ctl = 0 ;
prq - > msi_index = 0 ;
prq - > cmd_cons_dma_addr = cpu_to_le64 ( tx_ring - > hw_cons_phys_addr ) ;
prq_cds = & prq - > cds_ring ;
prq_cds - > host_phys_addr = cpu_to_le64 ( tx_ring - > phys_addr ) ;
prq_cds - > ring_size = cpu_to_le32 ( tx_ring - > num_desc ) ;
phys_addr = rq_phys_addr ;
err = qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-06-01 11:28:51 +00:00
adapter - > fw_hal_version ,
2010-01-13 00:37:25 +00:00
( u32 ) ( phys_addr > > 32 ) ,
( ( u32 ) phys_addr & 0xffffffff ) ,
rq_size ,
QLCNIC_CDRP_CMD_CREATE_TX_CTX ) ;
if ( err = = QLCNIC_RCODE_SUCCESS ) {
temp = le32_to_cpu ( prsp - > cds_ring . host_producer_crb ) ;
2011-04-01 14:28:05 +00:00
tx_ring - > crb_cmd_producer = adapter - > ahw - > pci_base0 + temp ;
2010-01-13 00:37:25 +00:00
adapter - > tx_context_id =
le16_to_cpu ( prsp - > context_id ) ;
} else {
dev_err ( & adapter - > pdev - > dev ,
" Failed to create tx ctx in firmware%d \n " , err ) ;
err = - EIO ;
}
2011-04-01 14:28:05 +00:00
dma_free_coherent ( & adapter - > pdev - > dev , rsp_size , rsp_addr ,
rsp_phys_addr ) ;
2010-01-13 00:37:25 +00:00
out_free_rq :
2011-04-01 14:28:05 +00:00
dma_free_coherent ( & adapter - > pdev - > dev , rq_size , rq_addr , rq_phys_addr ) ;
2010-01-13 00:37:25 +00:00
return err ;
}
static void
qlcnic_fw_cmd_destroy_tx_ctx ( struct qlcnic_adapter * adapter )
{
if ( qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-06-01 11:28:51 +00:00
adapter - > fw_hal_version ,
2010-01-13 00:37:25 +00:00
adapter - > tx_context_id ,
QLCNIC_DESTROY_CTX_RESET ,
0 ,
QLCNIC_CDRP_CMD_DESTROY_TX_CTX ) ) {
dev_err ( & adapter - > pdev - > dev ,
" Failed to destroy tx ctx in firmware \n " ) ;
}
}
int
qlcnic_fw_cmd_query_phy ( struct qlcnic_adapter * adapter , u32 reg , u32 * val )
{
if ( qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-06-01 11:28:51 +00:00
adapter - > fw_hal_version ,
2010-01-13 00:37:25 +00:00
reg ,
0 ,
0 ,
QLCNIC_CDRP_CMD_READ_PHY ) ) {
return - EIO ;
}
return QLCRD32 ( adapter , QLCNIC_ARG1_CRB_OFFSET ) ;
}
int
qlcnic_fw_cmd_set_phy ( struct qlcnic_adapter * adapter , u32 reg , u32 val )
{
return qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-06-01 11:28:51 +00:00
adapter - > fw_hal_version ,
2010-01-13 00:37:25 +00:00
reg ,
val ,
0 ,
QLCNIC_CDRP_CMD_WRITE_PHY ) ;
}
int qlcnic_alloc_hw_resources ( struct qlcnic_adapter * adapter )
{
void * addr ;
int err ;
int ring ;
struct qlcnic_recv_context * recv_ctx ;
struct qlcnic_host_rds_ring * rds_ring ;
struct qlcnic_host_sds_ring * sds_ring ;
struct qlcnic_host_tx_ring * tx_ring ;
struct pci_dev * pdev = adapter - > pdev ;
2011-04-01 14:28:05 +00:00
recv_ctx = adapter - > recv_ctx ;
2010-01-13 00:37:25 +00:00
tx_ring = adapter - > tx_ring ;
2011-04-01 14:28:05 +00:00
tx_ring - > hw_consumer = ( __le32 * ) dma_alloc_coherent ( & pdev - > dev ,
sizeof ( u32 ) , & tx_ring - > hw_cons_phys_addr , GFP_KERNEL ) ;
2010-01-13 00:37:25 +00:00
if ( tx_ring - > hw_consumer = = NULL ) {
dev_err ( & pdev - > dev , " failed to allocate tx consumer \n " ) ;
return - ENOMEM ;
}
/* cmd desc ring */
2011-04-01 14:28:05 +00:00
addr = dma_alloc_coherent ( & pdev - > dev , TX_DESC_RINGSIZE ( tx_ring ) ,
& tx_ring - > phys_addr , GFP_KERNEL ) ;
2010-01-13 00:37:25 +00:00
if ( addr = = NULL ) {
dev_err ( & pdev - > dev , " failed to allocate tx desc ring \n " ) ;
2010-05-17 01:22:08 +00:00
err = - ENOMEM ;
goto err_out_free ;
2010-01-13 00:37:25 +00:00
}
tx_ring - > desc_head = ( struct cmd_desc_type0 * ) addr ;
for ( ring = 0 ; ring < adapter - > max_rds_rings ; ring + + ) {
rds_ring = & recv_ctx - > rds_rings [ ring ] ;
2011-04-01 14:28:05 +00:00
addr = dma_alloc_coherent ( & adapter - > pdev - > dev ,
2010-01-13 00:37:25 +00:00
RCV_DESC_RINGSIZE ( rds_ring ) ,
2011-04-01 14:28:05 +00:00
& rds_ring - > phys_addr , GFP_KERNEL ) ;
2010-01-13 00:37:25 +00:00
if ( addr = = NULL ) {
dev_err ( & pdev - > dev ,
" failed to allocate rds ring [%d] \n " , ring ) ;
err = - ENOMEM ;
goto err_out_free ;
}
rds_ring - > desc_head = ( struct rcv_desc * ) addr ;
}
for ( ring = 0 ; ring < adapter - > max_sds_rings ; ring + + ) {
sds_ring = & recv_ctx - > sds_rings [ ring ] ;
2011-04-01 14:28:05 +00:00
addr = dma_alloc_coherent ( & adapter - > pdev - > dev ,
2010-01-13 00:37:25 +00:00
STATUS_DESC_RINGSIZE ( sds_ring ) ,
2011-04-01 14:28:05 +00:00
& sds_ring - > phys_addr , GFP_KERNEL ) ;
2010-01-13 00:37:25 +00:00
if ( addr = = NULL ) {
dev_err ( & pdev - > dev ,
" failed to allocate sds ring [%d] \n " , ring ) ;
err = - ENOMEM ;
goto err_out_free ;
}
sds_ring - > desc_head = ( struct status_desc * ) addr ;
}
return 0 ;
err_out_free :
qlcnic_free_hw_resources ( adapter ) ;
return err ;
}
2010-06-22 03:19:01 +00:00
int qlcnic_fw_create_ctx ( struct qlcnic_adapter * adapter )
2010-01-13 00:37:25 +00:00
{
2010-06-22 03:19:01 +00:00
int err ;
2010-11-23 01:25:21 +00:00
if ( adapter - > flags & QLCNIC_NEED_FLR ) {
2010-11-16 14:08:06 +00:00
pci_reset_function ( adapter - > pdev ) ;
2010-11-23 01:25:21 +00:00
adapter - > flags & = ~ QLCNIC_NEED_FLR ;
}
2010-11-16 14:08:06 +00:00
2010-06-22 03:19:01 +00:00
err = qlcnic_fw_cmd_create_rx_ctx ( adapter ) ;
if ( err )
return err ;
err = qlcnic_fw_cmd_create_tx_ctx ( adapter ) ;
if ( err ) {
qlcnic_fw_cmd_destroy_rx_ctx ( adapter ) ;
return err ;
}
2010-01-13 00:37:25 +00:00
2010-06-22 03:19:01 +00:00
set_bit ( __QLCNIC_FW_ATTACHED , & adapter - > state ) ;
return 0 ;
}
2010-01-13 00:37:25 +00:00
2010-06-22 03:19:01 +00:00
void qlcnic_fw_destroy_ctx ( struct qlcnic_adapter * adapter )
{
2010-01-13 00:37:25 +00:00
if ( test_and_clear_bit ( __QLCNIC_FW_ATTACHED , & adapter - > state ) ) {
qlcnic_fw_cmd_destroy_rx_ctx ( adapter ) ;
qlcnic_fw_cmd_destroy_tx_ctx ( adapter ) ;
/* Allow dma queues to drain after context reset */
msleep ( 20 ) ;
}
2010-06-22 03:19:01 +00:00
}
void qlcnic_free_hw_resources ( struct qlcnic_adapter * adapter )
{
struct qlcnic_recv_context * recv_ctx ;
struct qlcnic_host_rds_ring * rds_ring ;
struct qlcnic_host_sds_ring * sds_ring ;
struct qlcnic_host_tx_ring * tx_ring ;
int ring ;
2010-01-13 00:37:25 +00:00
2011-04-01 14:28:05 +00:00
recv_ctx = adapter - > recv_ctx ;
2010-01-13 00:37:25 +00:00
tx_ring = adapter - > tx_ring ;
if ( tx_ring - > hw_consumer ! = NULL ) {
2011-04-01 14:28:05 +00:00
dma_free_coherent ( & adapter - > pdev - > dev ,
2010-01-13 00:37:25 +00:00
sizeof ( u32 ) ,
tx_ring - > hw_consumer ,
tx_ring - > hw_cons_phys_addr ) ;
tx_ring - > hw_consumer = NULL ;
}
if ( tx_ring - > desc_head ! = NULL ) {
2011-04-01 14:28:05 +00:00
dma_free_coherent ( & adapter - > pdev - > dev ,
2010-01-13 00:37:25 +00:00
TX_DESC_RINGSIZE ( tx_ring ) ,
tx_ring - > desc_head , tx_ring - > phys_addr ) ;
tx_ring - > desc_head = NULL ;
}
for ( ring = 0 ; ring < adapter - > max_rds_rings ; ring + + ) {
rds_ring = & recv_ctx - > rds_rings [ ring ] ;
if ( rds_ring - > desc_head ! = NULL ) {
2011-04-01 14:28:05 +00:00
dma_free_coherent ( & adapter - > pdev - > dev ,
2010-01-13 00:37:25 +00:00
RCV_DESC_RINGSIZE ( rds_ring ) ,
rds_ring - > desc_head ,
rds_ring - > phys_addr ) ;
rds_ring - > desc_head = NULL ;
}
}
for ( ring = 0 ; ring < adapter - > max_sds_rings ; ring + + ) {
sds_ring = & recv_ctx - > sds_rings [ ring ] ;
if ( sds_ring - > desc_head ! = NULL ) {
2011-04-01 14:28:05 +00:00
dma_free_coherent ( & adapter - > pdev - > dev ,
2010-01-13 00:37:25 +00:00
STATUS_DESC_RINGSIZE ( sds_ring ) ,
sds_ring - > desc_head ,
sds_ring - > phys_addr ) ;
sds_ring - > desc_head = NULL ;
}
}
}
2010-06-01 11:28:51 +00:00
/* Get MAC address of a NIC partition */
int qlcnic_get_mac_address ( struct qlcnic_adapter * adapter , u8 * mac )
{
int err ;
u32 arg1 ;
2011-04-01 14:28:05 +00:00
arg1 = adapter - > ahw - > pci_func | BIT_8 ;
2010-06-01 11:28:51 +00:00
err = qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-06-01 11:28:51 +00:00
adapter - > fw_hal_version ,
arg1 ,
0 ,
0 ,
QLCNIC_CDRP_CMD_MAC_ADDRESS ) ;
2010-06-17 02:56:39 +00:00
if ( err = = QLCNIC_RCODE_SUCCESS )
2010-06-01 11:28:51 +00:00
qlcnic_fetch_mac ( adapter , QLCNIC_ARG1_CRB_OFFSET ,
QLCNIC_ARG2_CRB_OFFSET , 0 , mac ) ;
2010-06-17 02:56:39 +00:00
else {
2010-06-01 11:28:51 +00:00
dev_err ( & adapter - > pdev - > dev ,
" Failed to get mac address%d \n " , err ) ;
err = - EIO ;
}
return err ;
}
/* Get info of a NIC partition */
2010-06-29 08:01:20 +00:00
int qlcnic_get_nic_info ( struct qlcnic_adapter * adapter ,
struct qlcnic_info * npar_info , u8 func_id )
2010-06-01 11:28:51 +00:00
{
int err ;
dma_addr_t nic_dma_t ;
struct qlcnic_info * nic_info ;
void * nic_info_addr ;
size_t nic_size = sizeof ( struct qlcnic_info ) ;
2011-04-01 14:28:05 +00:00
nic_info_addr = dma_alloc_coherent ( & adapter - > pdev - > dev , nic_size ,
& nic_dma_t , GFP_KERNEL ) ;
2010-06-01 11:28:51 +00:00
if ( ! nic_info_addr )
return - ENOMEM ;
memset ( nic_info_addr , 0 , nic_size ) ;
nic_info = ( struct qlcnic_info * ) nic_info_addr ;
err = qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-06-01 11:28:51 +00:00
adapter - > fw_hal_version ,
MSD ( nic_dma_t ) ,
LSD ( nic_dma_t ) ,
( func_id < < 16 | nic_size ) ,
QLCNIC_CDRP_CMD_GET_NIC_INFO ) ;
if ( err = = QLCNIC_RCODE_SUCCESS ) {
2010-07-13 20:33:35 +00:00
npar_info - > pci_func = le16_to_cpu ( nic_info - > pci_func ) ;
npar_info - > op_mode = le16_to_cpu ( nic_info - > op_mode ) ;
2010-06-29 08:01:20 +00:00
npar_info - > phys_port = le16_to_cpu ( nic_info - > phys_port ) ;
npar_info - > switch_mode = le16_to_cpu ( nic_info - > switch_mode ) ;
npar_info - > max_tx_ques = le16_to_cpu ( nic_info - > max_tx_ques ) ;
npar_info - > max_rx_ques = le16_to_cpu ( nic_info - > max_rx_ques ) ;
npar_info - > min_tx_bw = le16_to_cpu ( nic_info - > min_tx_bw ) ;
npar_info - > max_tx_bw = le16_to_cpu ( nic_info - > max_tx_bw ) ;
npar_info - > capabilities = le32_to_cpu ( nic_info - > capabilities ) ;
npar_info - > max_mtu = le16_to_cpu ( nic_info - > max_mtu ) ;
2010-06-16 09:07:27 +00:00
2010-06-01 11:28:51 +00:00
dev_info ( & adapter - > pdev - > dev ,
" phy port: %d switch_mode: %d, \n "
" \t max_tx_q: %d max_rx_q: %d min_tx_bw: 0x%x, \n "
" \t max_tx_bw: 0x%x max_mtu:0x%x, capabilities: 0x%x \n " ,
2010-06-29 08:01:20 +00:00
npar_info - > phys_port , npar_info - > switch_mode ,
npar_info - > max_tx_ques , npar_info - > max_rx_ques ,
npar_info - > min_tx_bw , npar_info - > max_tx_bw ,
npar_info - > max_mtu , npar_info - > capabilities ) ;
2010-06-01 11:28:51 +00:00
} else {
dev_err ( & adapter - > pdev - > dev ,
" Failed to get nic info%d \n " , err ) ;
err = - EIO ;
}
2011-04-01 14:28:05 +00:00
dma_free_coherent ( & adapter - > pdev - > dev , nic_size , nic_info_addr ,
nic_dma_t ) ;
2010-06-01 11:28:51 +00:00
return err ;
}
/* Configure a NIC partition */
int qlcnic_set_nic_info ( struct qlcnic_adapter * adapter , struct qlcnic_info * nic )
{
int err = - EIO ;
dma_addr_t nic_dma_t ;
void * nic_info_addr ;
struct qlcnic_info * nic_info ;
size_t nic_size = sizeof ( struct qlcnic_info ) ;
if ( adapter - > op_mode ! = QLCNIC_MGMT_FUNC )
return err ;
2011-04-01 14:28:05 +00:00
nic_info_addr = dma_alloc_coherent ( & adapter - > pdev - > dev , nic_size ,
& nic_dma_t , GFP_KERNEL ) ;
2010-06-01 11:28:51 +00:00
if ( ! nic_info_addr )
return - ENOMEM ;
memset ( nic_info_addr , 0 , nic_size ) ;
nic_info = ( struct qlcnic_info * ) nic_info_addr ;
nic_info - > pci_func = cpu_to_le16 ( nic - > pci_func ) ;
nic_info - > op_mode = cpu_to_le16 ( nic - > op_mode ) ;
nic_info - > phys_port = cpu_to_le16 ( nic - > phys_port ) ;
nic_info - > switch_mode = cpu_to_le16 ( nic - > switch_mode ) ;
nic_info - > capabilities = cpu_to_le32 ( nic - > capabilities ) ;
nic_info - > max_mac_filters = nic - > max_mac_filters ;
nic_info - > max_tx_ques = cpu_to_le16 ( nic - > max_tx_ques ) ;
nic_info - > max_rx_ques = cpu_to_le16 ( nic - > max_rx_ques ) ;
nic_info - > min_tx_bw = cpu_to_le16 ( nic - > min_tx_bw ) ;
nic_info - > max_tx_bw = cpu_to_le16 ( nic - > max_tx_bw ) ;
err = qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-06-01 11:28:51 +00:00
adapter - > fw_hal_version ,
MSD ( nic_dma_t ) ,
LSD ( nic_dma_t ) ,
2010-06-29 08:01:20 +00:00
( ( nic - > pci_func < < 16 ) | nic_size ) ,
2010-06-01 11:28:51 +00:00
QLCNIC_CDRP_CMD_SET_NIC_INFO ) ;
if ( err ! = QLCNIC_RCODE_SUCCESS ) {
dev_err ( & adapter - > pdev - > dev ,
" Failed to set nic info%d \n " , err ) ;
err = - EIO ;
}
2011-04-01 14:28:05 +00:00
dma_free_coherent ( & adapter - > pdev - > dev , nic_size , nic_info_addr ,
nic_dma_t ) ;
2010-06-01 11:28:51 +00:00
return err ;
}
/* Get PCI Info of a partition */
2010-06-29 08:01:20 +00:00
int qlcnic_get_pci_info ( struct qlcnic_adapter * adapter ,
struct qlcnic_pci_info * pci_info )
2010-06-01 11:28:51 +00:00
{
int err = 0 , i ;
dma_addr_t pci_info_dma_t ;
struct qlcnic_pci_info * npar ;
void * pci_info_addr ;
size_t npar_size = sizeof ( struct qlcnic_pci_info ) ;
size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC ;
2011-04-01 14:28:05 +00:00
pci_info_addr = dma_alloc_coherent ( & adapter - > pdev - > dev , pci_size ,
& pci_info_dma_t , GFP_KERNEL ) ;
2010-06-01 11:28:51 +00:00
if ( ! pci_info_addr )
return - ENOMEM ;
memset ( pci_info_addr , 0 , pci_size ) ;
npar = ( struct qlcnic_pci_info * ) pci_info_addr ;
err = qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-06-01 11:28:51 +00:00
adapter - > fw_hal_version ,
MSD ( pci_info_dma_t ) ,
LSD ( pci_info_dma_t ) ,
pci_size ,
QLCNIC_CDRP_CMD_GET_PCI_INFO ) ;
if ( err = = QLCNIC_RCODE_SUCCESS ) {
2010-06-29 08:01:20 +00:00
for ( i = 0 ; i < QLCNIC_MAX_PCI_FUNC ; i + + , npar + + , pci_info + + ) {
2010-10-04 04:20:14 +00:00
pci_info - > id = le16_to_cpu ( npar - > id ) ;
pci_info - > active = le16_to_cpu ( npar - > active ) ;
pci_info - > type = le16_to_cpu ( npar - > type ) ;
2010-06-29 08:01:20 +00:00
pci_info - > default_port =
2010-10-04 04:20:14 +00:00
le16_to_cpu ( npar - > default_port ) ;
2010-06-29 08:01:20 +00:00
pci_info - > tx_min_bw =
2010-10-04 04:20:14 +00:00
le16_to_cpu ( npar - > tx_min_bw ) ;
2010-06-29 08:01:20 +00:00
pci_info - > tx_max_bw =
2010-10-04 04:20:14 +00:00
le16_to_cpu ( npar - > tx_max_bw ) ;
2010-06-29 08:01:20 +00:00
memcpy ( pci_info - > mac , npar - > mac , ETH_ALEN ) ;
2010-06-01 11:28:51 +00:00
}
} else {
dev_err ( & adapter - > pdev - > dev ,
" Failed to get PCI Info%d \n " , err ) ;
err = - EIO ;
}
2011-04-01 14:28:05 +00:00
dma_free_coherent ( & adapter - > pdev - > dev , pci_size , pci_info_addr ,
2010-06-01 11:28:51 +00:00
pci_info_dma_t ) ;
return err ;
}
/* Configure eSwitch for port mirroring */
int qlcnic_config_port_mirroring ( struct qlcnic_adapter * adapter , u8 id ,
u8 enable_mirroring , u8 pci_func )
{
int err = - EIO ;
u32 arg1 ;
if ( adapter - > op_mode ! = QLCNIC_MGMT_FUNC | |
! ( adapter - > eswitch [ id ] . flags & QLCNIC_SWITCH_ENABLE ) )
return err ;
arg1 = id | ( enable_mirroring ? BIT_4 : 0 ) ;
arg1 | = pci_func < < 8 ;
err = qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-06-01 11:28:51 +00:00
adapter - > fw_hal_version ,
arg1 ,
0 ,
0 ,
QLCNIC_CDRP_CMD_SET_PORTMIRRORING ) ;
if ( err ! = QLCNIC_RCODE_SUCCESS ) {
dev_err ( & adapter - > pdev - > dev ,
" Failed to configure port mirroring%d on eswitch:%d \n " ,
pci_func , id ) ;
} else {
dev_info ( & adapter - > pdev - > dev ,
" Configured eSwitch %d for port mirroring:%d \n " ,
id , pci_func ) ;
}
return err ;
}
2010-08-17 00:34:22 +00:00
int qlcnic_get_port_stats ( struct qlcnic_adapter * adapter , const u8 func ,
const u8 rx_tx , struct __qlcnic_esw_statistics * esw_stats ) {
size_t stats_size = sizeof ( struct __qlcnic_esw_statistics ) ;
2010-08-19 05:08:30 +00:00
struct __qlcnic_esw_statistics * stats ;
2010-08-17 00:34:22 +00:00
dma_addr_t stats_dma_t ;
void * stats_addr ;
u32 arg1 ;
int err ;
if ( esw_stats = = NULL )
return - ENOMEM ;
if ( adapter - > op_mode ! = QLCNIC_MGMT_FUNC & &
2011-04-01 14:28:05 +00:00
func ! = adapter - > ahw - > pci_func ) {
2010-08-17 00:34:22 +00:00
dev_err ( & adapter - > pdev - > dev ,
" Not privilege to query stats for func=%d " , func ) ;
return - EIO ;
}
2011-04-01 14:28:05 +00:00
stats_addr = dma_alloc_coherent ( & adapter - > pdev - > dev , stats_size ,
& stats_dma_t , GFP_KERNEL ) ;
2010-08-17 00:34:22 +00:00
if ( ! stats_addr ) {
dev_err ( & adapter - > pdev - > dev , " Unable to allocate memory \n " ) ;
return - ENOMEM ;
}
memset ( stats_addr , 0 , stats_size ) ;
arg1 = func | QLCNIC_STATS_VERSION < < 8 | QLCNIC_STATS_PORT < < 12 ;
arg1 | = rx_tx < < 15 | stats_size < < 16 ;
err = qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-08-17 00:34:22 +00:00
adapter - > fw_hal_version ,
arg1 ,
MSD ( stats_dma_t ) ,
LSD ( stats_dma_t ) ,
QLCNIC_CDRP_CMD_GET_ESWITCH_STATS ) ;
2010-08-19 05:08:30 +00:00
if ( ! err ) {
stats = ( struct __qlcnic_esw_statistics * ) stats_addr ;
esw_stats - > context_id = le16_to_cpu ( stats - > context_id ) ;
esw_stats - > version = le16_to_cpu ( stats - > version ) ;
esw_stats - > size = le16_to_cpu ( stats - > size ) ;
esw_stats - > multicast_frames =
le64_to_cpu ( stats - > multicast_frames ) ;
esw_stats - > broadcast_frames =
le64_to_cpu ( stats - > broadcast_frames ) ;
esw_stats - > unicast_frames = le64_to_cpu ( stats - > unicast_frames ) ;
esw_stats - > dropped_frames = le64_to_cpu ( stats - > dropped_frames ) ;
esw_stats - > local_frames = le64_to_cpu ( stats - > local_frames ) ;
esw_stats - > errors = le64_to_cpu ( stats - > errors ) ;
esw_stats - > numbytes = le64_to_cpu ( stats - > numbytes ) ;
}
2010-08-17 00:34:22 +00:00
2011-04-01 14:28:05 +00:00
dma_free_coherent ( & adapter - > pdev - > dev , stats_size , stats_addr ,
2010-08-17 00:34:22 +00:00
stats_dma_t ) ;
return err ;
}
int qlcnic_get_eswitch_stats ( struct qlcnic_adapter * adapter , const u8 eswitch ,
const u8 rx_tx , struct __qlcnic_esw_statistics * esw_stats ) {
struct __qlcnic_esw_statistics port_stats ;
u8 i ;
int ret = - EIO ;
if ( esw_stats = = NULL )
return - ENOMEM ;
if ( adapter - > op_mode ! = QLCNIC_MGMT_FUNC )
return - EIO ;
if ( adapter - > npars = = NULL )
return - EIO ;
2010-10-04 04:20:10 +00:00
memset ( esw_stats , 0 , sizeof ( u64 ) ) ;
esw_stats - > unicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL ;
esw_stats - > multicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL ;
esw_stats - > broadcast_frames = QLCNIC_ESW_STATS_NOT_AVAIL ;
esw_stats - > dropped_frames = QLCNIC_ESW_STATS_NOT_AVAIL ;
esw_stats - > errors = QLCNIC_ESW_STATS_NOT_AVAIL ;
esw_stats - > local_frames = QLCNIC_ESW_STATS_NOT_AVAIL ;
esw_stats - > numbytes = QLCNIC_ESW_STATS_NOT_AVAIL ;
2010-08-17 00:34:22 +00:00
esw_stats - > context_id = eswitch ;
for ( i = 0 ; i < QLCNIC_MAX_PCI_FUNC ; i + + ) {
if ( adapter - > npars [ i ] . phy_port ! = eswitch )
continue ;
memset ( & port_stats , 0 , sizeof ( struct __qlcnic_esw_statistics ) ) ;
if ( qlcnic_get_port_stats ( adapter , i , rx_tx , & port_stats ) )
continue ;
esw_stats - > size = port_stats . size ;
esw_stats - > version = port_stats . version ;
2010-10-04 04:20:10 +00:00
QLCNIC_ADD_ESW_STATS ( esw_stats - > unicast_frames ,
port_stats . unicast_frames ) ;
QLCNIC_ADD_ESW_STATS ( esw_stats - > multicast_frames ,
port_stats . multicast_frames ) ;
QLCNIC_ADD_ESW_STATS ( esw_stats - > broadcast_frames ,
port_stats . broadcast_frames ) ;
QLCNIC_ADD_ESW_STATS ( esw_stats - > dropped_frames ,
port_stats . dropped_frames ) ;
QLCNIC_ADD_ESW_STATS ( esw_stats - > errors ,
port_stats . errors ) ;
QLCNIC_ADD_ESW_STATS ( esw_stats - > local_frames ,
port_stats . local_frames ) ;
QLCNIC_ADD_ESW_STATS ( esw_stats - > numbytes ,
port_stats . numbytes ) ;
2010-08-17 00:34:22 +00:00
ret = 0 ;
}
return ret ;
}
int qlcnic_clear_esw_stats ( struct qlcnic_adapter * adapter , const u8 func_esw ,
const u8 port , const u8 rx_tx )
{
u32 arg1 ;
if ( adapter - > op_mode ! = QLCNIC_MGMT_FUNC )
return - EIO ;
if ( func_esw = = QLCNIC_STATS_PORT ) {
if ( port > = QLCNIC_MAX_PCI_FUNC )
goto err_ret ;
} else if ( func_esw = = QLCNIC_STATS_ESWITCH ) {
if ( port > = QLCNIC_NIU_MAX_XG_PORTS )
goto err_ret ;
} else {
goto err_ret ;
}
if ( rx_tx > QLCNIC_QUERY_TX_COUNTER )
goto err_ret ;
arg1 = port | QLCNIC_STATS_VERSION < < 8 | func_esw < < 12 ;
arg1 | = BIT_14 | rx_tx < < 15 ;
return qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-08-17 00:34:22 +00:00
adapter - > fw_hal_version ,
arg1 ,
0 ,
0 ,
QLCNIC_CDRP_CMD_GET_ESWITCH_STATS ) ;
err_ret :
dev_err ( & adapter - > pdev - > dev , " Invalid argument func_esw=%d port=%d "
" rx_ctx=%d \n " , func_esw , port , rx_tx ) ;
return - EIO ;
}
2010-08-19 05:08:25 +00:00
static int
__qlcnic_get_eswitch_port_config ( struct qlcnic_adapter * adapter ,
u32 * arg1 , u32 * arg2 )
{
int err = - EIO ;
u8 pci_func ;
pci_func = ( * arg1 > > 8 ) ;
err = qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-08-19 05:08:25 +00:00
adapter - > fw_hal_version ,
* arg1 ,
0 ,
0 ,
QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG ) ;
if ( err = = QLCNIC_RCODE_SUCCESS ) {
* arg1 = QLCRD32 ( adapter , QLCNIC_ARG1_CRB_OFFSET ) ;
* arg2 = QLCRD32 ( adapter , QLCNIC_ARG2_CRB_OFFSET ) ;
dev_info ( & adapter - > pdev - > dev ,
2010-08-31 17:17:50 +00:00
" eSwitch port config for pci func %d \n " , pci_func ) ;
2010-08-19 05:08:25 +00:00
} else {
dev_err ( & adapter - > pdev - > dev ,
2010-08-31 17:17:50 +00:00
" Failed to get eswitch port config for pci func %d \n " ,
pci_func ) ;
2010-08-19 05:08:25 +00:00
}
return err ;
}
/* Configure eSwitch port
op_mode = 0 for setting default port behavior
op_mode = 1 for setting vlan id
op_mode = 2 for deleting vlan id
op_type = 0 for vlan_id
op_type = 1 for port vlan_id
*/
int qlcnic_config_switch_port ( struct qlcnic_adapter * adapter ,
struct qlcnic_esw_func_cfg * esw_cfg )
{
int err = - EIO ;
u32 arg1 , arg2 = 0 ;
u8 pci_func ;
if ( adapter - > op_mode ! = QLCNIC_MGMT_FUNC )
return err ;
pci_func = esw_cfg - > pci_func ;
arg1 = ( adapter - > npars [ pci_func ] . phy_port & BIT_0 ) ;
arg1 | = ( pci_func < < 8 ) ;
if ( __qlcnic_get_eswitch_port_config ( adapter , & arg1 , & arg2 ) )
return err ;
arg1 & = ~ ( 0x0ff < < 8 ) ;
arg1 | = ( pci_func < < 8 ) ;
arg1 & = ~ ( BIT_2 | BIT_3 ) ;
switch ( esw_cfg - > op_mode ) {
case QLCNIC_PORT_DEFAULTS :
arg1 | = ( BIT_4 | BIT_6 | BIT_7 ) ;
arg2 | = ( BIT_0 | BIT_1 ) ;
if ( adapter - > capabilities & QLCNIC_FW_CAPABILITY_TSO )
arg2 | = ( BIT_2 | BIT_3 ) ;
if ( ! ( esw_cfg - > discard_tagged ) )
arg1 & = ~ BIT_4 ;
if ( ! ( esw_cfg - > promisc_mode ) )
arg1 & = ~ BIT_6 ;
2010-08-31 17:17:50 +00:00
if ( ! ( esw_cfg - > mac_override ) )
2010-08-19 05:08:25 +00:00
arg1 & = ~ BIT_7 ;
if ( ! ( esw_cfg - > mac_anti_spoof ) )
arg2 & = ~ BIT_0 ;
if ( ! ( esw_cfg - > offload_flags & BIT_0 ) )
arg2 & = ~ ( BIT_1 | BIT_2 | BIT_3 ) ;
if ( ! ( esw_cfg - > offload_flags & BIT_1 ) )
arg2 & = ~ BIT_2 ;
if ( ! ( esw_cfg - > offload_flags & BIT_2 ) )
arg2 & = ~ BIT_3 ;
break ;
case QLCNIC_ADD_VLAN :
arg1 | = ( BIT_2 | BIT_5 ) ;
arg1 | = ( esw_cfg - > vlan_id < < 16 ) ;
break ;
case QLCNIC_DEL_VLAN :
arg1 | = ( BIT_3 | BIT_5 ) ;
arg1 & = ~ ( 0x0ffff < < 16 ) ;
2010-08-25 04:03:02 +00:00
break ;
2010-08-19 05:08:25 +00:00
default :
return err ;
}
err = qlcnic_issue_cmd ( adapter ,
2011-04-01 14:28:05 +00:00
adapter - > ahw - > pci_func ,
2010-08-19 05:08:25 +00:00
adapter - > fw_hal_version ,
arg1 ,
arg2 ,
0 ,
QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH ) ;
if ( err ! = QLCNIC_RCODE_SUCCESS ) {
dev_err ( & adapter - > pdev - > dev ,
2010-08-31 17:17:50 +00:00
" Failed to configure eswitch pci func %d \n " , pci_func ) ;
2010-08-19 05:08:25 +00:00
} else {
dev_info ( & adapter - > pdev - > dev ,
2010-08-31 17:17:50 +00:00
" Configured eSwitch for pci func %d \n " , pci_func ) ;
2010-08-19 05:08:25 +00:00
}
return err ;
}
int
qlcnic_get_eswitch_port_config ( struct qlcnic_adapter * adapter ,
struct qlcnic_esw_func_cfg * esw_cfg )
{
u32 arg1 , arg2 ;
u8 phy_port ;
if ( adapter - > op_mode = = QLCNIC_MGMT_FUNC )
phy_port = adapter - > npars [ esw_cfg - > pci_func ] . phy_port ;
else
phy_port = adapter - > physical_port ;
arg1 = phy_port ;
arg1 | = ( esw_cfg - > pci_func < < 8 ) ;
if ( __qlcnic_get_eswitch_port_config ( adapter , & arg1 , & arg2 ) )
return - EIO ;
esw_cfg - > discard_tagged = ! ! ( arg1 & BIT_4 ) ;
esw_cfg - > host_vlan_tag = ! ! ( arg1 & BIT_5 ) ;
esw_cfg - > promisc_mode = ! ! ( arg1 & BIT_6 ) ;
2010-08-31 17:17:50 +00:00
esw_cfg - > mac_override = ! ! ( arg1 & BIT_7 ) ;
2010-08-19 05:08:25 +00:00
esw_cfg - > vlan_id = LSW ( arg1 > > 16 ) ;
esw_cfg - > mac_anti_spoof = ( arg2 & 0x1 ) ;
esw_cfg - > offload_flags = ( ( arg2 > > 1 ) & 0x7 ) ;
return 0 ;
}