2006-10-21 15:33:03 -04:00
/*
* Copyright ( C ) 2003 - 2006 NetXen , Inc .
* All rights reserved .
2006-12-04 09:18:00 -08:00
*
2006-10-21 15:33:03 -04:00
* 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 .
2006-12-04 09:18:00 -08:00
*
2006-10-21 15:33:03 -04:00
* 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 .
2006-12-04 09:18:00 -08:00
*
2006-10-21 15:33:03 -04:00
* 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 .
2006-12-04 09:18:00 -08:00
*
2006-10-21 15:33:03 -04:00
* The full GNU General Public License is included in this distribution
* in the file called LICENSE .
2006-12-04 09:18:00 -08:00
*
2006-10-21 15:33:03 -04:00
* Contact Information :
* info @ netxen . com
* NetXen ,
* 3965 Freedom Circle , Fourth floor ,
* Santa Clara , CA 95054
*
*
* Source file for NIC routines to initialize the Phantom Hardware
*
*/
# include <linux/netdevice.h>
# include <linux/delay.h>
# include "netxen_nic.h"
# include "netxen_nic_hw.h"
# include "netxen_nic_phan_reg.h"
struct crb_addr_pair {
2007-02-28 05:16:40 -08:00
u32 addr ;
u32 data ;
2006-10-21 15:33:03 -04:00
} ;
# define NETXEN_MAX_CRB_XFORM 60
static unsigned int crb_addr_xform [ NETXEN_MAX_CRB_XFORM ] ;
2007-02-28 05:16:40 -08:00
# define NETXEN_ADDR_ERROR (0xffffffff)
2006-10-21 15:33:03 -04:00
# define crb_addr_transform(name) \
crb_addr_xform [ NETXEN_HW_PX_MAP_CRB_ # # name ] = \
NETXEN_HW_CRB_HUB_AGT_ADR_ # # name < < 20
2006-11-29 09:00:10 -08:00
# define NETXEN_NIC_XDMA_RESET 0x8000ff
2007-11-05 18:07:31 +01:00
static void netxen_post_rx_buffers_nodb ( struct netxen_adapter * adapter ,
uint32_t ctx , uint32_t ringid ) ;
#if 0
static void netxen_nic_locked_write_reg ( struct netxen_adapter * adapter ,
unsigned long off , int * data )
2006-10-21 15:33:03 -04:00
{
2006-11-29 09:00:10 -08:00
void __iomem * addr = pci_base_offset ( adapter , off ) ;
2006-10-21 15:33:03 -04:00
writel ( * data , addr ) ;
}
2007-11-05 18:07:31 +01:00
# endif /* 0 */
2006-10-21 15:33:03 -04:00
static void crb_addr_transform_setup ( void )
{
crb_addr_transform ( XDMA ) ;
crb_addr_transform ( TIMR ) ;
crb_addr_transform ( SRE ) ;
crb_addr_transform ( SQN3 ) ;
crb_addr_transform ( SQN2 ) ;
crb_addr_transform ( SQN1 ) ;
crb_addr_transform ( SQN0 ) ;
crb_addr_transform ( SQS3 ) ;
crb_addr_transform ( SQS2 ) ;
crb_addr_transform ( SQS1 ) ;
crb_addr_transform ( SQS0 ) ;
crb_addr_transform ( RPMX7 ) ;
crb_addr_transform ( RPMX6 ) ;
crb_addr_transform ( RPMX5 ) ;
crb_addr_transform ( RPMX4 ) ;
crb_addr_transform ( RPMX3 ) ;
crb_addr_transform ( RPMX2 ) ;
crb_addr_transform ( RPMX1 ) ;
crb_addr_transform ( RPMX0 ) ;
crb_addr_transform ( ROMUSB ) ;
crb_addr_transform ( SN ) ;
crb_addr_transform ( QMN ) ;
crb_addr_transform ( QMS ) ;
crb_addr_transform ( PGNI ) ;
crb_addr_transform ( PGND ) ;
crb_addr_transform ( PGN3 ) ;
crb_addr_transform ( PGN2 ) ;
crb_addr_transform ( PGN1 ) ;
crb_addr_transform ( PGN0 ) ;
crb_addr_transform ( PGSI ) ;
crb_addr_transform ( PGSD ) ;
crb_addr_transform ( PGS3 ) ;
crb_addr_transform ( PGS2 ) ;
crb_addr_transform ( PGS1 ) ;
crb_addr_transform ( PGS0 ) ;
crb_addr_transform ( PS ) ;
crb_addr_transform ( PH ) ;
crb_addr_transform ( NIU ) ;
crb_addr_transform ( I2Q ) ;
crb_addr_transform ( EG ) ;
crb_addr_transform ( MN ) ;
crb_addr_transform ( MS ) ;
crb_addr_transform ( CAS2 ) ;
crb_addr_transform ( CAS1 ) ;
crb_addr_transform ( CAS0 ) ;
crb_addr_transform ( CAM ) ;
crb_addr_transform ( C2C1 ) ;
crb_addr_transform ( C2C0 ) ;
2007-02-05 07:35:26 -08:00
crb_addr_transform ( SMB ) ;
2008-07-21 19:44:02 -07:00
crb_addr_transform ( OCM0 ) ;
crb_addr_transform ( I2C0 ) ;
2006-10-21 15:33:03 -04:00
}
int netxen_init_firmware ( struct netxen_adapter * adapter )
{
u32 state = 0 , loops = 0 , err = 0 ;
/* Window 1 call */
state = readl ( NETXEN_CRB_NORMALIZE ( adapter , CRB_CMDPEG_STATE ) ) ;
if ( state = = PHAN_INITIALIZE_ACK )
return 0 ;
while ( state ! = PHAN_INITIALIZE_COMPLETE & & loops < 2000 ) {
udelay ( 100 ) ;
/* Window 1 call */
state = readl ( NETXEN_CRB_NORMALIZE ( adapter , CRB_CMDPEG_STATE ) ) ;
loops + + ;
}
if ( loops > = 2000 ) {
printk ( KERN_ERR " Cmd Peg initialization not complete:%x. \n " ,
state ) ;
err = - EIO ;
return err ;
}
/* Window 1 call */
2007-07-02 00:26:00 +05:30
writel ( INTR_SCHEME_PERPORT ,
NETXEN_CRB_NORMALIZE ( adapter , CRB_NIC_CAPABILITIES_HOST ) ) ;
2008-03-17 19:59:48 -07:00
writel ( MSI_MODE_MULTIFUNC ,
NETXEN_CRB_NORMALIZE ( adapter , CRB_NIC_MSI_MODE_HOST ) ) ;
2007-04-20 07:52:37 -07:00
writel ( MPORT_MULTI_FUNCTION_MODE ,
2006-12-04 09:23:25 -08:00
NETXEN_CRB_NORMALIZE ( adapter , CRB_MPORT_MODE ) ) ;
2006-10-21 15:33:03 -04:00
writel ( PHAN_INITIALIZE_ACK ,
NETXEN_CRB_NORMALIZE ( adapter , CRB_CMDPEG_STATE ) ) ;
return err ;
}
void netxen_initialize_adapter_sw ( struct netxen_adapter * adapter )
{
int ctxid , ring ;
u32 i ;
u32 num_rx_bufs = 0 ;
struct netxen_rcv_desc_ctx * rcv_desc ;
DPRINTK ( INFO , " initializing some queues: %p \n " , adapter ) ;
for ( ctxid = 0 ; ctxid < MAX_RCV_CTX ; + + ctxid ) {
for ( ring = 0 ; ring < NUM_RCV_DESC_RINGS ; ring + + ) {
struct netxen_rx_buffer * rx_buf ;
rcv_desc = & adapter - > recv_ctx [ ctxid ] . rcv_desc [ ring ] ;
rcv_desc - > begin_alloc = 0 ;
rx_buf = rcv_desc - > rx_buf_arr ;
num_rx_bufs = rcv_desc - > max_rx_desc_count ;
/*
* Now go through all of them , set reference handles
* and put them in the queues .
*/
for ( i = 0 ; i < num_rx_bufs ; i + + ) {
rx_buf - > ref_handle = i ;
rx_buf - > state = NETXEN_BUFFER_FREE ;
DPRINTK ( INFO , " Rx buf:ctx%d i(%d) rx_buf: "
" %p \n " , ctxid , i , rx_buf ) ;
rx_buf + + ;
}
}
}
}
void netxen_initialize_adapter_ops ( struct netxen_adapter * adapter )
{
switch ( adapter - > ahw . board_type ) {
case NETXEN_NIC_GBE :
2006-12-04 09:18:00 -08:00
adapter - > enable_phy_interrupts =
2006-10-21 15:33:03 -04:00
netxen_niu_gbe_enable_phy_interrupts ;
2006-12-04 09:18:00 -08:00
adapter - > disable_phy_interrupts =
2006-10-21 15:33:03 -04:00
netxen_niu_gbe_disable_phy_interrupts ;
2006-12-04 09:18:00 -08:00
adapter - > handle_phy_intr = netxen_nic_gbe_handle_phy_intr ;
adapter - > macaddr_set = netxen_niu_macaddr_set ;
adapter - > set_mtu = netxen_nic_set_mtu_gb ;
adapter - > set_promisc = netxen_niu_set_promiscuous_mode ;
adapter - > phy_read = netxen_niu_gbe_phy_read ;
adapter - > phy_write = netxen_niu_gbe_phy_write ;
adapter - > init_niu = netxen_nic_init_niu_gb ;
adapter - > stop_port = netxen_niu_disable_gbe_port ;
2006-10-21 15:33:03 -04:00
break ;
case NETXEN_NIC_XGBE :
2006-12-04 09:18:00 -08:00
adapter - > enable_phy_interrupts =
2006-10-21 15:33:03 -04:00
netxen_niu_xgbe_enable_phy_interrupts ;
2006-12-04 09:18:00 -08:00
adapter - > disable_phy_interrupts =
2006-10-21 15:33:03 -04:00
netxen_niu_xgbe_disable_phy_interrupts ;
2006-12-04 09:18:00 -08:00
adapter - > handle_phy_intr = netxen_nic_xgbe_handle_phy_intr ;
adapter - > macaddr_set = netxen_niu_xg_macaddr_set ;
adapter - > set_mtu = netxen_nic_set_mtu_xgb ;
adapter - > init_port = netxen_niu_xg_init_port ;
adapter - > set_promisc = netxen_niu_xg_set_promiscuous_mode ;
adapter - > stop_port = netxen_niu_disable_xg_port ;
2006-10-21 15:33:03 -04:00
break ;
default :
break ;
}
}
/*
* netxen_decode_crb_addr ( 0 - utility to translate from internal Phantom CRB
* address to external PCI CRB address .
*/
2007-11-05 18:07:31 +01:00
static u32 netxen_decode_crb_addr ( u32 addr )
2006-10-21 15:33:03 -04:00
{
int i ;
2007-02-28 05:16:40 -08:00
u32 base_addr , offset , pci_base ;
2006-10-21 15:33:03 -04:00
crb_addr_transform_setup ( ) ;
pci_base = NETXEN_ADDR_ERROR ;
base_addr = addr & 0xfff00000 ;
offset = addr & 0x000fffff ;
for ( i = 0 ; i < NETXEN_MAX_CRB_XFORM ; i + + ) {
if ( crb_addr_xform [ i ] = = base_addr ) {
pci_base = i < < 20 ;
break ;
}
}
if ( pci_base = = NETXEN_ADDR_ERROR )
return pci_base ;
else
return ( pci_base + offset ) ;
}
2007-04-20 07:53:05 -07:00
static long rom_max_timeout = 100 ;
static long rom_lock_timeout = 10000 ;
2008-07-21 19:44:00 -07:00
#if 0
2007-02-05 07:40:49 -08:00
static long rom_write_timeout = 700 ;
2008-07-21 19:44:00 -07:00
# endif
2006-10-21 15:33:03 -04:00
2007-11-05 18:07:31 +01:00
static int rom_lock ( struct netxen_adapter * adapter )
2006-10-21 15:33:03 -04:00
{
int iter ;
u32 done = 0 ;
int timeout = 0 ;
while ( ! done ) {
/* acquire semaphore2 from PCI HW block */
netxen_nic_read_w0 ( adapter , NETXEN_PCIE_REG ( PCIE_SEM2_LOCK ) ,
& done ) ;
if ( done = = 1 )
break ;
if ( timeout > = rom_lock_timeout )
return - EIO ;
timeout + + ;
/*
* Yield CPU
*/
if ( ! in_atomic ( ) )
schedule ( ) ;
else {
for ( iter = 0 ; iter < 20 ; iter + + )
cpu_relax ( ) ; /*This a nop instr on i386 */
}
}
netxen_nic_reg_write ( adapter , NETXEN_ROM_LOCK_ID , ROM_LOCK_DRIVER ) ;
return 0 ;
}
2007-11-05 18:07:31 +01:00
static int netxen_wait_rom_done ( struct netxen_adapter * adapter )
2006-10-21 15:33:03 -04:00
{
long timeout = 0 ;
long done = 0 ;
while ( done = = 0 ) {
done = netxen_nic_reg_read ( adapter , NETXEN_ROMUSB_GLB_STATUS ) ;
done & = 2 ;
timeout + + ;
if ( timeout > = rom_max_timeout ) {
printk ( " Timeout reached waiting for rom done " ) ;
return - EIO ;
}
}
return 0 ;
}
2008-07-21 19:44:00 -07:00
#if 0
2007-11-05 18:07:31 +01:00
static int netxen_rom_wren ( struct netxen_adapter * adapter )
2006-11-29 09:00:10 -08:00
{
/* Set write enable latch in ROM status register */
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_ABYTE_CNT , 0 ) ;
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_INSTR_OPCODE ,
M25P_INSTR_WREN ) ;
if ( netxen_wait_rom_done ( adapter ) ) {
return - 1 ;
}
return 0 ;
}
2007-11-05 18:07:31 +01:00
static unsigned int netxen_rdcrbreg ( struct netxen_adapter * adapter ,
unsigned int addr )
2006-11-29 09:00:10 -08:00
{
unsigned int data = 0xdeaddead ;
data = netxen_nic_reg_read ( adapter , addr ) ;
return data ;
}
2007-11-05 18:07:31 +01:00
static int netxen_do_rom_rdsr ( struct netxen_adapter * adapter )
2006-11-29 09:00:10 -08:00
{
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_INSTR_OPCODE ,
M25P_INSTR_RDSR ) ;
if ( netxen_wait_rom_done ( adapter ) ) {
return - 1 ;
}
return netxen_rdcrbreg ( adapter , NETXEN_ROMUSB_ROM_RDATA ) ;
}
2008-07-21 19:44:00 -07:00
# endif
2006-11-29 09:00:10 -08:00
2007-11-05 18:07:31 +01:00
static void netxen_rom_unlock ( struct netxen_adapter * adapter )
2006-11-29 09:00:10 -08:00
{
u32 val ;
/* release semaphore2 */
netxen_nic_read_w0 ( adapter , NETXEN_PCIE_REG ( PCIE_SEM2_UNLOCK ) , & val ) ;
}
2008-07-21 19:44:00 -07:00
#if 0
2007-11-05 18:07:31 +01:00
static int netxen_rom_wip_poll ( struct netxen_adapter * adapter )
2006-11-29 09:00:10 -08:00
{
long timeout = 0 ;
long wip = 1 ;
int val ;
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_ABYTE_CNT , 0 ) ;
while ( wip ! = 0 ) {
val = netxen_do_rom_rdsr ( adapter ) ;
wip = val & 1 ;
timeout + + ;
if ( timeout > rom_max_timeout ) {
return - 1 ;
}
}
return 0 ;
}
2007-11-05 18:07:31 +01:00
static int do_rom_fast_write ( struct netxen_adapter * adapter , int addr ,
int data )
2006-11-29 09:00:10 -08:00
{
if ( netxen_rom_wren ( adapter ) ) {
return - 1 ;
}
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_WDATA , data ) ;
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_ADDRESS , addr ) ;
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_ABYTE_CNT , 3 ) ;
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_INSTR_OPCODE ,
M25P_INSTR_PP ) ;
if ( netxen_wait_rom_done ( adapter ) ) {
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_ABYTE_CNT , 0 ) ;
return - 1 ;
}
return netxen_rom_wip_poll ( adapter ) ;
}
2008-07-21 19:44:00 -07:00
# endif
2006-11-29 09:00:10 -08:00
2007-11-05 18:07:31 +01:00
static int do_rom_fast_read ( struct netxen_adapter * adapter ,
int addr , int * valp )
2006-10-21 15:33:03 -04:00
{
2007-07-02 09:37:57 +05:30
cond_resched ( ) ;
2007-03-13 04:15:06 -08:00
2006-10-21 15:33:03 -04:00
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_ADDRESS , addr ) ;
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_ABYTE_CNT , 3 ) ;
2007-03-13 04:15:06 -08:00
udelay ( 100 ) ; /* prevent bursting on CRB */
2006-10-21 15:33:03 -04:00
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT , 0 ) ;
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_INSTR_OPCODE , 0xb ) ;
if ( netxen_wait_rom_done ( adapter ) ) {
printk ( " Error waiting for rom done \n " ) ;
return - EIO ;
}
/* reset abyte_cnt and dummy_byte_cnt */
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_ABYTE_CNT , 0 ) ;
2007-03-13 04:15:06 -08:00
udelay ( 100 ) ; /* prevent bursting on CRB */
2006-10-21 15:33:03 -04:00
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT , 0 ) ;
* valp = netxen_nic_reg_read ( adapter , NETXEN_ROMUSB_ROM_RDATA ) ;
return 0 ;
}
2007-11-05 18:07:31 +01:00
static int do_rom_fast_read_words ( struct netxen_adapter * adapter , int addr ,
u8 * bytes , size_t size )
2007-02-05 07:40:49 -08:00
{
int addridx ;
int ret = 0 ;
for ( addridx = addr ; addridx < ( addr + size ) ; addridx + = 4 ) {
2007-12-22 19:44:00 +00:00
int v ;
ret = do_rom_fast_read ( adapter , addridx , & v ) ;
2007-02-05 07:40:49 -08:00
if ( ret ! = 0 )
break ;
2007-12-22 19:44:00 +00:00
* ( __le32 * ) bytes = cpu_to_le32 ( v ) ;
2007-02-05 07:40:49 -08:00
bytes + = 4 ;
}
return ret ;
}
int
2007-11-23 21:23:36 -05:00
netxen_rom_fast_read_words ( struct netxen_adapter * adapter , int addr ,
2007-02-05 07:40:49 -08:00
u8 * bytes , size_t size )
{
int ret ;
ret = rom_lock ( adapter ) ;
if ( ret < 0 )
return ret ;
ret = do_rom_fast_read_words ( adapter , addr , bytes , size ) ;
netxen_rom_unlock ( adapter ) ;
return ret ;
}
2006-10-21 15:33:03 -04:00
int netxen_rom_fast_read ( struct netxen_adapter * adapter , int addr , int * valp )
{
int ret ;
if ( rom_lock ( adapter ) ! = 0 )
return - EIO ;
ret = do_rom_fast_read ( adapter , addr , valp ) ;
2006-11-29 09:00:10 -08:00
netxen_rom_unlock ( adapter ) ;
return ret ;
}
2007-11-05 18:07:31 +01:00
#if 0
2006-11-29 09:00:10 -08:00
int netxen_rom_fast_write ( struct netxen_adapter * adapter , int addr , int data )
{
int ret = 0 ;
if ( rom_lock ( adapter ) ! = 0 ) {
return - 1 ;
}
ret = do_rom_fast_write ( adapter , addr , data ) ;
netxen_rom_unlock ( adapter ) ;
return ret ;
}
2007-02-05 07:40:49 -08:00
2007-11-23 21:23:36 -05:00
static int do_rom_fast_write_words ( struct netxen_adapter * adapter ,
2007-11-05 18:07:31 +01:00
int addr , u8 * bytes , size_t size )
2007-02-05 07:40:49 -08:00
{
int addridx = addr ;
int ret = 0 ;
while ( addridx < ( addr + size ) ) {
int last_attempt = 0 ;
int timeout = 0 ;
int data ;
2007-12-22 19:44:00 +00:00
data = le32_to_cpu ( ( * ( __le32 * ) bytes ) ) ;
2007-02-05 07:40:49 -08:00
ret = do_rom_fast_write ( adapter , addridx , data ) ;
if ( ret < 0 )
return ret ;
2007-11-23 21:23:36 -05:00
2007-02-05 07:40:49 -08:00
while ( 1 ) {
int data1 ;
2007-02-26 14:51:56 -08:00
ret = do_rom_fast_read ( adapter , addridx , & data1 ) ;
if ( ret < 0 )
return ret ;
2007-02-05 07:40:49 -08:00
if ( data1 = = data )
break ;
if ( timeout + + > = rom_write_timeout ) {
if ( last_attempt + + < 4 ) {
2007-11-23 21:23:36 -05:00
ret = do_rom_fast_write ( adapter ,
2007-02-05 07:40:49 -08:00
addridx , data ) ;
if ( ret < 0 )
return ret ;
}
else {
printk ( KERN_INFO " Data write did not "
" succeed at address 0x%x \n " , addridx ) ;
break ;
}
}
}
bytes + = 4 ;
addridx + = 4 ;
}
return ret ;
}
2007-11-23 21:23:36 -05:00
int netxen_rom_fast_write_words ( struct netxen_adapter * adapter , int addr ,
2007-02-05 07:40:49 -08:00
u8 * bytes , size_t size )
{
int ret = 0 ;
ret = rom_lock ( adapter ) ;
if ( ret < 0 )
return ret ;
ret = do_rom_fast_write_words ( adapter , addr , bytes , size ) ;
netxen_rom_unlock ( adapter ) ;
return ret ;
}
2007-11-05 18:07:31 +01:00
static int netxen_rom_wrsr ( struct netxen_adapter * adapter , int data )
2007-02-05 07:40:49 -08:00
{
int ret ;
ret = netxen_rom_wren ( adapter ) ;
if ( ret < 0 )
return ret ;
netxen_crb_writelit_adapter ( adapter , NETXEN_ROMUSB_ROM_WDATA , data ) ;
2007-11-23 21:23:36 -05:00
netxen_crb_writelit_adapter ( adapter ,
2007-02-05 07:40:49 -08:00
NETXEN_ROMUSB_ROM_INSTR_OPCODE , 0x1 ) ;
ret = netxen_wait_rom_done ( adapter ) ;
if ( ret < 0 )
return ret ;
return netxen_rom_wip_poll ( adapter ) ;
}
2007-11-05 18:07:31 +01:00
static int netxen_rom_rdsr ( struct netxen_adapter * adapter )
2007-02-05 07:40:49 -08:00
{
int ret ;
ret = rom_lock ( adapter ) ;
if ( ret < 0 )
return ret ;
ret = netxen_do_rom_rdsr ( adapter ) ;
netxen_rom_unlock ( adapter ) ;
return ret ;
}
int netxen_backup_crbinit ( struct netxen_adapter * adapter )
{
int ret = FLASH_SUCCESS ;
int val ;
2007-06-07 04:36:36 -07:00
char * buffer = kmalloc ( NETXEN_FLASH_SECTOR_SIZE , GFP_KERNEL ) ;
2007-02-05 07:40:49 -08:00
if ( ! buffer )
2007-11-23 21:23:36 -05:00
return - ENOMEM ;
2007-02-05 07:40:49 -08:00
/* unlock sector 63 */
val = netxen_rom_rdsr ( adapter ) ;
val = val & 0xe3 ;
ret = netxen_rom_wrsr ( adapter , val ) ;
if ( ret ! = FLASH_SUCCESS )
goto out_kfree ;
ret = netxen_rom_wip_poll ( adapter ) ;
if ( ret ! = FLASH_SUCCESS )
goto out_kfree ;
/* copy sector 0 to sector 63 */
2007-11-23 21:23:36 -05:00
ret = netxen_rom_fast_read_words ( adapter , NETXEN_CRBINIT_START ,
2007-06-07 04:36:36 -07:00
buffer , NETXEN_FLASH_SECTOR_SIZE ) ;
2007-02-05 07:40:49 -08:00
if ( ret ! = FLASH_SUCCESS )
goto out_kfree ;
2007-11-23 21:23:36 -05:00
ret = netxen_rom_fast_write_words ( adapter , NETXEN_FIXED_START ,
2007-06-07 04:36:36 -07:00
buffer , NETXEN_FLASH_SECTOR_SIZE ) ;
2007-02-05 07:40:49 -08:00
if ( ret ! = FLASH_SUCCESS )
goto out_kfree ;
/* lock sector 63 */
val = netxen_rom_rdsr ( adapter ) ;
if ( ! ( val & 0x8 ) ) {
val | = ( 0x1 < < 2 ) ;
/* lock sector 63 */
if ( netxen_rom_wrsr ( adapter , val ) = = 0 ) {
ret = netxen_rom_wip_poll ( adapter ) ;
if ( ret ! = FLASH_SUCCESS )
goto out_kfree ;
/* lock SR writes */
ret = netxen_rom_wip_poll ( adapter ) ;
if ( ret ! = FLASH_SUCCESS )
goto out_kfree ;
}
}
out_kfree :
kfree ( buffer ) ;
return ret ;
}
2007-11-05 18:07:31 +01:00
static int netxen_do_rom_se ( struct netxen_adapter * adapter , int addr )
2006-11-29 09:00:10 -08:00
{
netxen_rom_wren ( adapter ) ;
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_ADDRESS , addr ) ;
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_ABYTE_CNT , 3 ) ;
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_INSTR_OPCODE ,
M25P_INSTR_SE ) ;
if ( netxen_wait_rom_done ( adapter ) ) {
netxen_nic_reg_write ( adapter , NETXEN_ROMUSB_ROM_ABYTE_CNT , 0 ) ;
return - 1 ;
}
return netxen_rom_wip_poll ( adapter ) ;
}
2007-11-05 18:07:31 +01:00
static void check_erased_flash ( struct netxen_adapter * adapter , int addr )
2007-02-05 07:40:49 -08:00
{
int i ;
int val ;
int count = 0 , erased_errors = 0 ;
int range ;
2007-11-23 21:23:36 -05:00
range = ( addr = = NETXEN_USER_START ) ?
2007-06-07 04:36:36 -07:00
NETXEN_FIXED_START : addr + NETXEN_FLASH_SECTOR_SIZE ;
2007-11-23 21:23:36 -05:00
2007-02-05 07:40:49 -08:00
for ( i = addr ; i < range ; i + = 4 ) {
netxen_rom_fast_read ( adapter , i , & val ) ;
if ( val ! = 0xffffffff )
erased_errors + + ;
count + + ;
}
if ( erased_errors )
printk ( KERN_INFO " 0x%x out of 0x%x words fail to be erased "
" for sector address: %x \n " , erased_errors , count , addr ) ;
}
2006-11-29 09:00:10 -08:00
int netxen_rom_se ( struct netxen_adapter * adapter , int addr )
{
int ret = 0 ;
if ( rom_lock ( adapter ) ! = 0 ) {
return - 1 ;
}
ret = netxen_do_rom_se ( adapter , addr ) ;
netxen_rom_unlock ( adapter ) ;
2007-02-05 07:40:49 -08:00
msleep ( 30 ) ;
check_erased_flash ( adapter , addr ) ;
return ret ;
}
2007-11-05 18:07:31 +01:00
static int netxen_flash_erase_sections ( struct netxen_adapter * adapter ,
int start , int end )
2007-02-05 07:40:49 -08:00
{
int ret = FLASH_SUCCESS ;
int i ;
for ( i = start ; i < end ; i + + ) {
2007-06-07 04:36:36 -07:00
ret = netxen_rom_se ( adapter , i * NETXEN_FLASH_SECTOR_SIZE ) ;
2007-02-05 07:40:49 -08:00
if ( ret )
break ;
ret = netxen_rom_wip_poll ( adapter ) ;
if ( ret < 0 )
return ret ;
}
return ret ;
}
int
netxen_flash_erase_secondary ( struct netxen_adapter * adapter )
{
int ret = FLASH_SUCCESS ;
int start , end ;
2007-06-07 04:36:36 -07:00
start = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE ;
end = NETXEN_USER_START / NETXEN_FLASH_SECTOR_SIZE ;
2007-02-05 07:40:49 -08:00
ret = netxen_flash_erase_sections ( adapter , start , end ) ;
return ret ;
}
int
netxen_flash_erase_primary ( struct netxen_adapter * adapter )
{
int ret = FLASH_SUCCESS ;
int start , end ;
2007-06-07 04:36:36 -07:00
start = NETXEN_PRIMARY_START / NETXEN_FLASH_SECTOR_SIZE ;
end = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE ;
2007-02-05 07:40:49 -08:00
ret = netxen_flash_erase_sections ( adapter , start , end ) ;
return ret ;
}
2007-02-09 05:49:08 -08:00
void netxen_halt_pegs ( struct netxen_adapter * adapter )
{
netxen_crb_writelit_adapter ( adapter , NETXEN_CRB_PEG_NET_0 + 0x3c , 1 ) ;
netxen_crb_writelit_adapter ( adapter , NETXEN_CRB_PEG_NET_1 + 0x3c , 1 ) ;
netxen_crb_writelit_adapter ( adapter , NETXEN_CRB_PEG_NET_2 + 0x3c , 1 ) ;
netxen_crb_writelit_adapter ( adapter , NETXEN_CRB_PEG_NET_3 + 0x3c , 1 ) ;
}
2007-02-05 07:40:49 -08:00
int netxen_flash_unlock ( struct netxen_adapter * adapter )
{
int ret = 0 ;
ret = netxen_rom_wrsr ( adapter , 0 ) ;
if ( ret < 0 )
return ret ;
ret = netxen_rom_wren ( adapter ) ;
if ( ret < 0 )
return ret ;
2006-10-21 15:33:03 -04:00
return ret ;
}
2008-07-21 19:44:00 -07:00
# endif /* 0 */
2006-10-21 15:33:03 -04:00
# define NETXEN_BOARDTYPE 0x4008
# define NETXEN_BOARDNUM 0x400c
# define NETXEN_CHIPNUM 0x4010
# define NETXEN_ROMBUS_RESET 0xFFFFFFFF
int netxen_pinit_from_rom ( struct netxen_adapter * adapter , int verbose )
{
2008-06-15 22:59:45 -07:00
int addr , val ;
2006-10-21 15:33:03 -04:00
int n , i ;
int init_delay = 0 ;
struct crb_addr_pair * buf ;
2007-02-28 05:16:40 -08:00
u32 off ;
2006-10-21 15:33:03 -04:00
/* resetall */
netxen_crb_writelit_adapter ( adapter , NETXEN_ROMUSB_GLB_SW_RESET ,
NETXEN_ROMBUS_RESET ) ;
if ( verbose ) {
if ( netxen_rom_fast_read ( adapter , NETXEN_BOARDTYPE , & val ) = = 0 )
printk ( " P2 ROM board type: 0x%08x \n " , val ) ;
else
printk ( " Could not read board type \n " ) ;
if ( netxen_rom_fast_read ( adapter , NETXEN_BOARDNUM , & val ) = = 0 )
printk ( " P2 ROM board num: 0x%08x \n " , val ) ;
else
printk ( " Could not read board number \n " ) ;
if ( netxen_rom_fast_read ( adapter , NETXEN_CHIPNUM , & val ) = = 0 )
printk ( " P2 ROM chip num: 0x%08x \n " , val ) ;
else
printk ( " Could not read chip number \n " ) ;
}
2008-07-21 19:44:00 -07:00
if ( netxen_rom_fast_read ( adapter , 0 , & n ) = = 0 & & ( n & 0x80000000 ) ) {
n & = ~ 0x80000000 ;
if ( n < 0x400 ) {
2006-10-21 15:33:03 -04:00
if ( verbose )
printk ( " %s: %d CRB init values found "
" in ROM. \n " , netxen_nic_driver_name , n ) ;
} else {
printk ( " %s:n=0x%x Error! NetXen card flash not "
" initialized. \n " , __FUNCTION__ , n ) ;
return - EIO ;
}
buf = kcalloc ( n , sizeof ( struct crb_addr_pair ) , GFP_KERNEL ) ;
if ( buf = = NULL ) {
2006-11-29 09:00:10 -08:00
printk ( " %s: netxen_pinit_from_rom: Unable to calloc "
" memory. \n " , netxen_nic_driver_name ) ;
2006-10-21 15:33:03 -04:00
return - ENOMEM ;
}
for ( i = 0 ; i < n ; i + + ) {
if ( netxen_rom_fast_read ( adapter , 8 * i + 4 , & val ) ! = 0
| | netxen_rom_fast_read ( adapter , 8 * i + 8 ,
& addr ) ! = 0 )
return - EIO ;
buf [ i ] . addr = addr ;
buf [ i ] . data = val ;
if ( verbose )
printk ( " %s: PCI: 0x%08x == 0x%08x \n " ,
netxen_nic_driver_name , ( unsigned int )
2007-02-28 05:16:40 -08:00
netxen_decode_crb_addr ( addr ) , val ) ;
2006-10-21 15:33:03 -04:00
}
for ( i = 0 ; i < n ; i + + ) {
2007-02-28 05:16:40 -08:00
off = netxen_decode_crb_addr ( buf [ i ] . addr ) ;
2007-02-05 07:35:26 -08:00
if ( off = = NETXEN_ADDR_ERROR ) {
2007-02-28 05:16:40 -08:00
printk ( KERN_ERR " CRB init value out of range %x \n " ,
2007-02-05 07:35:26 -08:00
buf [ i ] . addr ) ;
continue ;
}
off + = NETXEN_PCI_CRBSPACE ;
2006-10-21 15:33:03 -04:00
/* skipping cold reboot MAGIC */
if ( off = = NETXEN_CAM_RAM ( 0x1fc ) )
continue ;
/* After writing this register, HW needs time for CRB */
/* to quiet down (else crb_window returns 0xffffffff) */
if ( off = = NETXEN_ROMUSB_GLB_SW_RESET ) {
init_delay = 1 ;
/* hold xdma in reset also */
2006-11-29 09:00:10 -08:00
buf [ i ] . data = NETXEN_NIC_XDMA_RESET ;
2006-10-21 15:33:03 -04:00
}
2008-07-21 19:44:00 -07:00
netxen_nic_hw_write_wx ( adapter , off , & buf [ i ] . data , 4 ) ;
2006-10-21 15:33:03 -04:00
if ( init_delay = = 1 ) {
2008-06-15 22:59:46 -07:00
msleep ( 1000 ) ;
2006-10-21 15:33:03 -04:00
init_delay = 0 ;
}
2008-06-15 22:59:46 -07:00
msleep ( 1 ) ;
2006-10-21 15:33:03 -04:00
}
kfree ( buf ) ;
/* disable_peg_cache_all */
/* unreset_net_cache */
netxen_nic_hw_read_wx ( adapter , NETXEN_ROMUSB_GLB_SW_RESET , & val ,
4 ) ;
netxen_crb_writelit_adapter ( adapter , NETXEN_ROMUSB_GLB_SW_RESET ,
( val & 0xffffff0f ) ) ;
/* p2dn replyCount */
netxen_crb_writelit_adapter ( adapter ,
NETXEN_CRB_PEG_NET_D + 0xec , 0x1e ) ;
/* disable_peg_cache 0 */
netxen_crb_writelit_adapter ( adapter ,
NETXEN_CRB_PEG_NET_D + 0x4c , 8 ) ;
/* disable_peg_cache 1 */
netxen_crb_writelit_adapter ( adapter ,
NETXEN_CRB_PEG_NET_I + 0x4c , 8 ) ;
/* peg_clr_all */
/* peg_clr 0 */
netxen_crb_writelit_adapter ( adapter , NETXEN_CRB_PEG_NET_0 + 0x8 ,
0 ) ;
netxen_crb_writelit_adapter ( adapter , NETXEN_CRB_PEG_NET_0 + 0xc ,
0 ) ;
/* peg_clr 1 */
netxen_crb_writelit_adapter ( adapter , NETXEN_CRB_PEG_NET_1 + 0x8 ,
0 ) ;
netxen_crb_writelit_adapter ( adapter , NETXEN_CRB_PEG_NET_1 + 0xc ,
0 ) ;
/* peg_clr 2 */
netxen_crb_writelit_adapter ( adapter , NETXEN_CRB_PEG_NET_2 + 0x8 ,
0 ) ;
netxen_crb_writelit_adapter ( adapter , NETXEN_CRB_PEG_NET_2 + 0xc ,
0 ) ;
/* peg_clr 3 */
netxen_crb_writelit_adapter ( adapter , NETXEN_CRB_PEG_NET_3 + 0x8 ,
0 ) ;
netxen_crb_writelit_adapter ( adapter , NETXEN_CRB_PEG_NET_3 + 0xc ,
0 ) ;
}
return 0 ;
}
2006-12-04 09:23:25 -08:00
int netxen_initialize_adapter_offload ( struct netxen_adapter * adapter )
{
uint64_t addr ;
uint32_t hi ;
uint32_t lo ;
adapter - > dummy_dma . addr =
2008-07-21 19:44:00 -07:00
pci_alloc_consistent ( adapter - > pdev ,
2006-12-04 09:23:25 -08:00
NETXEN_HOST_DUMMY_DMA_SIZE ,
& adapter - > dummy_dma . phys_addr ) ;
if ( adapter - > dummy_dma . addr = = NULL ) {
printk ( " %s: ERROR: Could not allocate dummy DMA memory \n " ,
__FUNCTION__ ) ;
return - ENOMEM ;
}
addr = ( uint64_t ) adapter - > dummy_dma . phys_addr ;
hi = ( addr > > 32 ) & 0xffffffff ;
lo = addr & 0xffffffff ;
writel ( hi , NETXEN_CRB_NORMALIZE ( adapter , CRB_HOST_DUMMY_BUF_ADDR_HI ) ) ;
writel ( lo , NETXEN_CRB_NORMALIZE ( adapter , CRB_HOST_DUMMY_BUF_ADDR_LO ) ) ;
return 0 ;
}
void netxen_free_adapter_offload ( struct netxen_adapter * adapter )
{
2008-06-15 22:59:46 -07:00
int i ;
2006-12-04 09:23:25 -08:00
if ( adapter - > dummy_dma . addr ) {
2008-06-15 22:59:46 -07:00
i = 100 ;
do {
if ( dma_watchdog_shutdown_request ( adapter ) = = 1 )
break ;
msleep ( 50 ) ;
if ( dma_watchdog_shutdown_poll_result ( adapter ) = = 1 )
break ;
} while ( - - i ) ;
if ( i ) {
2008-07-21 19:44:00 -07:00
pci_free_consistent ( adapter - > pdev ,
2006-12-04 09:23:25 -08:00
NETXEN_HOST_DUMMY_DMA_SIZE ,
adapter - > dummy_dma . addr ,
adapter - > dummy_dma . phys_addr ) ;
2008-06-15 22:59:46 -07:00
adapter - > dummy_dma . addr = NULL ;
} else {
printk ( KERN_ERR " %s: dma_watchdog_shutdown failed \n " ,
adapter - > netdev - > name ) ;
}
2006-12-04 09:23:25 -08:00
}
}
2007-07-02 09:37:57 +05:30
int netxen_phantom_init ( struct netxen_adapter * adapter , int pegtune_val )
2006-10-21 15:33:03 -04:00
{
u32 val = 0 ;
2007-07-02 09:37:57 +05:30
int retries = 30 ;
2006-10-21 15:33:03 -04:00
2006-11-29 09:00:10 -08:00
if ( ! pegtune_val ) {
2007-07-02 09:37:57 +05:30
do {
val = readl ( NETXEN_CRB_NORMALIZE
2006-10-21 15:33:03 -04:00
( adapter , CRB_CMDPEG_STATE ) ) ;
2007-07-02 09:37:57 +05:30
pegtune_val = readl ( NETXEN_CRB_NORMALIZE
( adapter , NETXEN_ROMUSB_GLB_PEGTUNE_DONE ) ) ;
if ( val = = PHAN_INITIALIZE_COMPLETE | |
val = = PHAN_INITIALIZE_ACK )
return 0 ;
msleep ( 1000 ) ;
} while ( - - retries ) ;
if ( ! retries ) {
printk ( KERN_WARNING " netxen_phantom_init: init failed, "
" pegtune_val=%x \n " , pegtune_val ) ;
return - 1 ;
2006-10-21 15:33:03 -04:00
}
}
2007-07-02 09:37:57 +05:30
return 0 ;
2006-10-21 15:33:03 -04:00
}
2007-11-05 18:07:31 +01:00
static int netxen_nic_check_temp ( struct netxen_adapter * adapter )
2006-11-29 09:00:10 -08:00
{
2007-04-20 07:52:37 -07:00
struct net_device * netdev = adapter - > netdev ;
2006-11-29 09:00:10 -08:00
uint32_t temp , temp_state , temp_val ;
int rv = 0 ;
temp = readl ( NETXEN_CRB_NORMALIZE ( adapter , CRB_TEMP_STATE ) ) ;
temp_state = nx_get_temp_state ( temp ) ;
temp_val = nx_get_temp_val ( temp ) ;
if ( temp_state = = NX_TEMP_PANIC ) {
printk ( KERN_ALERT
" %s: Device temperature %d degrees C exceeds "
" maximum allowed. Hardware has been shut down. \n " ,
netxen_nic_driver_name , temp_val ) ;
2007-04-20 07:52:37 -07:00
netif_carrier_off ( netdev ) ;
netif_stop_queue ( netdev ) ;
2006-11-29 09:00:10 -08:00
rv = 1 ;
} else if ( temp_state = = NX_TEMP_WARN ) {
if ( adapter - > temp = = NX_TEMP_NORMAL ) {
printk ( KERN_ALERT
" %s: Device temperature %d degrees C "
" exceeds operating range. "
" Immediate action needed. \n " ,
netxen_nic_driver_name , temp_val ) ;
}
} else {
if ( adapter - > temp = = NX_TEMP_WARN ) {
printk ( KERN_INFO
" %s: Device temperature is now %d degrees C "
" in normal range. \n " , netxen_nic_driver_name ,
temp_val ) ;
}
}
adapter - > temp = temp_state ;
return rv ;
}
2006-12-05 19:36:26 +00:00
void netxen_watchdog_task ( struct work_struct * work )
2006-10-21 15:33:03 -04:00
{
2006-12-05 19:36:26 +00:00
struct netxen_adapter * adapter =
container_of ( work , struct netxen_adapter , watchdog_task ) ;
2006-10-21 15:33:03 -04:00
2007-04-20 07:55:26 -07:00
if ( ( adapter - > portnum = = 0 ) & & netxen_nic_check_temp ( adapter ) )
2006-11-29 09:00:10 -08:00
return ;
2007-06-11 03:30:58 -07:00
if ( adapter - > handle_phy_intr )
adapter - > handle_phy_intr ( adapter ) ;
2006-10-21 15:33:03 -04:00
mod_timer ( & adapter - > watchdog_timer , jiffies + 2 * HZ ) ;
}
/*
* netxen_process_rcv ( ) send the received packet to the protocol stack .
* and if the number of receives exceeds RX_BUFFERS_REFILL , then we
* invoke the routine to send more rx buffers to the Phantom . . .
*/
2007-11-05 18:07:31 +01:00
static void netxen_process_rcv ( struct netxen_adapter * adapter , int ctxid ,
struct status_desc * desc )
2006-10-21 15:33:03 -04:00
{
2007-04-20 07:52:37 -07:00
struct pci_dev * pdev = adapter - > pdev ;
struct net_device * netdev = adapter - > netdev ;
2007-12-31 10:08:57 -08:00
u64 sts_data = le64_to_cpu ( desc - > status_desc_data ) ;
int index = netxen_get_sts_refhandle ( sts_data ) ;
2006-10-21 15:33:03 -04:00
struct netxen_recv_context * recv_ctx = & ( adapter - > recv_ctx [ ctxid ] ) ;
struct netxen_rx_buffer * buffer ;
struct sk_buff * skb ;
2007-12-31 10:08:57 -08:00
u32 length = netxen_get_sts_totallength ( sts_data ) ;
2006-10-21 15:33:03 -04:00
u32 desc_ctx ;
struct netxen_rcv_desc_ctx * rcv_desc ;
int ret ;
2007-12-31 10:08:57 -08:00
desc_ctx = netxen_get_sts_type ( sts_data ) ;
2006-10-21 15:33:03 -04:00
if ( unlikely ( desc_ctx > = NUM_RCV_DESC_RINGS ) ) {
printk ( " %s: %s Bad Rcv descriptor ring \n " ,
netxen_nic_driver_name , netdev - > name ) ;
return ;
}
rcv_desc = & recv_ctx - > rcv_desc [ desc_ctx ] ;
2006-12-04 09:23:25 -08:00
if ( unlikely ( index > rcv_desc - > max_rx_desc_count ) ) {
DPRINTK ( ERR , " Got a buffer index:%x Max is %x \n " ,
index , rcv_desc - > max_rx_desc_count ) ;
return ;
}
2006-10-21 15:33:03 -04:00
buffer = & rcv_desc - > rx_buf_arr [ index ] ;
2006-12-04 09:23:25 -08:00
if ( desc_ctx = = RCV_DESC_LRO_CTXID ) {
buffer - > lro_current_frags + + ;
if ( netxen_get_sts_desc_lro_last_frag ( desc ) ) {
buffer - > lro_expected_frags =
netxen_get_sts_desc_lro_cnt ( desc ) ;
buffer - > lro_length = length ;
}
if ( buffer - > lro_current_frags ! = buffer - > lro_expected_frags ) {
if ( buffer - > lro_expected_frags ! = 0 ) {
2007-11-19 17:48:24 -08:00
printk ( " LRO: (refhandle:%x) recv frag. "
" wait for last. flags: %x expected:%d "
2006-12-04 09:23:25 -08:00
" have:%d \n " , index ,
netxen_get_sts_desc_lro_last_frag ( desc ) ,
buffer - > lro_expected_frags ,
buffer - > lro_current_frags ) ;
}
return ;
}
}
2006-10-21 15:33:03 -04:00
pci_unmap_single ( pdev , buffer - > dma , rcv_desc - > dma_size ,
PCI_DMA_FROMDEVICE ) ;
skb = ( struct sk_buff * ) buffer - > skb ;
2007-09-03 10:33:35 +05:30
if ( likely ( adapter - > rx_csum & &
2008-03-17 19:59:51 -07:00
netxen_get_sts_status ( sts_data ) = = STATUS_CKSUM_OK ) ) {
2007-04-20 07:52:37 -07:00
adapter - > stats . csummed + + ;
2006-10-21 15:33:03 -04:00
skb - > ip_summed = CHECKSUM_UNNECESSARY ;
2007-09-03 10:33:35 +05:30
} else
skb - > ip_summed = CHECKSUM_NONE ;
2007-07-02 09:37:57 +05:30
skb - > dev = netdev ;
2006-12-04 09:23:25 -08:00
if ( desc_ctx = = RCV_DESC_LRO_CTXID ) {
/* True length was only available on the last pkt */
skb_put ( skb , buffer - > lro_length ) ;
} else {
skb_put ( skb , length ) ;
}
2006-10-21 15:33:03 -04:00
skb - > protocol = eth_type_trans ( skb , netdev ) ;
ret = netif_receive_skb ( skb ) ;
netdev - > last_rx = jiffies ;
/*
* We just consumed one buffer so post a buffer .
*/
buffer - > skb = NULL ;
buffer - > state = NETXEN_BUFFER_FREE ;
2006-12-04 09:23:25 -08:00
buffer - > lro_current_frags = 0 ;
buffer - > lro_expected_frags = 0 ;
2006-10-21 15:33:03 -04:00
2007-04-20 07:52:37 -07:00
adapter - > stats . no_rcv + + ;
adapter - > stats . rxbytes + = length ;
2006-10-21 15:33:03 -04:00
}
/* Process Receive status ring */
u32 netxen_process_rcv_ring ( struct netxen_adapter * adapter , int ctxid , int max )
{
struct netxen_recv_context * recv_ctx = & ( adapter - > recv_ctx [ ctxid ] ) ;
struct status_desc * desc_head = recv_ctx - > rcv_status_desc_head ;
struct status_desc * desc ; /* used to read status desc here */
u32 consumer = recv_ctx - > status_rx_consumer ;
int count = 0 , ring ;
while ( count < max ) {
desc = & desc_head [ consumer ] ;
2007-01-02 10:39:10 +00:00
if ( ! ( netxen_get_sts_owner ( desc ) & STATUS_OWNER_HOST ) ) {
2006-12-04 09:23:25 -08:00
DPRINTK ( ERR , " desc %p ownedby %x \n " , desc ,
netxen_get_sts_owner ( desc ) ) ;
2006-10-21 15:33:03 -04:00
break ;
}
netxen_process_rcv ( adapter , ctxid , desc ) ;
2007-01-02 10:39:10 +00:00
netxen_set_sts_owner ( desc , STATUS_OWNER_PHANTOM ) ;
2006-10-21 15:33:03 -04:00
consumer = ( consumer + 1 ) & ( adapter - > max_rx_desc_count - 1 ) ;
count + + ;
}
2008-03-25 23:53:24 -04:00
for ( ring = 0 ; ring < NUM_RCV_DESC_RINGS ; ring + + )
2008-03-17 19:59:49 -07:00
netxen_post_rx_buffers_nodb ( adapter , ctxid , ring ) ;
2006-10-21 15:33:03 -04:00
/* update the consumer index in phantom */
if ( count ) {
recv_ctx - > status_rx_consumer = consumer ;
/* Window = 1 */
2008-07-21 19:44:00 -07:00
writel ( consumer , NETXEN_CRB_NORMALIZE ( adapter ,
recv_ctx - > crb_sts_consumer ) ) ;
2006-10-21 15:33:03 -04:00
}
return count ;
}
/* Process Command status ring */
2008-03-17 19:59:49 -07:00
int netxen_process_cmd_ring ( struct netxen_adapter * adapter )
2006-10-21 15:33:03 -04:00
{
2008-03-17 19:59:50 -07:00
u32 last_consumer , consumer ;
int count = 0 , i ;
2006-10-21 15:33:03 -04:00
struct netxen_cmd_buffer * buffer ;
2008-03-17 19:59:50 -07:00
struct pci_dev * pdev = adapter - > pdev ;
struct net_device * netdev = adapter - > netdev ;
2006-10-21 15:33:03 -04:00
struct netxen_skb_frag * frag ;
2008-03-17 19:59:50 -07:00
int done = 0 ;
2006-10-21 15:33:03 -04:00
last_consumer = adapter - > last_cmd_consumer ;
2007-02-09 05:45:18 -08:00
consumer = le32_to_cpu ( * ( adapter - > cmd_consumer ) ) ;
2006-10-21 15:33:03 -04:00
2008-03-17 19:59:50 -07:00
while ( last_consumer ! = consumer ) {
2006-10-21 15:33:03 -04:00
buffer = & adapter - > cmd_buf_arr [ last_consumer ] ;
2007-12-26 10:23:58 -08:00
if ( buffer - > skb ) {
frag = & buffer - > frag_array [ 0 ] ;
2006-10-21 15:33:03 -04:00
pci_unmap_single ( pdev , frag - > dma , frag - > length ,
PCI_DMA_TODEVICE ) ;
2007-07-02 09:37:57 +05:30
frag - > dma = 0ULL ;
2006-10-21 15:33:03 -04:00
for ( i = 1 ; i < buffer - > frag_count ; i + + ) {
frag + + ; /* Get the next frag */
pci_unmap_page ( pdev , frag - > dma , frag - > length ,
PCI_DMA_TODEVICE ) ;
2007-07-02 09:37:57 +05:30
frag - > dma = 0ULL ;
2006-10-21 15:33:03 -04:00
}
2008-03-17 19:59:50 -07:00
adapter - > stats . xmitfinished + + ;
2007-12-26 10:23:58 -08:00
dev_kfree_skb_any ( buffer - > skb ) ;
buffer - > skb = NULL ;
2006-10-21 15:33:03 -04:00
}
last_consumer = get_next_index ( last_consumer ,
adapter - > max_tx_desc_count ) ;
2008-03-17 19:59:50 -07:00
if ( + + count > = MAX_STATUS_HANDLE )
break ;
2006-10-21 15:33:03 -04:00
}
2008-03-17 19:59:50 -07:00
if ( count ) {
2006-10-21 15:33:03 -04:00
adapter - > last_cmd_consumer = last_consumer ;
2008-03-17 19:59:50 -07:00
smp_mb ( ) ;
if ( netif_queue_stopped ( netdev ) & & netif_running ( netdev ) ) {
netif_tx_lock ( netdev ) ;
netif_wake_queue ( netdev ) ;
smp_mb ( ) ;
netif_tx_unlock ( netdev ) ;
2006-10-21 15:33:03 -04:00
}
}
2006-12-04 09:23:25 -08:00
/*
* If everything is freed up to consumer then check if the ring is full
* If the ring is full then check if more needs to be freed and
* schedule the call back again .
*
* This happens when there are 2 CPUs . One could be freeing and the
* other filling it . If the ring is full when we get out of here and
* the card has already interrupted the host then the host can miss the
* interrupt .
*
* There is still a possible race condition and the host could miss an
* interrupt . The card has to take care of this .
*/
2008-03-17 19:59:50 -07:00
consumer = le32_to_cpu ( * ( adapter - > cmd_consumer ) ) ;
done = ( last_consumer = = consumer ) ;
2006-10-21 15:33:03 -04:00
2006-12-04 09:23:25 -08:00
return ( done ) ;
2006-10-21 15:33:03 -04:00
}
/*
* netxen_post_rx_buffers puts buffer in the Phantom memory
*/
void netxen_post_rx_buffers ( struct netxen_adapter * adapter , u32 ctx , u32 ringid )
{
2008-07-21 19:44:00 -07:00
struct pci_dev * pdev = adapter - > pdev ;
2006-10-21 15:33:03 -04:00
struct sk_buff * skb ;
struct netxen_recv_context * recv_ctx = & ( adapter - > recv_ctx [ ctx ] ) ;
struct netxen_rcv_desc_ctx * rcv_desc = NULL ;
2006-12-04 09:23:25 -08:00
uint producer ;
2006-10-21 15:33:03 -04:00
struct rcv_desc * pdesc ;
struct netxen_rx_buffer * buffer ;
int count = 0 ;
int index = 0 ;
2006-12-04 09:23:25 -08:00
netxen_ctx_msg msg = 0 ;
dma_addr_t dma ;
2006-10-21 15:33:03 -04:00
rcv_desc = & recv_ctx - > rcv_desc [ ringid ] ;
producer = rcv_desc - > producer ;
index = rcv_desc - > begin_alloc ;
buffer = & rcv_desc - > rx_buf_arr [ index ] ;
/* We can start writing rx descriptors into the phantom memory. */
while ( buffer - > state = = NETXEN_BUFFER_FREE ) {
skb = dev_alloc_skb ( rcv_desc - > skb_size ) ;
if ( unlikely ( ! skb ) ) {
/*
2006-12-04 09:23:25 -08:00
* TODO
2006-10-21 15:33:03 -04:00
* We need to schedule the posting of buffers to the pegs .
*/
rcv_desc - > begin_alloc = index ;
2006-11-29 09:00:10 -08:00
DPRINTK ( ERR , " netxen_post_rx_buffers: "
2006-10-21 15:33:03 -04:00
" allocated only %d buffers \n " , count ) ;
break ;
}
2006-12-04 09:23:25 -08:00
count + + ; /* now there should be no failure */
pdesc = & rcv_desc - > desc_head [ producer ] ;
# if defined(XGB_DEBUG)
* ( unsigned long * ) ( skb - > head ) = 0xc0debabe ;
if ( skb_is_nonlinear ( skb ) ) {
printk ( " Allocated SKB @%p is nonlinear \n " ) ;
}
# endif
skb_reserve ( skb , 2 ) ;
/* This will be setup when we receive the
* buffer after it has been filled FSL TBD TBD
* skb - > dev = netdev ;
*/
dma = pci_map_single ( pdev , skb - > data , rcv_desc - > dma_size ,
PCI_DMA_FROMDEVICE ) ;
2006-12-18 05:53:59 -08:00
pdesc - > addr_buffer = cpu_to_le64 ( dma ) ;
2006-12-04 09:23:25 -08:00
buffer - > skb = skb ;
buffer - > state = NETXEN_BUFFER_BUSY ;
buffer - > dma = dma ;
/* make a rcv descriptor */
2006-12-18 05:53:59 -08:00
pdesc - > reference_handle = cpu_to_le16 ( buffer - > ref_handle ) ;
pdesc - > buffer_length = cpu_to_le32 ( rcv_desc - > dma_size ) ;
2006-12-04 09:23:25 -08:00
DPRINTK ( INFO , " done writing descripter \n " ) ;
producer =
get_next_index ( producer , rcv_desc - > max_rx_desc_count ) ;
index = get_next_index ( index , rcv_desc - > max_rx_desc_count ) ;
buffer = & rcv_desc - > rx_buf_arr [ index ] ;
}
/* if we did allocate buffers, then write the count to Phantom */
if ( count ) {
rcv_desc - > begin_alloc = index ;
rcv_desc - > producer = producer ;
/* Window = 1 */
2008-07-21 19:44:00 -07:00
writel ( ( producer - 1 ) & ( rcv_desc - > max_rx_desc_count - 1 ) ,
NETXEN_CRB_NORMALIZE ( adapter ,
rcv_desc - > crb_rcv_producer ) ) ;
2006-12-04 09:23:25 -08:00
/*
* Write a doorbell msg to tell phanmon of change in
* receive ring producer
*/
netxen_set_msg_peg_id ( msg , NETXEN_RCV_PEG_DB_ID ) ;
netxen_set_msg_privid ( msg ) ;
netxen_set_msg_count ( msg ,
( ( producer -
1 ) & ( rcv_desc - >
max_rx_desc_count - 1 ) ) ) ;
2007-04-20 07:52:37 -07:00
netxen_set_msg_ctxid ( msg , adapter - > portnum ) ;
2006-12-04 09:23:25 -08:00
netxen_set_msg_opcode ( msg , NETXEN_RCV_PRODUCER ( ringid ) ) ;
writel ( msg ,
DB_NORMALIZE ( adapter ,
NETXEN_RCV_PRODUCER_OFFSET ) ) ;
}
}
2007-11-05 18:07:31 +01:00
static void netxen_post_rx_buffers_nodb ( struct netxen_adapter * adapter ,
uint32_t ctx , uint32_t ringid )
2006-12-04 09:23:25 -08:00
{
2008-07-21 19:44:00 -07:00
struct pci_dev * pdev = adapter - > pdev ;
2006-12-04 09:23:25 -08:00
struct sk_buff * skb ;
struct netxen_recv_context * recv_ctx = & ( adapter - > recv_ctx [ ctx ] ) ;
struct netxen_rcv_desc_ctx * rcv_desc = NULL ;
u32 producer ;
struct rcv_desc * pdesc ;
struct netxen_rx_buffer * buffer ;
int count = 0 ;
int index = 0 ;
rcv_desc = & recv_ctx - > rcv_desc [ ringid ] ;
producer = rcv_desc - > producer ;
index = rcv_desc - > begin_alloc ;
buffer = & rcv_desc - > rx_buf_arr [ index ] ;
/* We can start writing rx descriptors into the phantom memory. */
while ( buffer - > state = = NETXEN_BUFFER_FREE ) {
skb = dev_alloc_skb ( rcv_desc - > skb_size ) ;
if ( unlikely ( ! skb ) ) {
/*
* We need to schedule the posting of buffers to the pegs .
*/
rcv_desc - > begin_alloc = index ;
DPRINTK ( ERR , " netxen_post_rx_buffers_nodb: "
" allocated only %d buffers \n " , count ) ;
break ;
}
2006-10-21 15:33:03 -04:00
count + + ; /* now there should be no failure */
pdesc = & rcv_desc - > desc_head [ producer ] ;
2006-12-04 09:23:25 -08:00
skb_reserve ( skb , 2 ) ;
2007-11-23 21:23:36 -05:00
/*
2006-10-21 15:33:03 -04:00
* This will be setup when we receive the
* buffer after it has been filled
* skb - > dev = netdev ;
*/
buffer - > skb = skb ;
buffer - > state = NETXEN_BUFFER_BUSY ;
buffer - > dma = pci_map_single ( pdev , skb - > data ,
rcv_desc - > dma_size ,
PCI_DMA_FROMDEVICE ) ;
2006-12-04 09:23:25 -08:00
2006-10-21 15:33:03 -04:00
/* make a rcv descriptor */
2006-12-18 05:53:59 -08:00
pdesc - > reference_handle = cpu_to_le16 ( buffer - > ref_handle ) ;
2007-01-02 10:39:10 +00:00
pdesc - > buffer_length = cpu_to_le32 ( rcv_desc - > dma_size ) ;
2006-10-21 15:33:03 -04:00
pdesc - > addr_buffer = cpu_to_le64 ( buffer - > dma ) ;
producer =
get_next_index ( producer , rcv_desc - > max_rx_desc_count ) ;
index = get_next_index ( index , rcv_desc - > max_rx_desc_count ) ;
buffer = & rcv_desc - > rx_buf_arr [ index ] ;
}
/* if we did allocate buffers, then write the count to Phantom */
if ( count ) {
rcv_desc - > begin_alloc = index ;
rcv_desc - > producer = producer ;
/* Window = 1 */
2008-07-21 19:44:00 -07:00
writel ( ( producer - 1 ) & ( rcv_desc - > max_rx_desc_count - 1 ) ,
NETXEN_CRB_NORMALIZE ( adapter ,
rcv_desc - > crb_rcv_producer ) ) ;
2006-10-21 15:33:03 -04:00
wmb ( ) ;
}
}
void netxen_nic_clear_stats ( struct netxen_adapter * adapter )
{
memset ( & adapter - > stats , 0 , sizeof ( adapter - > stats ) ) ;
2007-04-20 07:52:37 -07:00
return ;
2006-10-21 15:33:03 -04:00
}