2008-07-21 19:44:08 -07:00
/*
2009-02-25 15:57:56 +00:00
* Copyright ( C ) 2003 - 2009 NetXen , Inc .
2009-09-11 11:28:15 +00:00
* Copyright ( C ) 2009 - QLogic Corporation .
2008-07-21 19:44:08 -07:00
* All rights reserved .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that 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 this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston ,
* MA 02111 - 1307 , USA .
*
* The full GNU General Public License is included in this distribution
2010-01-14 01:53:23 +00:00
* in the file called " COPYING " .
2008-07-21 19:44:08 -07:00
*
*/
# include "netxen_nic_hw.h"
# include "netxen_nic.h"
# define NXHAL_VERSION 1
static u32
netxen_poll_rsp ( struct netxen_adapter * adapter )
{
2009-01-14 20:47:30 -08:00
u32 rsp = NX_CDRP_RSP_OK ;
2008-07-21 19:44:08 -07:00
int timeout = 0 ;
do {
/* give atleast 1ms for firmware to respond */
msleep ( 1 ) ;
if ( + + timeout > NX_OS_CRB_RETRY_COUNT )
return NX_CDRP_RSP_TIMEOUT ;
2009-04-07 22:50:45 +00:00
rsp = NXRD32 ( adapter , NX_CDRP_CRB_OFFSET ) ;
2008-07-21 19:44:08 -07:00
} while ( ! NX_CDRP_IS_RSP ( rsp ) ) ;
return rsp ;
}
static u32
netxen_issue_cmd ( struct netxen_adapter * adapter ,
u32 pci_fn , u32 version , u32 arg1 , u32 arg2 , u32 arg3 , u32 cmd )
{
u32 rsp ;
u32 signature = 0 ;
u32 rcode = NX_RCODE_SUCCESS ;
signature = NX_CDRP_SIGNATURE_MAKE ( pci_fn , version ) ;
/* Acquire semaphore before accessing CRB */
if ( netxen_api_lock ( adapter ) )
return NX_RCODE_TIMEOUT ;
2009-04-07 22:50:45 +00:00
NXWR32 ( adapter , NX_SIGN_CRB_OFFSET , signature ) ;
2008-07-21 19:44:08 -07:00
2009-04-07 22:50:45 +00:00
NXWR32 ( adapter , NX_ARG1_CRB_OFFSET , arg1 ) ;
2008-07-21 19:44:08 -07:00
2009-04-07 22:50:45 +00:00
NXWR32 ( adapter , NX_ARG2_CRB_OFFSET , arg2 ) ;
2008-07-21 19:44:08 -07:00
2009-04-07 22:50:45 +00:00
NXWR32 ( adapter , NX_ARG3_CRB_OFFSET , arg3 ) ;
2008-07-21 19:44:08 -07:00
2009-04-07 22:50:45 +00:00
NXWR32 ( adapter , NX_CDRP_CRB_OFFSET , NX_CDRP_FORM_CMD ( cmd ) ) ;
2008-07-21 19:44:08 -07:00
rsp = netxen_poll_rsp ( adapter ) ;
if ( rsp = = NX_CDRP_RSP_TIMEOUT ) {
printk ( KERN_ERR " %s: card response timeout. \n " ,
netxen_nic_driver_name ) ;
rcode = NX_RCODE_TIMEOUT ;
} else if ( rsp = = NX_CDRP_RSP_FAIL ) {
2009-04-07 22:50:45 +00:00
rcode = NXRD32 ( adapter , NX_ARG1_CRB_OFFSET ) ;
2008-07-21 19:44:08 -07:00
printk ( KERN_ERR " %s: failed card response code:0x%x \n " ,
netxen_nic_driver_name , rcode ) ;
}
/* Release semaphore */
netxen_api_unlock ( adapter ) ;
return rcode ;
}
2008-08-01 03:14:59 -07:00
int
nx_fw_cmd_set_mtu ( struct netxen_adapter * adapter , int mtu )
2008-07-21 19:44:08 -07:00
{
u32 rcode = NX_RCODE_SUCCESS ;
2009-03-09 08:50:55 +00:00
struct netxen_recv_context * recv_ctx = & adapter - > recv_ctx ;
2008-07-21 19:44:08 -07:00
if ( recv_ctx - > state = = NX_HOST_CTX_STATE_ACTIVE )
rcode = netxen_issue_cmd ( adapter ,
adapter - > ahw . pci_func ,
NXHAL_VERSION ,
recv_ctx - > context_id ,
mtu ,
0 ,
NX_CDRP_CMD_SET_MTU ) ;
2008-08-01 03:14:59 -07:00
if ( rcode ! = NX_RCODE_SUCCESS )
return - EIO ;
return 0 ;
2008-07-21 19:44:08 -07:00
}
2011-03-15 14:54:55 -07:00
int
nx_fw_cmd_set_gbe_port ( struct netxen_adapter * adapter ,
u32 speed , u32 duplex , u32 autoneg )
{
return netxen_issue_cmd ( adapter ,
adapter - > ahw . pci_func ,
NXHAL_VERSION ,
speed ,
duplex ,
autoneg ,
NX_CDRP_CMD_CONFIG_GBE_PORT ) ;
}
2008-07-21 19:44:08 -07:00
static int
nx_fw_cmd_create_rx_ctx ( struct netxen_adapter * adapter )
{
void * addr ;
nx_hostrq_rx_ctx_t * prq ;
nx_cardrsp_rx_ctx_t * prsp ;
nx_hostrq_rds_ring_t * prq_rds ;
nx_hostrq_sds_ring_t * prq_sds ;
nx_cardrsp_rds_ring_t * prsp_rds ;
nx_cardrsp_sds_ring_t * prsp_sds ;
struct nx_host_rds_ring * rds_ring ;
2009-03-13 14:52:05 +00:00
struct nx_host_sds_ring * sds_ring ;
2008-07-21 19:44:08 -07:00
dma_addr_t hostrq_phys_addr , cardrsp_phys_addr ;
u64 phys_addr ;
int i , nrds_rings , nsds_rings ;
size_t rq_size , rsp_size ;
2009-01-14 20:47:30 -08:00
u32 cap , reg , val ;
2008-07-21 19:44:08 -07:00
int err ;
2009-03-09 08:50:55 +00:00
struct netxen_recv_context * recv_ctx = & adapter - > recv_ctx ;
2008-07-21 19:44:08 -07:00
nrds_rings = adapter - > max_rds_rings ;
2009-03-13 14:52:05 +00:00
nsds_rings = adapter - > max_sds_rings ;
2008-07-21 19:44:08 -07:00
rq_size =
SIZEOF_HOSTRQ_RX ( nx_hostrq_rx_ctx_t , nrds_rings , nsds_rings ) ;
rsp_size =
SIZEOF_CARDRSP_RX ( nx_cardrsp_rx_ctx_t , nrds_rings , nsds_rings ) ;
addr = pci_alloc_consistent ( adapter - > pdev ,
rq_size , & hostrq_phys_addr ) ;
if ( addr = = NULL )
return - ENOMEM ;
prq = ( nx_hostrq_rx_ctx_t * ) addr ;
addr = pci_alloc_consistent ( adapter - > pdev ,
rsp_size , & cardrsp_phys_addr ) ;
if ( addr = = NULL ) {
err = - ENOMEM ;
goto out_free_rq ;
}
prsp = ( nx_cardrsp_rx_ctx_t * ) addr ;
prq - > host_rsp_dma_addr = cpu_to_le64 ( cardrsp_phys_addr ) ;
cap = ( NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN ) ;
cap | = ( NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS ) ;
prq - > capabilities [ 0 ] = cpu_to_le32 ( cap ) ;
prq - > host_int_crb_mode =
cpu_to_le32 ( NX_HOST_INT_CRB_MODE_SHARED ) ;
prq - > host_rds_crb_mode =
cpu_to_le32 ( NX_HOST_RDS_CRB_MODE_UNIQUE ) ;
prq - > num_rds_rings = cpu_to_le16 ( nrds_rings ) ;
prq - > num_sds_rings = cpu_to_le16 ( nsds_rings ) ;
2009-01-14 20:47:30 -08:00
prq - > rds_ring_offset = cpu_to_le32 ( 0 ) ;
val = le32_to_cpu ( prq - > rds_ring_offset ) +
2008-07-21 19:44:08 -07:00
( sizeof ( nx_hostrq_rds_ring_t ) * nrds_rings ) ;
2009-01-14 20:47:30 -08:00
prq - > sds_ring_offset = cpu_to_le32 ( val ) ;
2008-07-21 19:44:08 -07:00
2009-01-14 20:47:30 -08:00
prq_rds = ( nx_hostrq_rds_ring_t * ) ( prq - > data +
le32_to_cpu ( prq - > rds_ring_offset ) ) ;
2008-07-21 19:44:08 -07:00
for ( i = 0 ; i < nrds_rings ; i + + ) {
rds_ring = & recv_ctx - > rds_rings [ i ] ;
prq_rds [ i ] . host_phys_addr = cpu_to_le64 ( rds_ring - > phys_addr ) ;
2009-03-13 14:52:03 +00:00
prq_rds [ i ] . ring_size = cpu_to_le32 ( rds_ring - > num_desc ) ;
2008-07-21 19:44:08 -07:00
prq_rds [ i ] . ring_kind = cpu_to_le32 ( i ) ;
prq_rds [ i ] . buff_size = cpu_to_le64 ( rds_ring - > dma_size ) ;
}
2009-01-14 20:47:30 -08:00
prq_sds = ( nx_hostrq_sds_ring_t * ) ( prq - > data +
le32_to_cpu ( prq - > sds_ring_offset ) ) ;
2008-07-21 19:44:08 -07:00
2009-03-13 14:52:05 +00:00
for ( i = 0 ; i < nsds_rings ; i + + ) {
sds_ring = & recv_ctx - > sds_rings [ i ] ;
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 ) ;
}
2008-07-21 19:44:08 -07:00
phys_addr = hostrq_phys_addr ;
err = netxen_issue_cmd ( adapter ,
adapter - > ahw . pci_func ,
NXHAL_VERSION ,
( u32 ) ( phys_addr > > 32 ) ,
( u32 ) ( phys_addr & 0xffffffff ) ,
rq_size ,
NX_CDRP_CMD_CREATE_RX_CTX ) ;
if ( err ) {
printk ( KERN_WARNING
" Failed to create rx ctx in firmware%d \n " , err ) ;
goto out_free_rsp ;
}
prsp_rds = ( ( nx_cardrsp_rds_ring_t * )
2009-01-14 20:47:30 -08:00
& prsp - > data [ le32_to_cpu ( prsp - > rds_ring_offset ) ] ) ;
2008-07-21 19:44:08 -07:00
2009-01-14 20:47:30 -08:00
for ( i = 0 ; i < le16_to_cpu ( prsp - > num_rds_rings ) ; i + + ) {
2008-07-21 19:44:08 -07:00
rds_ring = & recv_ctx - > rds_rings [ i ] ;
reg = le32_to_cpu ( prsp_rds [ i ] . host_producer_crb ) ;
2009-09-05 17:43:10 +00:00
rds_ring - > crb_rcv_producer = netxen_get_ioaddr ( adapter ,
NETXEN_NIC_REG ( reg - 0x200 ) ) ;
2008-07-21 19:44:08 -07:00
}
prsp_sds = ( ( nx_cardrsp_sds_ring_t * )
2009-01-14 20:47:30 -08:00
& prsp - > data [ le32_to_cpu ( prsp - > sds_ring_offset ) ] ) ;
2008-07-21 19:44:08 -07:00
2009-03-13 14:52:05 +00:00
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 ) ;
2009-09-05 17:43:10 +00:00
sds_ring - > crb_sts_consumer = netxen_get_ioaddr ( adapter ,
NETXEN_NIC_REG ( reg - 0x200 ) ) ;
2009-03-13 14:52:05 +00:00
reg = le32_to_cpu ( prsp_sds [ i ] . interrupt_crb ) ;
2009-09-05 17:43:10 +00:00
sds_ring - > crb_intr_mask = netxen_get_ioaddr ( adapter ,
NETXEN_NIC_REG ( reg - 0x200 ) ) ;
2009-03-13 14:52:05 +00:00
}
2008-07-21 19:44:08 -07:00
recv_ctx - > state = le32_to_cpu ( prsp - > host_ctx_state ) ;
recv_ctx - > context_id = le16_to_cpu ( prsp - > context_id ) ;
2009-01-14 20:47:30 -08:00
recv_ctx - > virt_port = prsp - > virt_port ;
2008-07-21 19:44:08 -07:00
out_free_rsp :
pci_free_consistent ( adapter - > pdev , rsp_size , prsp , cardrsp_phys_addr ) ;
out_free_rq :
pci_free_consistent ( adapter - > pdev , rq_size , prq , hostrq_phys_addr ) ;
return err ;
}
static void
nx_fw_cmd_destroy_rx_ctx ( struct netxen_adapter * adapter )
{
2009-03-09 08:50:55 +00:00
struct netxen_recv_context * recv_ctx = & adapter - > recv_ctx ;
2008-07-21 19:44:08 -07:00
if ( netxen_issue_cmd ( adapter ,
adapter - > ahw . pci_func ,
NXHAL_VERSION ,
recv_ctx - > context_id ,
NX_DESTROY_CTX_RESET ,
0 ,
NX_CDRP_CMD_DESTROY_RX_CTX ) ) {
printk ( KERN_WARNING
" %s: Failed to destroy rx ctx in firmware \n " ,
netxen_nic_driver_name ) ;
}
}
static int
nx_fw_cmd_create_tx_ctx ( struct netxen_adapter * adapter )
{
nx_hostrq_tx_ctx_t * prq ;
nx_hostrq_cds_ring_t * prq_cds ;
nx_cardrsp_tx_ctx_t * prsp ;
void * rq_addr , * rsp_addr ;
size_t rq_size , rsp_size ;
u32 temp ;
int err = 0 ;
u64 offset , phys_addr ;
dma_addr_t rq_phys_addr , rsp_phys_addr ;
2009-04-28 15:29:10 +00:00
struct nx_host_tx_ring * tx_ring = adapter - > tx_ring ;
struct netxen_recv_context * recv_ctx = & adapter - > recv_ctx ;
2008-07-21 19:44:08 -07:00
rq_size = SIZEOF_HOSTRQ_TX ( nx_hostrq_tx_ctx_t ) ;
rq_addr = pci_alloc_consistent ( adapter - > pdev ,
rq_size , & rq_phys_addr ) ;
if ( ! rq_addr )
return - ENOMEM ;
rsp_size = SIZEOF_CARDRSP_TX ( nx_cardrsp_tx_ctx_t ) ;
rsp_addr = pci_alloc_consistent ( adapter - > pdev ,
rsp_size , & rsp_phys_addr ) ;
if ( ! rsp_addr ) {
err = - ENOMEM ;
goto out_free_rq ;
}
memset ( rq_addr , 0 , rq_size ) ;
prq = ( nx_hostrq_tx_ctx_t * ) rq_addr ;
memset ( rsp_addr , 0 , rsp_size ) ;
prsp = ( nx_cardrsp_tx_ctx_t * ) rsp_addr ;
prq - > host_rsp_dma_addr = cpu_to_le64 ( rsp_phys_addr ) ;
temp = ( NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN | NX_CAP0_LSO ) ;
prq - > capabilities [ 0 ] = cpu_to_le32 ( temp ) ;
prq - > host_int_crb_mode =
cpu_to_le32 ( NX_HOST_INT_CRB_MODE_SHARED ) ;
prq - > interrupt_ctl = 0 ;
prq - > msi_index = 0 ;
prq - > dummy_dma_addr = cpu_to_le64 ( adapter - > dummy_dma . phys_addr ) ;
2009-04-28 15:29:10 +00:00
offset = recv_ctx - > phys_addr + sizeof ( struct netxen_ring_ctx ) ;
2008-07-21 19:44:08 -07:00
prq - > cmd_cons_dma_addr = cpu_to_le64 ( offset ) ;
prq_cds = & prq - > cds_ring ;
2009-04-07 22:50:40 +00:00
prq_cds - > host_phys_addr = cpu_to_le64 ( tx_ring - > phys_addr ) ;
prq_cds - > ring_size = cpu_to_le32 ( tx_ring - > num_desc ) ;
2008-07-21 19:44:08 -07:00
phys_addr = rq_phys_addr ;
err = netxen_issue_cmd ( adapter ,
adapter - > ahw . pci_func ,
NXHAL_VERSION ,
( u32 ) ( phys_addr > > 32 ) ,
( ( u32 ) phys_addr & 0xffffffff ) ,
rq_size ,
NX_CDRP_CMD_CREATE_TX_CTX ) ;
if ( err = = NX_RCODE_SUCCESS ) {
temp = le32_to_cpu ( prsp - > cds_ring . host_producer_crb ) ;
2009-09-05 17:43:10 +00:00
tx_ring - > crb_cmd_producer = netxen_get_ioaddr ( adapter ,
NETXEN_NIC_REG ( temp - 0x200 ) ) ;
2008-07-21 19:44:08 -07:00
#if 0
adapter - > tx_state =
le32_to_cpu ( prsp - > host_ctx_state ) ;
# endif
adapter - > tx_context_id =
le16_to_cpu ( prsp - > context_id ) ;
} else {
printk ( KERN_WARNING
" Failed to create tx ctx in firmware%d \n " , err ) ;
err = - EIO ;
}
pci_free_consistent ( adapter - > pdev , rsp_size , rsp_addr , rsp_phys_addr ) ;
out_free_rq :
pci_free_consistent ( adapter - > pdev , rq_size , rq_addr , rq_phys_addr ) ;
return err ;
}
static void
nx_fw_cmd_destroy_tx_ctx ( struct netxen_adapter * adapter )
{
if ( netxen_issue_cmd ( adapter ,
adapter - > ahw . pci_func ,
NXHAL_VERSION ,
adapter - > tx_context_id ,
NX_DESTROY_CTX_RESET ,
0 ,
NX_CDRP_CMD_DESTROY_TX_CTX ) ) {
printk ( KERN_WARNING
" %s: Failed to destroy tx ctx in firmware \n " ,
netxen_nic_driver_name ) ;
}
}
2009-08-24 19:23:27 +00:00
int
nx_fw_cmd_query_phy ( struct netxen_adapter * adapter , u32 reg , u32 * val )
{
u32 rcode ;
rcode = netxen_issue_cmd ( adapter ,
adapter - > ahw . pci_func ,
NXHAL_VERSION ,
reg ,
0 ,
0 ,
NX_CDRP_CMD_READ_PHY ) ;
if ( rcode ! = NX_RCODE_SUCCESS )
return - EIO ;
return NXRD32 ( adapter , NX_ARG1_CRB_OFFSET ) ;
}
int
nx_fw_cmd_set_phy ( struct netxen_adapter * adapter , u32 reg , u32 val )
{
u32 rcode ;
rcode = netxen_issue_cmd ( adapter ,
adapter - > ahw . pci_func ,
NXHAL_VERSION ,
reg ,
val ,
0 ,
NX_CDRP_CMD_WRITE_PHY ) ;
if ( rcode ! = NX_RCODE_SUCCESS )
return - EIO ;
return 0 ;
}
2008-07-21 19:44:08 -07:00
static u64 ctx_addr_sig_regs [ ] [ 3 ] = {
{ NETXEN_NIC_REG ( 0x188 ) , NETXEN_NIC_REG ( 0x18c ) , NETXEN_NIC_REG ( 0x1c0 ) } ,
{ NETXEN_NIC_REG ( 0x190 ) , NETXEN_NIC_REG ( 0x194 ) , NETXEN_NIC_REG ( 0x1c4 ) } ,
{ NETXEN_NIC_REG ( 0x198 ) , NETXEN_NIC_REG ( 0x19c ) , NETXEN_NIC_REG ( 0x1c8 ) } ,
{ NETXEN_NIC_REG ( 0x1a0 ) , NETXEN_NIC_REG ( 0x1a4 ) , NETXEN_NIC_REG ( 0x1cc ) }
} ;
# define CRB_CTX_ADDR_REG_LO(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][0])
# define CRB_CTX_ADDR_REG_HI(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][2])
# define CRB_CTX_SIGNATURE_REG(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][1])
# define lower32(x) ((u32)((x) & 0xffffffff))
# define upper32(x) ((u32)(((u64)(x) >> 32) & 0xffffffff))
static struct netxen_recv_crb recv_crb_registers [ ] = {
/* Instance 0 */
{
/* crb_rcv_producer: */
{
NETXEN_NIC_REG ( 0x100 ) ,
/* Jumbo frames */
NETXEN_NIC_REG ( 0x110 ) ,
/* LRO */
NETXEN_NIC_REG ( 0x120 )
} ,
/* crb_sts_consumer: */
2009-04-07 22:50:46 +00:00
{
NETXEN_NIC_REG ( 0x138 ) ,
NETXEN_NIC_REG_2 ( 0x000 ) ,
NETXEN_NIC_REG_2 ( 0x004 ) ,
NETXEN_NIC_REG_2 ( 0x008 ) ,
} ,
/* sw_int_mask */
{
CRB_SW_INT_MASK_0 ,
NETXEN_NIC_REG_2 ( 0x044 ) ,
NETXEN_NIC_REG_2 ( 0x048 ) ,
NETXEN_NIC_REG_2 ( 0x04c ) ,
} ,
2008-07-21 19:44:08 -07:00
} ,
/* Instance 1 */
{
/* crb_rcv_producer: */
{
NETXEN_NIC_REG ( 0x144 ) ,
/* Jumbo frames */
NETXEN_NIC_REG ( 0x154 ) ,
/* LRO */
NETXEN_NIC_REG ( 0x164 )
} ,
/* crb_sts_consumer: */
2009-04-07 22:50:46 +00:00
{
NETXEN_NIC_REG ( 0x17c ) ,
NETXEN_NIC_REG_2 ( 0x020 ) ,
NETXEN_NIC_REG_2 ( 0x024 ) ,
NETXEN_NIC_REG_2 ( 0x028 ) ,
} ,
/* sw_int_mask */
{
CRB_SW_INT_MASK_1 ,
NETXEN_NIC_REG_2 ( 0x064 ) ,
NETXEN_NIC_REG_2 ( 0x068 ) ,
NETXEN_NIC_REG_2 ( 0x06c ) ,
} ,
2008-07-21 19:44:08 -07:00
} ,
/* Instance 2 */
{
/* crb_rcv_producer: */
{
NETXEN_NIC_REG ( 0x1d8 ) ,
/* Jumbo frames */
NETXEN_NIC_REG ( 0x1f8 ) ,
/* LRO */
NETXEN_NIC_REG ( 0x208 )
} ,
/* crb_sts_consumer: */
2009-04-07 22:50:46 +00:00
{
NETXEN_NIC_REG ( 0x220 ) ,
NETXEN_NIC_REG_2 ( 0x03c ) ,
NETXEN_NIC_REG_2 ( 0x03c ) ,
NETXEN_NIC_REG_2 ( 0x03c ) ,
} ,
/* sw_int_mask */
{
CRB_SW_INT_MASK_2 ,
NETXEN_NIC_REG_2 ( 0x03c ) ,
NETXEN_NIC_REG_2 ( 0x03c ) ,
NETXEN_NIC_REG_2 ( 0x03c ) ,
} ,
2008-07-21 19:44:08 -07:00
} ,
/* Instance 3 */
{
/* crb_rcv_producer: */
{
NETXEN_NIC_REG ( 0x22c ) ,
/* Jumbo frames */
NETXEN_NIC_REG ( 0x23c ) ,
/* LRO */
NETXEN_NIC_REG ( 0x24c )
} ,
/* crb_sts_consumer: */
2009-04-07 22:50:46 +00:00
{
NETXEN_NIC_REG ( 0x264 ) ,
NETXEN_NIC_REG_2 ( 0x03c ) ,
NETXEN_NIC_REG_2 ( 0x03c ) ,
NETXEN_NIC_REG_2 ( 0x03c ) ,
} ,
/* sw_int_mask */
{
CRB_SW_INT_MASK_3 ,
NETXEN_NIC_REG_2 ( 0x03c ) ,
NETXEN_NIC_REG_2 ( 0x03c ) ,
NETXEN_NIC_REG_2 ( 0x03c ) ,
} ,
2008-07-21 19:44:08 -07:00
} ,
} ;
static int
netxen_init_old_ctx ( struct netxen_adapter * adapter )
{
struct netxen_recv_context * recv_ctx ;
struct nx_host_rds_ring * rds_ring ;
2009-03-13 14:52:05 +00:00
struct nx_host_sds_ring * sds_ring ;
2009-04-07 22:50:40 +00:00
struct nx_host_tx_ring * tx_ring ;
2009-03-09 08:50:55 +00:00
int ring ;
2009-04-07 22:50:46 +00:00
int port = adapter - > portnum ;
2009-04-28 15:29:10 +00:00
struct netxen_ring_ctx * hwctx ;
2009-04-07 22:50:46 +00:00
u32 signature ;
2008-07-21 19:44:08 -07:00
2009-04-28 15:29:10 +00:00
tx_ring = adapter - > tx_ring ;
recv_ctx = & adapter - > recv_ctx ;
hwctx = recv_ctx - > hwctx ;
2009-04-07 22:50:46 +00:00
hwctx - > cmd_ring_addr = cpu_to_le64 ( tx_ring - > phys_addr ) ;
hwctx - > cmd_ring_size = cpu_to_le32 ( tx_ring - > num_desc ) ;
2008-07-21 19:44:08 -07:00
2009-03-09 08:50:55 +00:00
for ( ring = 0 ; ring < adapter - > max_rds_rings ; ring + + ) {
rds_ring = & recv_ctx - > rds_rings [ ring ] ;
2008-07-21 19:44:08 -07:00
2009-04-07 22:50:46 +00:00
hwctx - > rcv_rings [ ring ] . addr =
2009-03-09 08:50:55 +00:00
cpu_to_le64 ( rds_ring - > phys_addr ) ;
2009-04-07 22:50:46 +00:00
hwctx - > rcv_rings [ ring ] . size =
2009-03-13 14:52:03 +00:00
cpu_to_le32 ( rds_ring - > num_desc ) ;
2008-07-21 19:44:08 -07:00
}
2009-04-07 22:50:46 +00:00
for ( ring = 0 ; ring < adapter - > max_sds_rings ; ring + + ) {
sds_ring = & recv_ctx - > sds_rings [ ring ] ;
if ( ring = = 0 ) {
hwctx - > sts_ring_addr = cpu_to_le64 ( sds_ring - > phys_addr ) ;
hwctx - > sts_ring_size = cpu_to_le32 ( sds_ring - > num_desc ) ;
}
hwctx - > sts_rings [ ring ] . addr = cpu_to_le64 ( sds_ring - > phys_addr ) ;
hwctx - > sts_rings [ ring ] . size = cpu_to_le32 ( sds_ring - > num_desc ) ;
hwctx - > sts_rings [ ring ] . msi_index = cpu_to_le16 ( ring ) ;
}
hwctx - > sts_ring_count = cpu_to_le32 ( adapter - > max_sds_rings ) ;
signature = ( adapter - > max_sds_rings > 1 ) ?
NETXEN_CTX_SIGNATURE_V2 : NETXEN_CTX_SIGNATURE ;
NXWR32 ( adapter , CRB_CTX_ADDR_REG_LO ( port ) ,
2009-04-28 15:29:10 +00:00
lower32 ( recv_ctx - > phys_addr ) ) ;
2009-04-07 22:50:46 +00:00
NXWR32 ( adapter , CRB_CTX_ADDR_REG_HI ( port ) ,
2009-04-28 15:29:10 +00:00
upper32 ( recv_ctx - > phys_addr ) ) ;
2009-04-07 22:50:46 +00:00
NXWR32 ( adapter , CRB_CTX_SIGNATURE_REG ( port ) ,
signature | port ) ;
2008-07-21 19:44:08 -07:00
return 0 ;
}
int netxen_alloc_hw_resources ( struct netxen_adapter * adapter )
{
void * addr ;
int err = 0 ;
2009-03-09 08:50:55 +00:00
int ring ;
2008-07-21 19:44:08 -07:00
struct netxen_recv_context * recv_ctx ;
struct nx_host_rds_ring * rds_ring ;
2009-03-13 14:52:05 +00:00
struct nx_host_sds_ring * sds_ring ;
2009-04-28 15:29:10 +00:00
struct nx_host_tx_ring * tx_ring ;
2009-03-13 14:52:05 +00:00
struct pci_dev * pdev = adapter - > pdev ;
struct net_device * netdev = adapter - > netdev ;
2009-04-07 22:50:46 +00:00
int port = adapter - > portnum ;
2008-07-21 19:44:08 -07:00
2009-04-28 15:29:10 +00:00
recv_ctx = & adapter - > recv_ctx ;
tx_ring = adapter - > tx_ring ;
2009-03-13 14:52:05 +00:00
addr = pci_alloc_consistent ( pdev ,
2008-07-21 19:44:08 -07:00
sizeof ( struct netxen_ring_ctx ) + sizeof ( uint32_t ) ,
2009-04-28 15:29:10 +00:00
& recv_ctx - > phys_addr ) ;
2008-07-21 19:44:08 -07:00
if ( addr = = NULL ) {
2009-03-13 14:52:05 +00:00
dev_err ( & pdev - > dev , " failed to allocate hw context \n " ) ;
2008-07-21 19:44:08 -07:00
return - ENOMEM ;
}
2009-04-28 15:29:10 +00:00
2008-07-21 19:44:08 -07:00
memset ( addr , 0 , sizeof ( struct netxen_ring_ctx ) ) ;
2009-04-28 15:29:10 +00:00
recv_ctx - > hwctx = ( struct netxen_ring_ctx * ) addr ;
recv_ctx - > hwctx - > ctx_id = cpu_to_le32 ( port ) ;
recv_ctx - > hwctx - > cmd_consumer_offset =
cpu_to_le64 ( recv_ctx - > phys_addr +
2008-07-21 19:44:08 -07:00
sizeof ( struct netxen_ring_ctx ) ) ;
2009-04-07 22:50:40 +00:00
tx_ring - > hw_consumer =
2008-07-21 19:44:08 -07:00
( __le32 * ) ( ( ( char * ) addr ) + sizeof ( struct netxen_ring_ctx ) ) ;
/* cmd desc ring */
2009-04-07 22:50:40 +00:00
addr = pci_alloc_consistent ( pdev , TX_DESC_RINGSIZE ( tx_ring ) ,
& tx_ring - > phys_addr ) ;
2008-07-21 19:44:08 -07:00
if ( addr = = NULL ) {
2009-03-13 14:52:05 +00:00
dev_err ( & pdev - > dev , " %s: failed to allocate tx desc ring \n " ,
netdev - > name ) ;
2010-06-13 23:39:03 +00:00
err = - ENOMEM ;
goto err_out_free ;
2008-07-21 19:44:08 -07:00
}
2009-04-07 22:50:40 +00:00
tx_ring - > desc_head = ( struct cmd_desc_type0 * ) addr ;
2008-07-21 19:44:08 -07:00
2009-03-09 08:50:55 +00:00
for ( ring = 0 ; ring < adapter - > max_rds_rings ; ring + + ) {
rds_ring = & recv_ctx - > rds_rings [ ring ] ;
2008-07-21 19:44:08 -07:00
addr = pci_alloc_consistent ( adapter - > pdev ,
2009-03-13 14:52:05 +00:00
RCV_DESC_RINGSIZE ( rds_ring ) ,
2009-03-09 08:50:55 +00:00
& rds_ring - > phys_addr ) ;
2008-07-21 19:44:08 -07:00
if ( addr = = NULL ) {
2009-03-13 14:52:05 +00:00
dev_err ( & pdev - > dev ,
" %s: failed to allocate rds ring [%d] \n " ,
netdev - > name , ring ) ;
2008-07-21 19:44:08 -07:00
err = - ENOMEM ;
goto err_out_free ;
}
2009-03-09 08:50:55 +00:00
rds_ring - > desc_head = ( struct rcv_desc * ) addr ;
2008-07-21 19:44:08 -07:00
2009-07-26 20:07:42 +00:00
if ( NX_IS_REVISION_P2 ( adapter - > ahw . revision_id ) )
2009-03-09 08:50:55 +00:00
rds_ring - > crb_rcv_producer =
2009-09-05 17:43:10 +00:00
netxen_get_ioaddr ( adapter ,
recv_crb_registers [ port ] . crb_rcv_producer [ ring ] ) ;
2008-07-21 19:44:08 -07:00
}
2009-03-13 14:52:05 +00:00
for ( ring = 0 ; ring < adapter - > max_sds_rings ; ring + + ) {
sds_ring = & recv_ctx - > sds_rings [ ring ] ;
addr = pci_alloc_consistent ( adapter - > pdev ,
STATUS_DESC_RINGSIZE ( sds_ring ) ,
& sds_ring - > phys_addr ) ;
if ( addr = = NULL ) {
dev_err ( & pdev - > dev ,
" %s: failed to allocate sds ring [%d] \n " ,
netdev - > name , ring ) ;
err = - ENOMEM ;
goto err_out_free ;
}
sds_ring - > desc_head = ( struct status_desc * ) addr ;
2009-04-07 22:50:46 +00:00
2010-03-26 00:30:08 +00:00
if ( NX_IS_REVISION_P2 ( adapter - > ahw . revision_id ) ) {
sds_ring - > crb_sts_consumer =
netxen_get_ioaddr ( adapter ,
recv_crb_registers [ port ] . crb_sts_consumer [ ring ] ) ;
2009-04-07 22:50:46 +00:00
2010-03-26 00:30:08 +00:00
sds_ring - > crb_intr_mask =
netxen_get_ioaddr ( adapter ,
recv_crb_registers [ port ] . sw_int_mask [ ring ] ) ;
}
2009-03-09 08:50:55 +00:00
}
2009-07-26 20:07:42 +00:00
if ( ! NX_IS_REVISION_P2 ( adapter - > ahw . revision_id ) ) {
2009-09-05 17:43:08 +00:00
if ( test_and_set_bit ( __NX_FW_ATTACHED , & adapter - > state ) )
goto done ;
2008-07-21 19:44:08 -07:00
err = nx_fw_cmd_create_rx_ctx ( adapter ) ;
if ( err )
goto err_out_free ;
err = nx_fw_cmd_create_tx_ctx ( adapter ) ;
if ( err )
goto err_out_free ;
} else {
err = netxen_init_old_ctx ( adapter ) ;
2009-07-17 15:27:06 +00:00
if ( err )
goto err_out_free ;
2008-07-21 19:44:08 -07:00
}
2009-09-05 17:43:08 +00:00
done :
2008-07-21 19:44:08 -07:00
return 0 ;
err_out_free :
netxen_free_hw_resources ( adapter ) ;
return err ;
}
void netxen_free_hw_resources ( struct netxen_adapter * adapter )
{
struct netxen_recv_context * recv_ctx ;
struct nx_host_rds_ring * rds_ring ;
2009-03-13 14:52:05 +00:00
struct nx_host_sds_ring * sds_ring ;
2009-04-07 22:50:40 +00:00
struct nx_host_tx_ring * tx_ring ;
2009-03-09 08:50:55 +00:00
int ring ;
2008-07-21 19:44:08 -07:00
2009-04-07 22:50:46 +00:00
int port = adapter - > portnum ;
2009-07-26 20:07:42 +00:00
if ( ! NX_IS_REVISION_P2 ( adapter - > ahw . revision_id ) ) {
2009-09-05 17:43:08 +00:00
if ( ! test_and_clear_bit ( __NX_FW_ATTACHED , & adapter - > state ) )
goto done ;
2008-07-21 19:44:08 -07:00
nx_fw_cmd_destroy_rx_ctx ( adapter ) ;
2009-07-17 15:27:06 +00:00
nx_fw_cmd_destroy_tx_ctx ( adapter ) ;
2009-04-07 22:50:46 +00:00
} else {
netxen_api_lock ( adapter ) ;
NXWR32 ( adapter , CRB_CTX_SIGNATURE_REG ( port ) ,
2009-07-17 15:27:06 +00:00
NETXEN_CTX_D3_RESET | port ) ;
2009-04-07 22:50:46 +00:00
netxen_api_unlock ( adapter ) ;
2008-07-21 19:44:08 -07:00
}
2009-07-17 15:27:06 +00:00
/* Allow dma queues to drain after context reset */
msleep ( 20 ) ;
2009-09-05 17:43:08 +00:00
done :
2009-04-28 15:29:10 +00:00
recv_ctx = & adapter - > recv_ctx ;
if ( recv_ctx - > hwctx ! = NULL ) {
2008-07-21 19:44:08 -07:00
pci_free_consistent ( adapter - > pdev ,
sizeof ( struct netxen_ring_ctx ) +
sizeof ( uint32_t ) ,
2009-04-28 15:29:10 +00:00
recv_ctx - > hwctx ,
recv_ctx - > phys_addr ) ;
recv_ctx - > hwctx = NULL ;
2008-07-21 19:44:08 -07:00
}
2009-04-28 15:29:10 +00:00
tx_ring = adapter - > tx_ring ;
2009-04-07 22:50:40 +00:00
if ( tx_ring - > desc_head ! = NULL ) {
2008-07-21 19:44:08 -07:00
pci_free_consistent ( adapter - > pdev ,
2009-04-07 22:50:40 +00:00
TX_DESC_RINGSIZE ( tx_ring ) ,
tx_ring - > desc_head , tx_ring - > phys_addr ) ;
tx_ring - > desc_head = NULL ;
2008-07-21 19:44:08 -07:00
}
2009-03-09 08:50:55 +00:00
for ( ring = 0 ; ring < adapter - > max_rds_rings ; ring + + ) {
rds_ring = & recv_ctx - > rds_rings [ ring ] ;
2008-07-21 19:44:08 -07:00
2009-03-09 08:50:55 +00:00
if ( rds_ring - > desc_head ! = NULL ) {
2008-07-21 19:44:08 -07:00
pci_free_consistent ( adapter - > pdev ,
2009-03-13 14:52:05 +00:00
RCV_DESC_RINGSIZE ( rds_ring ) ,
2009-03-09 08:50:55 +00:00
rds_ring - > desc_head ,
rds_ring - > phys_addr ) ;
rds_ring - > desc_head = NULL ;
2008-07-21 19:44:08 -07:00
}
}
2009-03-09 08:50:55 +00:00
2009-03-13 14:52:05 +00:00
for ( ring = 0 ; ring < adapter - > max_sds_rings ; ring + + ) {
sds_ring = & recv_ctx - > sds_rings [ ring ] ;
if ( sds_ring - > desc_head ! = NULL ) {
pci_free_consistent ( adapter - > pdev ,
STATUS_DESC_RINGSIZE ( sds_ring ) ,
sds_ring - > desc_head ,
sds_ring - > phys_addr ) ;
sds_ring - > desc_head = NULL ;
}
2009-03-09 08:50:55 +00:00
}
2008-07-21 19:44:08 -07:00
}