diff options
| author | Jeff Garzik <jgarzik@pobox.com> | 2005-08-29 19:24:43 -0400 | 
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-08-29 19:24:43 -0400 | 
| commit | 76b2bf9b4dee2fb32ef17f5c84a99ce481a14be2 (patch) | |
| tree | 49cd36d6e980044c2a88f2c14cdc9259e0f0f1b4 /drivers/net/s2io.c | |
| parent | 2fca877b68b2b4fc5b94277858a1bedd46017cde (diff) | |
| parent | 8f3d17fb7bcb7c255197d11469fb5e9695c9d2f4 (diff) | |
Merge libata branch 'chs-support' to latest upstream kernel.
Diffstat (limited to 'drivers/net/s2io.c')
| -rw-r--r-- | drivers/net/s2io.c | 3085 | 
1 files changed, 1895 insertions, 1190 deletions
| diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index ea638b162d3..7ca78228b10 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -11,29 +11,28 @@   * See the file COPYING in this distribution for more information.   *   * Credits: - * Jeff Garzik		: For pointing out the improper error condition  - *			  check in the s2io_xmit routine and also some  - * 			  issues in the Tx watch dog function. Also for - *			  patiently answering all those innumerable  + * Jeff Garzik		: For pointing out the improper error condition + *			  check in the s2io_xmit routine and also some + *			  issues in the Tx watch dog function. Also for + *			  patiently answering all those innumerable   *			  questions regaring the 2.6 porting issues.   * Stephen Hemminger	: Providing proper 2.6 porting mechanism for some   *			  macros available only in 2.6 Kernel. - * Francois Romieu	: For pointing out all code part that were  + * Francois Romieu	: For pointing out all code part that were   *			  deprecated and also styling related comments. - * Grant Grundler	: For helping me get rid of some Architecture  + * Grant Grundler	: For helping me get rid of some Architecture   *			  dependent code.   * Christopher Hellwig	: Some more 2.6 specific issues in the driver. - *			  	 + *   * The module loadable parameters that are supported by the driver and a brief   * explaination of all the variables. - * rx_ring_num : This can be used to program the number of receive rings used  - * in the driver.  					 - * rx_ring_len: This defines the number of descriptors each ring can have. This  + * rx_ring_num : This can be used to program the number of receive rings used + * in the driver. + * rx_ring_len: This defines the number of descriptors each ring can have. This   * is also an array of size 8.   * tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver. - * tx_fifo_len: This too is an array of 8. Each element defines the number of  + * tx_fifo_len: This too is an array of 8. Each element defines the number of   * Tx descriptors that can be associated with each corresponding FIFO. - * in PCI Configuration space.   ************************************************************************/  #include <linux/config.h> @@ -56,27 +55,39 @@  #include <linux/ethtool.h>  #include <linux/version.h>  #include <linux/workqueue.h> +#include <linux/if_vlan.h> -#include <asm/io.h>  #include <asm/system.h>  #include <asm/uaccess.h> +#include <asm/io.h>  /* local include */  #include "s2io.h"  #include "s2io-regs.h"  /* S2io Driver name & version. */ -static char s2io_driver_name[] = "s2io"; -static char s2io_driver_version[] = "Version 1.7.7.1"; +static char s2io_driver_name[] = "Neterion"; +static char s2io_driver_version[] = "Version 2.0.3.1"; + +static inline int RXD_IS_UP2DT(RxD_t *rxdp) +{ +	int ret; + +	ret = ((!(rxdp->Control_1 & RXD_OWN_XENA)) && +		(GET_RXD_MARKER(rxdp->Control_2) != THE_RXD_MARK)); -/*  +	return ret; +} + +/*   * Cards with following subsystem_id have a link state indication   * problem, 600B, 600C, 600D, 640B, 640C and 640D.   * macro below identifies these cards given the subsystem_id.   */ -#define CARDS_WITH_FAULTY_LINK_INDICATORS(subid) \ -		(((subid >= 0x600B) && (subid <= 0x600D)) || \ -		 ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0 +#define CARDS_WITH_FAULTY_LINK_INDICATORS(dev_type, subid) \ +	(dev_type == XFRAME_I_DEVICE) ?			\ +		((((subid >= 0x600B) && (subid <= 0x600D)) || \ +		 ((subid >= 0x640B) && (subid <= 0x640D))) ? 1 : 0) : 0  #define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \  				      ADAPTER_STATUS_RMAC_LOCAL_FAULT))) @@ -86,9 +97,12 @@ static char s2io_driver_version[] = "Version 1.7.7.1";  static inline int rx_buffer_level(nic_t * sp, int rxb_size, int ring)  {  	int level = 0; -	if ((sp->pkt_cnt[ring] - rxb_size) > 16) { +	mac_info_t *mac_control; + +	mac_control = &sp->mac_control; +	if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) {  		level = LOW; -		if ((sp->pkt_cnt[ring] - rxb_size) < MAX_RXDS_PER_BLOCK) { +		if (rxb_size <= MAX_RXDS_PER_BLOCK) {  			level = PANIC;  		}  	} @@ -145,6 +159,9 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {  	{"rmac_pause_cnt"},  	{"rmac_accepted_ip"},  	{"rmac_err_tcp"}, +	{"\n DRIVER STATISTICS"}, +	{"single_bit_ecc_errs"}, +	{"double_bit_ecc_errs"},  };  #define S2IO_STAT_LEN sizeof(ethtool_stats_keys)/ ETH_GSTRING_LEN @@ -153,8 +170,37 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {  #define S2IO_TEST_LEN	sizeof(s2io_gstrings) / ETH_GSTRING_LEN  #define S2IO_STRINGS_LEN	S2IO_TEST_LEN * ETH_GSTRING_LEN +#define S2IO_TIMER_CONF(timer, handle, arg, exp)		\ +			init_timer(&timer);			\ +			timer.function = handle;		\ +			timer.data = (unsigned long) arg;	\ +			mod_timer(&timer, (jiffies + exp))	\ + +/* Add the vlan */ +static void s2io_vlan_rx_register(struct net_device *dev, +					struct vlan_group *grp) +{ +	nic_t *nic = dev->priv; +	unsigned long flags; + +	spin_lock_irqsave(&nic->tx_lock, flags); +	nic->vlgrp = grp; +	spin_unlock_irqrestore(&nic->tx_lock, flags); +} + +/* Unregister the vlan */ +static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid) +{ +	nic_t *nic = dev->priv; +	unsigned long flags; + +	spin_lock_irqsave(&nic->tx_lock, flags); +	if (nic->vlgrp) +		nic->vlgrp->vlan_devices[vid] = NULL; +	spin_unlock_irqrestore(&nic->tx_lock, flags); +} -/*  +/*   * Constants to be programmed into the Xena's registers, to configure   * the XAUI.   */ @@ -162,7 +208,28 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {  #define SWITCH_SIGN	0xA5A5A5A5A5A5A5A5ULL  #define	END_SIGN	0x0 -static u64 default_mdio_cfg[] = { +static u64 herc_act_dtx_cfg[] = { +	/* Set address */ +	0x8000051536750000ULL, 0x80000515367500E0ULL, +	/* Write data */ +	0x8000051536750004ULL, 0x80000515367500E4ULL, +	/* Set address */ +	0x80010515003F0000ULL, 0x80010515003F00E0ULL, +	/* Write data */ +	0x80010515003F0004ULL, 0x80010515003F00E4ULL, +	/* Set address */ +	0x801205150D440000ULL, 0x801205150D4400E0ULL, +	/* Write data */ +	0x801205150D440004ULL, 0x801205150D4400E4ULL, +	/* Set address */ +	0x80020515F2100000ULL, 0x80020515F21000E0ULL, +	/* Write data */ +	0x80020515F2100004ULL, 0x80020515F21000E4ULL, +	/* Done */ +	END_SIGN +}; + +static u64 xena_mdio_cfg[] = {  	/* Reset PMA PLL */  	0xC001010000000000ULL, 0xC0010100000000E0ULL,  	0xC0010100008000E4ULL, @@ -172,7 +239,7 @@ static u64 default_mdio_cfg[] = {  	END_SIGN  }; -static u64 default_dtx_cfg[] = { +static u64 xena_dtx_cfg[] = {  	0x8000051500000000ULL, 0x80000515000000E0ULL,  	0x80000515D93500E4ULL, 0x8001051500000000ULL,  	0x80010515000000E0ULL, 0x80010515001E00E4ULL, @@ -196,8 +263,7 @@ static u64 default_dtx_cfg[] = {  	END_SIGN  }; - -/*  +/*   * Constants for Fixing the MacAddress problem seen mostly on   * Alpha machines.   */ @@ -226,20 +292,25 @@ static unsigned int tx_fifo_len[MAX_TX_FIFOS] =  static unsigned int rx_ring_num = 1;  static unsigned int rx_ring_sz[MAX_RX_RINGS] =      {[0 ...(MAX_RX_RINGS - 1)] = 0 }; -static unsigned int Stats_refresh_time = 4; +static unsigned int rts_frm_len[MAX_RX_RINGS] = +    {[0 ...(MAX_RX_RINGS - 1)] = 0 }; +static unsigned int use_continuous_tx_intrs = 1;  static unsigned int rmac_pause_time = 65535;  static unsigned int mc_pause_threshold_q0q3 = 187;  static unsigned int mc_pause_threshold_q4q7 = 187;  static unsigned int shared_splits;  static unsigned int tmac_util_period = 5;  static unsigned int rmac_util_period = 5; +static unsigned int bimodal = 0;  #ifndef CONFIG_S2IO_NAPI  static unsigned int indicate_max_pkts;  #endif +/* Frequency of Rx desc syncs expressed as power of 2 */ +static unsigned int rxsync_frequency = 3; -/*  +/*   * S2IO device table. - * This table lists all the devices that this driver supports.  + * This table lists all the devices that this driver supports.   */  static struct pci_device_id s2io_tbl[] __devinitdata = {  	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_WIN, @@ -247,9 +318,9 @@ static struct pci_device_id s2io_tbl[] __devinitdata = {  	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI,  	 PCI_ANY_ID, PCI_ANY_ID},  	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_WIN, -	 PCI_ANY_ID, PCI_ANY_ID}, -	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_UNI, -	 PCI_ANY_ID, PCI_ANY_ID}, +         PCI_ANY_ID, PCI_ANY_ID}, +        {PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_HERC_UNI, +         PCI_ANY_ID, PCI_ANY_ID},  	{0,}  }; @@ -268,8 +339,8 @@ static struct pci_driver s2io_driver = {  /**   * init_shared_mem - Allocation and Initialization of Memory   * @nic: Device private variable. - * Description: The function allocates all the memory areas shared  - * between the NIC and the driver. This includes Tx descriptors,  + * Description: The function allocates all the memory areas shared + * between the NIC and the driver. This includes Tx descriptors,   * Rx descriptors and the statistics block.   */ @@ -279,11 +350,11 @@ static int init_shared_mem(struct s2io_nic *nic)  	void *tmp_v_addr, *tmp_v_addr_next;  	dma_addr_t tmp_p_addr, tmp_p_addr_next;  	RxD_block_t *pre_rxd_blk = NULL; -	int i, j, blk_cnt; +	int i, j, blk_cnt, rx_sz, tx_sz;  	int lst_size, lst_per_page;  	struct net_device *dev = nic->dev;  #ifdef CONFIG_2BUFF_MODE -	unsigned long tmp; +	u64 tmp;  	buffAdd_t *ba;  #endif @@ -300,36 +371,41 @@ static int init_shared_mem(struct s2io_nic *nic)  		size += config->tx_cfg[i].fifo_len;  	}  	if (size > MAX_AVAILABLE_TXDS) { -		DBG_PRINT(ERR_DBG, "%s: Total number of Tx FIFOs ", -			  dev->name); -		DBG_PRINT(ERR_DBG, "exceeds the maximum value "); -		DBG_PRINT(ERR_DBG, "that can be used\n"); +		DBG_PRINT(ERR_DBG, "%s: Requested TxDs too high, ", +			  __FUNCTION__); +		DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size);  		return FAILURE;  	}  	lst_size = (sizeof(TxD_t) * config->max_txds); +	tx_sz = lst_size * size;  	lst_per_page = PAGE_SIZE / lst_size;  	for (i = 0; i < config->tx_fifo_num; i++) {  		int fifo_len = config->tx_cfg[i].fifo_len;  		int list_holder_size = fifo_len * sizeof(list_info_hold_t); -		nic->list_info[i] = kmalloc(list_holder_size, GFP_KERNEL); -		if (!nic->list_info[i]) { +		mac_control->fifos[i].list_info = kmalloc(list_holder_size, +							  GFP_KERNEL); +		if (!mac_control->fifos[i].list_info) {  			DBG_PRINT(ERR_DBG,  				  "Malloc failed for list_info\n");  			return -ENOMEM;  		} -		memset(nic->list_info[i], 0, list_holder_size); +		memset(mac_control->fifos[i].list_info, 0, list_holder_size);  	}  	for (i = 0; i < config->tx_fifo_num; i++) {  		int page_num = TXD_MEM_PAGE_CNT(config->tx_cfg[i].fifo_len,  						lst_per_page); -		mac_control->tx_curr_put_info[i].offset = 0; -		mac_control->tx_curr_put_info[i].fifo_len = +		mac_control->fifos[i].tx_curr_put_info.offset = 0; +		mac_control->fifos[i].tx_curr_put_info.fifo_len =  		    config->tx_cfg[i].fifo_len - 1; -		mac_control->tx_curr_get_info[i].offset = 0; -		mac_control->tx_curr_get_info[i].fifo_len = +		mac_control->fifos[i].tx_curr_get_info.offset = 0; +		mac_control->fifos[i].tx_curr_get_info.fifo_len =  		    config->tx_cfg[i].fifo_len - 1; +		mac_control->fifos[i].fifo_no = i; +		mac_control->fifos[i].nic = nic; +		mac_control->fifos[i].max_txds = MAX_SKB_FRAGS; +  		for (j = 0; j < page_num; j++) {  			int k = 0;  			dma_addr_t tmp_p; @@ -345,16 +421,15 @@ static int init_shared_mem(struct s2io_nic *nic)  			while (k < lst_per_page) {  				int l = (j * lst_per_page) + k;  				if (l == config->tx_cfg[i].fifo_len) -					goto end_txd_alloc; -				nic->list_info[i][l].list_virt_addr = +					break; +				mac_control->fifos[i].list_info[l].list_virt_addr =  				    tmp_v + (k * lst_size); -				nic->list_info[i][l].list_phy_addr = +				mac_control->fifos[i].list_info[l].list_phy_addr =  				    tmp_p + (k * lst_size);  				k++;  			}  		}  	} -      end_txd_alloc:  	/* Allocation and initialization of RXDs in Rings */  	size = 0; @@ -367,21 +442,26 @@ static int init_shared_mem(struct s2io_nic *nic)  			return FAILURE;  		}  		size += config->rx_cfg[i].num_rxd; -		nic->block_count[i] = +		mac_control->rings[i].block_count =  		    config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1); -		nic->pkt_cnt[i] = -		    config->rx_cfg[i].num_rxd - nic->block_count[i]; +		mac_control->rings[i].pkt_cnt = +		    config->rx_cfg[i].num_rxd - mac_control->rings[i].block_count;  	} +	size = (size * (sizeof(RxD_t))); +	rx_sz = size;  	for (i = 0; i < config->rx_ring_num; i++) { -		mac_control->rx_curr_get_info[i].block_index = 0; -		mac_control->rx_curr_get_info[i].offset = 0; -		mac_control->rx_curr_get_info[i].ring_len = +		mac_control->rings[i].rx_curr_get_info.block_index = 0; +		mac_control->rings[i].rx_curr_get_info.offset = 0; +		mac_control->rings[i].rx_curr_get_info.ring_len =  		    config->rx_cfg[i].num_rxd - 1; -		mac_control->rx_curr_put_info[i].block_index = 0; -		mac_control->rx_curr_put_info[i].offset = 0; -		mac_control->rx_curr_put_info[i].ring_len = +		mac_control->rings[i].rx_curr_put_info.block_index = 0; +		mac_control->rings[i].rx_curr_put_info.offset = 0; +		mac_control->rings[i].rx_curr_put_info.ring_len =  		    config->rx_cfg[i].num_rxd - 1; +		mac_control->rings[i].nic = nic; +		mac_control->rings[i].ring_no = i; +  		blk_cnt =  		    config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1);  		/*  Allocating all the Rx blocks */ @@ -395,32 +475,36 @@ static int init_shared_mem(struct s2io_nic *nic)  							  &tmp_p_addr);  			if (tmp_v_addr == NULL) {  				/* -				 * In case of failure, free_shared_mem()  -				 * is called, which should free any  -				 * memory that was alloced till the  +				 * In case of failure, free_shared_mem() +				 * is called, which should free any +				 * memory that was alloced till the  				 * failure happened.  				 */ -				nic->rx_blocks[i][j].block_virt_addr = +				mac_control->rings[i].rx_blocks[j].block_virt_addr =  				    tmp_v_addr;  				return -ENOMEM;  			}  			memset(tmp_v_addr, 0, size); -			nic->rx_blocks[i][j].block_virt_addr = tmp_v_addr; -			nic->rx_blocks[i][j].block_dma_addr = tmp_p_addr; +			mac_control->rings[i].rx_blocks[j].block_virt_addr = +				tmp_v_addr; +			mac_control->rings[i].rx_blocks[j].block_dma_addr = +				tmp_p_addr;  		}  		/* Interlinking all Rx Blocks */  		for (j = 0; j < blk_cnt; j++) { -			tmp_v_addr = nic->rx_blocks[i][j].block_virt_addr; +			tmp_v_addr = +				mac_control->rings[i].rx_blocks[j].block_virt_addr;  			tmp_v_addr_next = -			    nic->rx_blocks[i][(j + 1) % +				mac_control->rings[i].rx_blocks[(j + 1) %  					      blk_cnt].block_virt_addr; -			tmp_p_addr = nic->rx_blocks[i][j].block_dma_addr; +			tmp_p_addr = +				mac_control->rings[i].rx_blocks[j].block_dma_addr;  			tmp_p_addr_next = -			    nic->rx_blocks[i][(j + 1) % +				mac_control->rings[i].rx_blocks[(j + 1) %  					      blk_cnt].block_dma_addr;  			pre_rxd_blk = (RxD_block_t *) tmp_v_addr; -			pre_rxd_blk->reserved_1 = END_OF_BLOCK;	/* last RxD  +			pre_rxd_blk->reserved_1 = END_OF_BLOCK;	/* last RxD  								 * marker.  								 */  #ifndef	CONFIG_2BUFF_MODE @@ -433,43 +517,43 @@ static int init_shared_mem(struct s2io_nic *nic)  	}  #ifdef CONFIG_2BUFF_MODE -	/*  +	/*  	 * Allocation of Storages for buffer addresses in 2BUFF mode  	 * and the buffers as well.  	 */  	for (i = 0; i < config->rx_ring_num; i++) {  		blk_cnt =  		    config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1); -		nic->ba[i] = kmalloc((sizeof(buffAdd_t *) * blk_cnt), +		mac_control->rings[i].ba = kmalloc((sizeof(buffAdd_t *) * blk_cnt),  				     GFP_KERNEL); -		if (!nic->ba[i]) +		if (!mac_control->rings[i].ba)  			return -ENOMEM;  		for (j = 0; j < blk_cnt; j++) {  			int k = 0; -			nic->ba[i][j] = kmalloc((sizeof(buffAdd_t) * +			mac_control->rings[i].ba[j] = kmalloc((sizeof(buffAdd_t) *  						 (MAX_RXDS_PER_BLOCK + 1)),  						GFP_KERNEL); -			if (!nic->ba[i][j]) +			if (!mac_control->rings[i].ba[j])  				return -ENOMEM;  			while (k != MAX_RXDS_PER_BLOCK) { -				ba = &nic->ba[i][j][k]; +				ba = &mac_control->rings[i].ba[j][k]; -				ba->ba_0_org = kmalloc +				ba->ba_0_org = (void *) kmalloc  				    (BUF0_LEN + ALIGN_SIZE, GFP_KERNEL);  				if (!ba->ba_0_org)  					return -ENOMEM; -				tmp = (unsigned long) ba->ba_0_org; +				tmp = (u64) ba->ba_0_org;  				tmp += ALIGN_SIZE; -				tmp &= ~((unsigned long) ALIGN_SIZE); +				tmp &= ~((u64) ALIGN_SIZE);  				ba->ba_0 = (void *) tmp; -				ba->ba_1_org = kmalloc +				ba->ba_1_org = (void *) kmalloc  				    (BUF1_LEN + ALIGN_SIZE, GFP_KERNEL);  				if (!ba->ba_1_org)  					return -ENOMEM; -				tmp = (unsigned long) ba->ba_1_org; +				tmp = (u64) ba->ba_1_org;  				tmp += ALIGN_SIZE; -				tmp &= ~((unsigned long) ALIGN_SIZE); +				tmp &= ~((u64) ALIGN_SIZE);  				ba->ba_1 = (void *) tmp;  				k++;  			} @@ -483,9 +567,9 @@ static int init_shared_mem(struct s2io_nic *nic)  	    (nic->pdev, size, &mac_control->stats_mem_phy);  	if (!mac_control->stats_mem) { -		/*  -		 * In case of failure, free_shared_mem() is called, which  -		 * should free any memory that was alloced till the  +		/* +		 * In case of failure, free_shared_mem() is called, which +		 * should free any memory that was alloced till the  		 * failure happened.  		 */  		return -ENOMEM; @@ -495,15 +579,14 @@ static int init_shared_mem(struct s2io_nic *nic)  	tmp_v_addr = mac_control->stats_mem;  	mac_control->stats_info = (StatInfo_t *) tmp_v_addr;  	memset(tmp_v_addr, 0, size); -  	DBG_PRINT(INIT_DBG, "%s:Ring Mem PHY: 0x%llx\n", dev->name,  		  (unsigned long long) tmp_p_addr);  	return SUCCESS;  } -/**   - * free_shared_mem - Free the allocated Memory  +/** + * free_shared_mem - Free the allocated Memory   * @nic:  Device private variable.   * Description: This function is to free all memory locations allocated by   * the init_shared_mem() function and return it to the kernel. @@ -533,15 +616,19 @@ static void free_shared_mem(struct s2io_nic *nic)  						lst_per_page);  		for (j = 0; j < page_num; j++) {  			int mem_blks = (j * lst_per_page); -			if (!nic->list_info[i][mem_blks].list_virt_addr) +			if ((!mac_control->fifos[i].list_info) || +				(!mac_control->fifos[i].list_info[mem_blks]. +				 list_virt_addr))  				break;  			pci_free_consistent(nic->pdev, PAGE_SIZE, -					    nic->list_info[i][mem_blks]. +					    mac_control->fifos[i]. +					    list_info[mem_blks].  					    list_virt_addr, -					    nic->list_info[i][mem_blks]. +					    mac_control->fifos[i]. +					    list_info[mem_blks].  					    list_phy_addr);  		} -		kfree(nic->list_info[i]); +		kfree(mac_control->fifos[i].list_info);  	}  #ifndef CONFIG_2BUFF_MODE @@ -550,10 +637,12 @@ static void free_shared_mem(struct s2io_nic *nic)  	size = SIZE_OF_BLOCK;  #endif  	for (i = 0; i < config->rx_ring_num; i++) { -		blk_cnt = nic->block_count[i]; +		blk_cnt = mac_control->rings[i].block_count;  		for (j = 0; j < blk_cnt; j++) { -			tmp_v_addr = nic->rx_blocks[i][j].block_virt_addr; -			tmp_p_addr = nic->rx_blocks[i][j].block_dma_addr; +			tmp_v_addr = mac_control->rings[i].rx_blocks[j]. +				block_virt_addr; +			tmp_p_addr = mac_control->rings[i].rx_blocks[j]. +				block_dma_addr;  			if (tmp_v_addr == NULL)  				break;  			pci_free_consistent(nic->pdev, size, @@ -566,35 +655,21 @@ static void free_shared_mem(struct s2io_nic *nic)  	for (i = 0; i < config->rx_ring_num; i++) {  		blk_cnt =  		    config->rx_cfg[i].num_rxd / (MAX_RXDS_PER_BLOCK + 1); -		if (!nic->ba[i]) -			goto end_free;  		for (j = 0; j < blk_cnt; j++) {  			int k = 0; -			if (!nic->ba[i][j]) { -				kfree(nic->ba[i]); -				goto end_free; -			} +			if (!mac_control->rings[i].ba[j]) +				continue;  			while (k != MAX_RXDS_PER_BLOCK) { -				buffAdd_t *ba = &nic->ba[i][j][k]; -				if (!ba || !ba->ba_0_org || !ba->ba_1_org) -				{ -					kfree(nic->ba[i]); -					kfree(nic->ba[i][j]); -					if(ba->ba_0_org) -						kfree(ba->ba_0_org); -					if(ba->ba_1_org) -						kfree(ba->ba_1_org); -					goto end_free; -				} +				buffAdd_t *ba = &mac_control->rings[i].ba[j][k];  				kfree(ba->ba_0_org);  				kfree(ba->ba_1_org);  				k++;  			} -			kfree(nic->ba[i][j]); +			kfree(mac_control->rings[i].ba[j]);  		} -		kfree(nic->ba[i]); +		if (mac_control->rings[i].ba) +			kfree(mac_control->rings[i].ba);  	} -end_free:  #endif  	if (mac_control->stats_mem) { @@ -605,12 +680,93 @@ end_free:  	}  } -/**   - *  init_nic - Initialization of hardware  +/** + * s2io_verify_pci_mode - + */ + +static int s2io_verify_pci_mode(nic_t *nic) +{ +	XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; +	register u64 val64 = 0; +	int     mode; + +	val64 = readq(&bar0->pci_mode); +	mode = (u8)GET_PCI_MODE(val64); + +	if ( val64 & PCI_MODE_UNKNOWN_MODE) +		return -1;      /* Unknown PCI mode */ +	return mode; +} + + +/** + * s2io_print_pci_mode - + */ +static int s2io_print_pci_mode(nic_t *nic) +{ +	XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; +	register u64 val64 = 0; +	int	mode; +	struct config_param *config = &nic->config; + +	val64 = readq(&bar0->pci_mode); +	mode = (u8)GET_PCI_MODE(val64); + +	if ( val64 & PCI_MODE_UNKNOWN_MODE) +		return -1;	/* Unknown PCI mode */ + +	if (val64 & PCI_MODE_32_BITS) { +		DBG_PRINT(ERR_DBG, "%s: Device is on 32 bit ", nic->dev->name); +	} else { +		DBG_PRINT(ERR_DBG, "%s: Device is on 64 bit ", nic->dev->name); +	} + +	switch(mode) { +		case PCI_MODE_PCI_33: +			DBG_PRINT(ERR_DBG, "33MHz PCI bus\n"); +			config->bus_speed = 33; +			break; +		case PCI_MODE_PCI_66: +			DBG_PRINT(ERR_DBG, "66MHz PCI bus\n"); +			config->bus_speed = 133; +			break; +		case PCI_MODE_PCIX_M1_66: +			DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n"); +			config->bus_speed = 133; /* Herc doubles the clock rate */ +			break; +		case PCI_MODE_PCIX_M1_100: +			DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n"); +			config->bus_speed = 200; +			break; +		case PCI_MODE_PCIX_M1_133: +			DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n"); +			config->bus_speed = 266; +			break; +		case PCI_MODE_PCIX_M2_66: +			DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n"); +			config->bus_speed = 133; +			break; +		case PCI_MODE_PCIX_M2_100: +			DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n"); +			config->bus_speed = 200; +			break; +		case PCI_MODE_PCIX_M2_133: +			DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n"); +			config->bus_speed = 266; +			break; +		default: +			return -1;	/* Unsupported bus speed */ +	} + +	return mode; +} + +/** + *  init_nic - Initialization of hardware   *  @nic: device peivate variable - *  Description: The function sequentially configures every block  - *  of the H/W from their reset values.  - *  Return Value:  SUCCESS on success and  + *  Description: The function sequentially configures every block + *  of the H/W from their reset values. + *  Return Value:  SUCCESS on success and   *  '-1' on failure (endian settings incorrect).   */ @@ -626,21 +782,32 @@ static int init_nic(struct s2io_nic *nic)  	struct config_param *config;  	int mdio_cnt = 0, dtx_cnt = 0;  	unsigned long long mem_share; +	int mem_size;  	mac_control = &nic->mac_control;  	config = &nic->config; -	/* Initialize swapper control register */ -	if (s2io_set_swapper(nic)) { +	/* to set the swapper controle on the card */ +	if(s2io_set_swapper(nic)) {  		DBG_PRINT(ERR_DBG,"ERROR: Setting Swapper failed\n");  		return -1;  	} +	/* +	 * Herc requires EOI to be removed from reset before XGXS, so.. +	 */ +	if (nic->device_type & XFRAME_II_DEVICE) { +		val64 = 0xA500000000ULL; +		writeq(val64, &bar0->sw_reset); +		msleep(500); +		val64 = readq(&bar0->sw_reset); +	} +  	/* Remove XGXS from reset state */  	val64 = 0;  	writeq(val64, &bar0->sw_reset); -	val64 = readq(&bar0->sw_reset);  	msleep(500); +	val64 = readq(&bar0->sw_reset);  	/*  Enable Receiving broadcasts */  	add = &bar0->mac_cfg; @@ -660,48 +827,58 @@ static int init_nic(struct s2io_nic *nic)  	val64 = dev->mtu;  	writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len); -	/*  -	 * Configuring the XAUI Interface of Xena.  +	/* +	 * Configuring the XAUI Interface of Xena.  	 * *************************************** -	 * To Configure the Xena's XAUI, one has to write a series  -	 * of 64 bit values into two registers in a particular  -	 * sequence. Hence a macro 'SWITCH_SIGN' has been defined  -	 * which will be defined in the array of configuration values  -	 * (default_dtx_cfg & default_mdio_cfg) at appropriate places  -	 * to switch writing from one regsiter to another. We continue  +	 * To Configure the Xena's XAUI, one has to write a series +	 * of 64 bit values into two registers in a particular +	 * sequence. Hence a macro 'SWITCH_SIGN' has been defined +	 * which will be defined in the array of configuration values +	 * (xena_dtx_cfg & xena_mdio_cfg) at appropriate places +	 * to switch writing from one regsiter to another. We continue  	 * writing these values until we encounter the 'END_SIGN' macro. -	 * For example, After making a series of 21 writes into  -	 * dtx_control register the 'SWITCH_SIGN' appears and hence we  +	 * For example, After making a series of 21 writes into +	 * dtx_control register the 'SWITCH_SIGN' appears and hence we  	 * start writing into mdio_control until we encounter END_SIGN.  	 */ -	while (1) { -	      dtx_cfg: -		while (default_dtx_cfg[dtx_cnt] != END_SIGN) { -			if (default_dtx_cfg[dtx_cnt] == SWITCH_SIGN) { -				dtx_cnt++; -				goto mdio_cfg; -			} -			SPECIAL_REG_WRITE(default_dtx_cfg[dtx_cnt], +	if (nic->device_type & XFRAME_II_DEVICE) { +		while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) { +			SPECIAL_REG_WRITE(herc_act_dtx_cfg[dtx_cnt],  					  &bar0->dtx_control, UF); -			val64 = readq(&bar0->dtx_control); +			if (dtx_cnt & 0x1) +				msleep(1); /* Necessary!! */  			dtx_cnt++;  		} -	      mdio_cfg: -		while (default_mdio_cfg[mdio_cnt] != END_SIGN) { -			if (default_mdio_cfg[mdio_cnt] == SWITCH_SIGN) { +	} else { +		while (1) { +		      dtx_cfg: +			while (xena_dtx_cfg[dtx_cnt] != END_SIGN) { +				if (xena_dtx_cfg[dtx_cnt] == SWITCH_SIGN) { +					dtx_cnt++; +					goto mdio_cfg; +				} +				SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt], +						  &bar0->dtx_control, UF); +				val64 = readq(&bar0->dtx_control); +				dtx_cnt++; +			} +		      mdio_cfg: +			while (xena_mdio_cfg[mdio_cnt] != END_SIGN) { +				if (xena_mdio_cfg[mdio_cnt] == SWITCH_SIGN) { +					mdio_cnt++; +					goto dtx_cfg; +				} +				SPECIAL_REG_WRITE(xena_mdio_cfg[mdio_cnt], +						  &bar0->mdio_control, UF); +				val64 = readq(&bar0->mdio_control);  				mdio_cnt++; +			} +			if ((xena_dtx_cfg[dtx_cnt] == END_SIGN) && +			    (xena_mdio_cfg[mdio_cnt] == END_SIGN)) { +				break; +			} else {  				goto dtx_cfg;  			} -			SPECIAL_REG_WRITE(default_mdio_cfg[mdio_cnt], -					  &bar0->mdio_control, UF); -			val64 = readq(&bar0->mdio_control); -			mdio_cnt++; -		} -		if ((default_dtx_cfg[dtx_cnt] == END_SIGN) && -		    (default_mdio_cfg[mdio_cnt] == END_SIGN)) { -			break; -		} else { -			goto dtx_cfg;  		}  	} @@ -748,12 +925,20 @@ static int init_nic(struct s2io_nic *nic)  	val64 |= BIT(0);	/* To enable the FIFO partition. */  	writeq(val64, &bar0->tx_fifo_partition_0); +	/* +	 * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug +	 * SXE-008 TRANSMIT DMA ARBITRATION ISSUE. +	 */ +	if ((nic->device_type == XFRAME_I_DEVICE) && +		(get_xena_rev_id(nic->pdev) < 4)) +		writeq(PCC_ENABLE_FOUR, &bar0->pcc_enable); +  	val64 = readq(&bar0->tx_fifo_partition_0);  	DBG_PRINT(INIT_DBG, "Fifo partition at: 0x%p is: 0x%llx\n",  		  &bar0->tx_fifo_partition_0, (unsigned long long) val64); -	/*  -	 * Initialization of Tx_PA_CONFIG register to ignore packet  +	/* +	 * Initialization of Tx_PA_CONFIG register to ignore packet  	 * integrity checking.  	 */  	val64 = readq(&bar0->tx_pa_cfg); @@ -770,85 +955,304 @@ static int init_nic(struct s2io_nic *nic)  	}  	writeq(val64, &bar0->rx_queue_priority); -	/*  -	 * Allocating equal share of memory to all the  +	/* +	 * Allocating equal share of memory to all the  	 * configured Rings.  	 */  	val64 = 0; +	if (nic->device_type & XFRAME_II_DEVICE) +		mem_size = 32; +	else +		mem_size = 64; +  	for (i = 0; i < config->rx_ring_num; i++) {  		switch (i) {  		case 0: -			mem_share = (64 / config->rx_ring_num + -				     64 % config->rx_ring_num); +			mem_share = (mem_size / config->rx_ring_num + +				     mem_size % config->rx_ring_num);  			val64 |= RX_QUEUE_CFG_Q0_SZ(mem_share);  			continue;  		case 1: -			mem_share = (64 / config->rx_ring_num); +			mem_share = (mem_size / config->rx_ring_num);  			val64 |= RX_QUEUE_CFG_Q1_SZ(mem_share);  			continue;  		case 2: -			mem_share = (64 / config->rx_ring_num); +			mem_share = (mem_size / config->rx_ring_num);  			val64 |= RX_QUEUE_CFG_Q2_SZ(mem_share);  			continue;  		case 3: -			mem_share = (64 / config->rx_ring_num); +			mem_share = (mem_size / config->rx_ring_num);  			val64 |= RX_QUEUE_CFG_Q3_SZ(mem_share);  			continue;  		case 4: -			mem_share = (64 / config->rx_ring_num); +			mem_share = (mem_size / config->rx_ring_num);  			val64 |= RX_QUEUE_CFG_Q4_SZ(mem_share);  			continue;  		case 5: -			mem_share = (64 / config->rx_ring_num); +			mem_share = (mem_size / config->rx_ring_num);  			val64 |= RX_QUEUE_CFG_Q5_SZ(mem_share);  			continue;  		case 6: -			mem_share = (64 / config->rx_ring_num); +			mem_share = (mem_size / config->rx_ring_num);  			val64 |= RX_QUEUE_CFG_Q6_SZ(mem_share);  			continue;  		case 7: -			mem_share = (64 / config->rx_ring_num); +			mem_share = (mem_size / config->rx_ring_num);  			val64 |= RX_QUEUE_CFG_Q7_SZ(mem_share);  			continue;  		}  	}  	writeq(val64, &bar0->rx_queue_cfg); -	/*  -	 * Initializing the Tx round robin registers to 0. -	 * Filling Tx and Rx round robin registers as per the  -	 * number of FIFOs and Rings is still TODO. -	 */ -	writeq(0, &bar0->tx_w_round_robin_0); -	writeq(0, &bar0->tx_w_round_robin_1); -	writeq(0, &bar0->tx_w_round_robin_2); -	writeq(0, &bar0->tx_w_round_robin_3); -	writeq(0, &bar0->tx_w_round_robin_4); - -	/*  -	 * TODO -	 * Disable Rx steering. Hard coding all packets be steered to -	 * Queue 0 for now.  +	/* +	 * Filling Tx round robin registers +	 * as per the number of FIFOs  	 */ -	val64 = 0x8080808080808080ULL; -	writeq(val64, &bar0->rts_qos_steering); +	switch (config->tx_fifo_num) { +	case 1: +		val64 = 0x0000000000000000ULL; +		writeq(val64, &bar0->tx_w_round_robin_0); +		writeq(val64, &bar0->tx_w_round_robin_1); +		writeq(val64, &bar0->tx_w_round_robin_2); +		writeq(val64, &bar0->tx_w_round_robin_3); +		writeq(val64, &bar0->tx_w_round_robin_4); +		break; +	case 2: +		val64 = 0x0000010000010000ULL; +		writeq(val64, &bar0->tx_w_round_robin_0); +		val64 = 0x0100000100000100ULL; +		writeq(val64, &bar0->tx_w_round_robin_1); +		val64 = 0x0001000001000001ULL; +		writeq(val64, &bar0->tx_w_round_robin_2); +		val64 = 0x0000010000010000ULL; +		writeq(val64, &bar0->tx_w_round_robin_3); +		val64 = 0x0100000000000000ULL; +		writeq(val64, &bar0->tx_w_round_robin_4); +		break; +	case 3: +		val64 = 0x0001000102000001ULL; +		writeq(val64, &bar0->tx_w_round_robin_0); +		val64 = 0x0001020000010001ULL; +		writeq(val64, &bar0->tx_w_round_robin_1); +		val64 = 0x0200000100010200ULL; +		writeq(val64, &bar0->tx_w_round_robin_2); +		val64 = 0x0001000102000001ULL; +		writeq(val64, &bar0->tx_w_round_robin_3); +		val64 = 0x0001020000000000ULL; +		writeq(val64, &bar0->tx_w_round_robin_4); +		break; +	case 4: +		val64 = 0x0001020300010200ULL; +		writeq(val64, &bar0->tx_w_round_robin_0); +		val64 = 0x0100000102030001ULL; +		writeq(val64, &bar0->tx_w_round_robin_1); +		val64 = 0x0200010000010203ULL; +		writeq(val64, &bar0->tx_w_round_robin_2); +		val64 = 0x0001020001000001ULL; +		writeq(val64, &bar0->tx_w_round_robin_3); +		val64 = 0x0203000100000000ULL; +		writeq(val64, &bar0->tx_w_round_robin_4); +		break; +	case 5: +		val64 = 0x0001000203000102ULL; +		writeq(val64, &bar0->tx_w_round_robin_0); +		val64 = 0x0001020001030004ULL; +		writeq(val64, &bar0->tx_w_round_robin_1); +		val64 = 0x0001000203000102ULL; +		writeq(val64, &bar0->tx_w_round_robin_2); +		val64 = 0x0001020001030004ULL; +		writeq(val64, &bar0->tx_w_round_robin_3); +		val64 = 0x0001000000000000ULL; +		writeq(val64, &bar0->tx_w_round_robin_4); +		break; +	case 6: +		val64 = 0x0001020304000102ULL; +		writeq(val64, &bar0->tx_w_round_robin_0); +		val64 = 0x0304050001020001ULL; +		writeq(val64, &bar0->tx_w_round_robin_1); +		val64 = 0x0203000100000102ULL; +		writeq(val64, &bar0->tx_w_round_robin_2); +		val64 = 0x0304000102030405ULL; +		writeq(val64, &bar0->tx_w_round_robin_3); +		val64 = 0x0001000200000000ULL; +		writeq(val64, &bar0->tx_w_round_robin_4); +		break; +	case 7: +		val64 = 0x0001020001020300ULL; +		writeq(val64, &bar0->tx_w_round_robin_0); +		val64 = 0x0102030400010203ULL; +		writeq(val64, &bar0->tx_w_round_robin_1); +		val64 = 0x0405060001020001ULL; +		writeq(val64, &bar0->tx_w_round_robin_2); +		val64 = 0x0304050000010200ULL; +		writeq(val64, &bar0->tx_w_round_robin_3); +		val64 = 0x0102030000000000ULL; +		writeq(val64, &bar0->tx_w_round_robin_4); +		break; +	case 8: +		val64 = 0x0001020300040105ULL; +		writeq(val64, &bar0->tx_w_round_robin_0); +		val64 = 0x0200030106000204ULL; +		writeq(val64, &bar0->tx_w_round_robin_1); +		val64 = 0x0103000502010007ULL; +		writeq(val64, &bar0->tx_w_round_robin_2); +		val64 = 0x0304010002060500ULL; +		writeq(val64, &bar0->tx_w_round_robin_3); +		val64 = 0x0103020400000000ULL; +		writeq(val64, &bar0->tx_w_round_robin_4); +		break; +	} + +	/* Filling the Rx round robin registers as per the +	 * number of Rings and steering based on QoS. +         */ +	switch (config->rx_ring_num) { +	case 1: +		val64 = 0x8080808080808080ULL; +		writeq(val64, &bar0->rts_qos_steering); +		break; +	case 2: +		val64 = 0x0000010000010000ULL; +		writeq(val64, &bar0->rx_w_round_robin_0); +		val64 = 0x0100000100000100ULL; +		writeq(val64, &bar0->rx_w_round_robin_1); +		val64 = 0x0001000001000001ULL; +		writeq(val64, &bar0->rx_w_round_robin_2); +		val64 = 0x0000010000010000ULL; +		writeq(val64, &bar0->rx_w_round_robin_3); +		val64 = 0x0100000000000000ULL; +		writeq(val64, &bar0->rx_w_round_robin_4); + +		val64 = 0x8080808040404040ULL; +		writeq(val64, &bar0->rts_qos_steering); +		break; +	case 3: +		val64 = 0x0001000102000001ULL; +		writeq(val64, &bar0->rx_w_round_robin_0); +		val64 = 0x0001020000010001ULL; +		writeq(val64, &bar0->rx_w_round_robin_1); +		val64 = 0x0200000100010200ULL; +		writeq(val64, &bar0->rx_w_round_robin_2); +		val64 = 0x0001000102000001ULL; +		writeq(val64, &bar0->rx_w_round_robin_3); +		val64 = 0x0001020000000000ULL; +		writeq(val64, &bar0->rx_w_round_robin_4); + +		val64 = 0x8080804040402020ULL; +		writeq(val64, &bar0->rts_qos_steering); +		break; +	case 4: +		val64 = 0x0001020300010200ULL; +		writeq(val64, &bar0->rx_w_round_robin_0); +		val64 = 0x0100000102030001ULL; +		writeq(val64, &bar0->rx_w_round_robin_1); +		val64 = 0x0200010000010203ULL; +		writeq(val64, &bar0->rx_w_round_robin_2); +		val64 = 0x0001020001000001ULL;	 +		writeq(val64, &bar0->rx_w_round_robin_3); +		val64 = 0x0203000100000000ULL; +		writeq(val64, &bar0->rx_w_round_robin_4); + +		val64 = 0x8080404020201010ULL; +		writeq(val64, &bar0->rts_qos_steering); +		break; +	case 5: +		val64 = 0x0001000203000102ULL; +		writeq(val64, &bar0->rx_w_round_robin_0); +		val64 = 0x0001020001030004ULL; +		writeq(val64, &bar0->rx_w_round_robin_1); +		val64 = 0x0001000203000102ULL; +		writeq(val64, &bar0->rx_w_round_robin_2); +		val64 = 0x0001020001030004ULL; +		writeq(val64, &bar0->rx_w_round_robin_3); +		val64 = 0x0001000000000000ULL; +		writeq(val64, &bar0->rx_w_round_robin_4); + +		val64 = 0x8080404020201008ULL; +		writeq(val64, &bar0->rts_qos_steering); +		break; +	case 6: +		val64 = 0x0001020304000102ULL; +		writeq(val64, &bar0->rx_w_round_robin_0); +		val64 = 0x0304050001020001ULL; +		writeq(val64, &bar0->rx_w_round_robin_1); +		val64 = 0x0203000100000102ULL; +		writeq(val64, &bar0->rx_w_round_robin_2); +		val64 = 0x0304000102030405ULL; +		writeq(val64, &bar0->rx_w_round_robin_3); +		val64 = 0x0001000200000000ULL; +		writeq(val64, &bar0->rx_w_round_robin_4); + +		val64 = 0x8080404020100804ULL; +		writeq(val64, &bar0->rts_qos_steering); +		break; +	case 7: +		val64 = 0x0001020001020300ULL; +		writeq(val64, &bar0->rx_w_round_robin_0); +		val64 = 0x0102030400010203ULL; +		writeq(val64, &bar0->rx_w_round_robin_1); +		val64 = 0x0405060001020001ULL; +		writeq(val64, &bar0->rx_w_round_robin_2); +		val64 = 0x0304050000010200ULL; +		writeq(val64, &bar0->rx_w_round_robin_3); +		val64 = 0x0102030000000000ULL; +		writeq(val64, &bar0->rx_w_round_robin_4); + +		val64 = 0x8080402010080402ULL; +		writeq(val64, &bar0->rts_qos_steering); +		break; +	case 8: +		val64 = 0x0001020300040105ULL; +		writeq(val64, &bar0->rx_w_round_robin_0); +		val64 = 0x0200030106000204ULL; +		writeq(val64, &bar0->rx_w_round_robin_1); +		val64 = 0x0103000502010007ULL; +		writeq(val64, &bar0->rx_w_round_robin_2); +		val64 = 0x0304010002060500ULL; +		writeq(val64, &bar0->rx_w_round_robin_3); +		val64 = 0x0103020400000000ULL; +		writeq(val64, &bar0->rx_w_round_robin_4); + +		val64 = 0x8040201008040201ULL; +		writeq(val64, &bar0->rts_qos_steering); +		break; +	}  	/* UDP Fix */  	val64 = 0; -	for (i = 1; i < 8; i++) +	for (i = 0; i < 8; i++) +		writeq(val64, &bar0->rts_frm_len_n[i]); + +	/* Set the default rts frame length for the rings configured */ +	val64 = MAC_RTS_FRM_LEN_SET(dev->mtu+22); +	for (i = 0 ; i < config->rx_ring_num ; i++)  		writeq(val64, &bar0->rts_frm_len_n[i]); -	/* Set rts_frm_len register for fifo 0 */ -	writeq(MAC_RTS_FRM_LEN_SET(dev->mtu + 22), -	       &bar0->rts_frm_len_n[0]); +	/* Set the frame length for the configured rings +	 * desired by the user +	 */ +	for (i = 0; i < config->rx_ring_num; i++) { +		/* If rts_frm_len[i] == 0 then it is assumed that user not +		 * specified frame length steering. +		 * If the user provides the frame length then program +		 * the rts_frm_len register for those values or else +		 * leave it as it is. +		 */ +		if (rts_frm_len[i] != 0) { +			writeq(MAC_RTS_FRM_LEN_SET(rts_frm_len[i]), +				&bar0->rts_frm_len_n[i]); +		} +	} -	/* Enable statistics */ +	/* Program statistics memory */  	writeq(mac_control->stats_mem_phy, &bar0->stat_addr); -	val64 = SET_UPDT_PERIOD(Stats_refresh_time) | -	    STAT_CFG_STAT_RO | STAT_CFG_STAT_EN; -	writeq(val64, &bar0->stat_cfg); -	/*  +	if (nic->device_type == XFRAME_II_DEVICE) { +		val64 = STAT_BC(0x320); +		writeq(val64, &bar0->stat_byte_cnt); +	} + +	/*  	 * Initializing the sampling rate for the device to calculate the  	 * bandwidth utilization.  	 */ @@ -857,30 +1261,38 @@ static int init_nic(struct s2io_nic *nic)  	writeq(val64, &bar0->mac_link_util); -	/*  -	 * Initializing the Transmit and Receive Traffic Interrupt  +	/* +	 * Initializing the Transmit and Receive Traffic Interrupt  	 * Scheme.  	 */ -	/* TTI Initialization. Default Tx timer gets us about +	/* +	 * TTI Initialization. Default Tx timer gets us about  	 * 250 interrupts per sec. Continuous interrupts are enabled  	 * by default.  	 */ -	val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078) | -	    TTI_DATA1_MEM_TX_URNG_A(0xA) | +	if (nic->device_type == XFRAME_II_DEVICE) { +		int count = (nic->config.bus_speed * 125)/2; +		val64 = TTI_DATA1_MEM_TX_TIMER_VAL(count); +	} else { + +		val64 = TTI_DATA1_MEM_TX_TIMER_VAL(0x2078); +	} +	val64 |= TTI_DATA1_MEM_TX_URNG_A(0xA) |  	    TTI_DATA1_MEM_TX_URNG_B(0x10) | -	    TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN | -		TTI_DATA1_MEM_TX_TIMER_CI_EN; +	    TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN; +		if (use_continuous_tx_intrs) +			val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;  	writeq(val64, &bar0->tti_data1_mem);  	val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |  	    TTI_DATA2_MEM_TX_UFC_B(0x20) | -	    TTI_DATA2_MEM_TX_UFC_C(0x40) | TTI_DATA2_MEM_TX_UFC_D(0x80); +	    TTI_DATA2_MEM_TX_UFC_C(0x70) | TTI_DATA2_MEM_TX_UFC_D(0x80);  	writeq(val64, &bar0->tti_data2_mem);  	val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;  	writeq(val64, &bar0->tti_command_mem); -	/*  +	/*  	 * Once the operation completes, the Strobe bit of the command  	 * register will be reset. We poll for this particular condition  	 * We wait for a maximum of 500ms for the operation to complete, @@ -901,52 +1313,97 @@ static int init_nic(struct s2io_nic *nic)  		time++;  	} -	/* RTI Initialization */ -	val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF) | -	    RTI_DATA1_MEM_RX_URNG_A(0xA) | -	    RTI_DATA1_MEM_RX_URNG_B(0x10) | -	    RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN; +	if (nic->config.bimodal) { +		int k = 0; +		for (k = 0; k < config->rx_ring_num; k++) { +			val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD; +			val64 |= TTI_CMD_MEM_OFFSET(0x38+k); +			writeq(val64, &bar0->tti_command_mem); + +		/* +		 * Once the operation completes, the Strobe bit of the command +		 * register will be reset. We poll for this particular condition +		 * We wait for a maximum of 500ms for the operation to complete, +		 * if it's not complete by then we return error. +		*/ +			time = 0; +			while (TRUE) { +				val64 = readq(&bar0->tti_command_mem); +				if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) { +					break; +				} +				if (time > 10) { +					DBG_PRINT(ERR_DBG, +						"%s: TTI init Failed\n", +					dev->name); +					return -1; +				} +				time++; +				msleep(50); +			} +		} +	} else { -	writeq(val64, &bar0->rti_data1_mem); +		/* RTI Initialization */ +		if (nic->device_type == XFRAME_II_DEVICE) { +			/* +			 * Programmed to generate Apprx 500 Intrs per +			 * second +			 */ +			int count = (nic->config.bus_speed * 125)/4; +			val64 = RTI_DATA1_MEM_RX_TIMER_VAL(count); +		} else { +			val64 = RTI_DATA1_MEM_RX_TIMER_VAL(0xFFF); +		} +		val64 |= RTI_DATA1_MEM_RX_URNG_A(0xA) | +		    RTI_DATA1_MEM_RX_URNG_B(0x10) | +		    RTI_DATA1_MEM_RX_URNG_C(0x30) | RTI_DATA1_MEM_RX_TIMER_AC_EN; -	val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) | -	    RTI_DATA2_MEM_RX_UFC_B(0x2) | -	    RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80); -	writeq(val64, &bar0->rti_data2_mem); +		writeq(val64, &bar0->rti_data1_mem); -	val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD; -	writeq(val64, &bar0->rti_command_mem); +		val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) | +		    RTI_DATA2_MEM_RX_UFC_B(0x2) | +		    RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80); +		writeq(val64, &bar0->rti_data2_mem); -	/*  -	 * Once the operation completes, the Strobe bit of the command -	 * register will be reset. We poll for this particular condition -	 * We wait for a maximum of 500ms for the operation to complete, -	 * if it's not complete by then we return error. -	 */ -	time = 0; -	while (TRUE) { -		val64 = readq(&bar0->rti_command_mem); -		if (!(val64 & TTI_CMD_MEM_STROBE_NEW_CMD)) { -			break; -		} -		if (time > 10) { -			DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n", -				  dev->name); -			return -1; +		for (i = 0; i < config->rx_ring_num; i++) { +			val64 = RTI_CMD_MEM_WE | RTI_CMD_MEM_STROBE_NEW_CMD +					| RTI_CMD_MEM_OFFSET(i); +			writeq(val64, &bar0->rti_command_mem); + +			/* +			 * Once the operation completes, the Strobe bit of the +			 * command register will be reset. We poll for this +			 * particular condition. We wait for a maximum of 500ms +			 * for the operation to complete, if it's not complete +			 * by then we return error. +			 */ +			time = 0; +			while (TRUE) { +				val64 = readq(&bar0->rti_command_mem); +				if (!(val64 & RTI_CMD_MEM_STROBE_NEW_CMD)) { +					break; +				} +				if (time > 10) { +					DBG_PRINT(ERR_DBG, "%s: RTI init Failed\n", +						  dev->name); +					return -1; +				} +				time++; +				msleep(50); +			}  		} -		time++; -		msleep(50);  	} -	/*  -	 * Initializing proper values as Pause threshold into all  +	/* +	 * Initializing proper values as Pause threshold into all  	 * the 8 Queues on Rx side.  	 */  	writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q0q3);  	writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q4q7);  	/* Disable RMAC PAD STRIPPING */ -	add = &bar0->mac_cfg; +	add = (void *) &bar0->mac_cfg;  	val64 = readq(&bar0->mac_cfg);  	val64 &= ~(MAC_CFG_RMAC_STRIP_PAD);  	writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); @@ -955,8 +1412,8 @@ static int init_nic(struct s2io_nic *nic)  	writel((u32) (val64 >> 32), (add + 4));  	val64 = readq(&bar0->mac_cfg); -	/*  -	 * Set the time value to be inserted in the pause frame  +	/* +	 * Set the time value to be inserted in the pause frame  	 * generated by xena.  	 */  	val64 = readq(&bar0->rmac_pause_cfg); @@ -964,7 +1421,7 @@ static int init_nic(struct s2io_nic *nic)  	val64 |= RMAC_PAUSE_HG_PTIME(nic->mac_control.rmac_pause_time);  	writeq(val64, &bar0->rmac_pause_cfg); -	/*  +	/*  	 * Set the Threshold Limit for Generating the pause frame  	 * If the amount of data in any Queue exceeds ratio of  	 * (mac_control.mc_pause_threshold_q0q3 or q4q7)/256 @@ -988,25 +1445,54 @@ static int init_nic(struct s2io_nic *nic)  	}  	writeq(val64, &bar0->mc_pause_thresh_q4q7); -	/*  -	 * TxDMA will stop Read request if the number of read split has  +	/* +	 * TxDMA will stop Read request if the number of read split has  	 * exceeded the limit pointed by shared_splits  	 */  	val64 = readq(&bar0->pic_control);  	val64 |= PIC_CNTL_SHARED_SPLITS(shared_splits);  	writeq(val64, &bar0->pic_control); +	/* +	 * Programming the Herc to split every write transaction +	 * that does not start on an ADB to reduce disconnects. +	 */ +	if (nic->device_type == XFRAME_II_DEVICE) { +		val64 = WREQ_SPLIT_MASK_SET_MASK(255); +		writeq(val64, &bar0->wreq_split_mask); +	} + +	/* Setting Link stability period to 64 ms */  +	if (nic->device_type == XFRAME_II_DEVICE) { +		val64 = MISC_LINK_STABILITY_PRD(3); +		writeq(val64, &bar0->misc_control); +	} +  	return SUCCESS;  } +#define LINK_UP_DOWN_INTERRUPT		1 +#define MAC_RMAC_ERR_TIMER		2 -/**   - *  en_dis_able_nic_intrs - Enable or Disable the interrupts  +#if defined(CONFIG_MSI_MODE) || defined(CONFIG_MSIX_MODE) +#define s2io_link_fault_indication(x) MAC_RMAC_ERR_TIMER +#else +int s2io_link_fault_indication(nic_t *nic) +{ +	if (nic->device_type == XFRAME_II_DEVICE) +		return LINK_UP_DOWN_INTERRUPT; +	else +		return MAC_RMAC_ERR_TIMER; +} +#endif + +/** + *  en_dis_able_nic_intrs - Enable or Disable the interrupts   *  @nic: device private variable,   *  @mask: A mask indicating which Intr block must be modified and,   *  @flag: A flag indicating whether to enable or disable the Intrs.   *  Description: This function will either disable or enable the interrupts - *  depending on the flag argument. The mask argument can be used to  - *  enable/disable any Intr block.  + *  depending on the flag argument. The mask argument can be used to + *  enable/disable any Intr block.   *  Return Value: NONE.   */ @@ -1024,20 +1510,31 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)  			temp64 = readq(&bar0->general_int_mask);  			temp64 &= ~((u64) val64);  			writeq(temp64, &bar0->general_int_mask); -			/*   -			 * Disabled all PCIX, Flash, MDIO, IIC and GPIO -			 * interrupts for now.  -			 * TODO  +			/* +			 * If Hercules adapter enable GPIO otherwise +			 * disabled all PCIX, Flash, MDIO, IIC and GPIO +			 * interrupts for now. +			 * TODO  			 */ -			writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask); -			/*  +			if (s2io_link_fault_indication(nic) == +					LINK_UP_DOWN_INTERRUPT ) { +				temp64 = readq(&bar0->pic_int_mask); +				temp64 &= ~((u64) PIC_INT_GPIO); +				writeq(temp64, &bar0->pic_int_mask); +				temp64 = readq(&bar0->gpio_int_mask); +				temp64 &= ~((u64) GPIO_INT_MASK_LINK_UP); +				writeq(temp64, &bar0->gpio_int_mask); +			} else { +				writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask); +			} +			/*  			 * No MSI Support is available presently, so TTI and  			 * RTI interrupts are also disabled.  			 */  		} else if (flag == DISABLE_INTRS) { -			/*   -			 * Disable PIC Intrs in the general  -			 * intr mask register  +			/* +			 * Disable PIC Intrs in the general +			 * intr mask register  			 */  			writeq(DISABLE_ALL_INTRS, &bar0->pic_int_mask);  			temp64 = readq(&bar0->general_int_mask); @@ -1055,27 +1552,27 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)  			temp64 = readq(&bar0->general_int_mask);  			temp64 &= ~((u64) val64);  			writeq(temp64, &bar0->general_int_mask); -			/*  -			 * Keep all interrupts other than PFC interrupt  +			/* +			 * Keep all interrupts other than PFC interrupt  			 * and PCC interrupt disabled in DMA level.  			 */  			val64 = DISABLE_ALL_INTRS & ~(TXDMA_PFC_INT_M |  						      TXDMA_PCC_INT_M);  			writeq(val64, &bar0->txdma_int_mask); -			/*  -			 * Enable only the MISC error 1 interrupt in PFC block  +			/* +			 * Enable only the MISC error 1 interrupt in PFC block  			 */  			val64 = DISABLE_ALL_INTRS & (~PFC_MISC_ERR_1);  			writeq(val64, &bar0->pfc_err_mask); -			/*  -			 * Enable only the FB_ECC error interrupt in PCC block  +			/* +			 * Enable only the FB_ECC error interrupt in PCC block  			 */  			val64 = DISABLE_ALL_INTRS & (~PCC_FB_ECC_ERR);  			writeq(val64, &bar0->pcc_err_mask);  		} else if (flag == DISABLE_INTRS) { -			/*  -			 * Disable TxDMA Intrs in the general intr mask  -			 * register  +			/* +			 * Disable TxDMA Intrs in the general intr mask +			 * register  			 */  			writeq(DISABLE_ALL_INTRS, &bar0->txdma_int_mask);  			writeq(DISABLE_ALL_INTRS, &bar0->pfc_err_mask); @@ -1093,15 +1590,15 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)  			temp64 = readq(&bar0->general_int_mask);  			temp64 &= ~((u64) val64);  			writeq(temp64, &bar0->general_int_mask); -			/*  -			 * All RxDMA block interrupts are disabled for now  -			 * TODO  +			/* +			 * All RxDMA block interrupts are disabled for now +			 * TODO  			 */  			writeq(DISABLE_ALL_INTRS, &bar0->rxdma_int_mask);  		} else if (flag == DISABLE_INTRS) { -			/*   -			 * Disable RxDMA Intrs in the general intr mask  -			 * register  +			/* +			 * Disable RxDMA Intrs in the general intr mask +			 * register  			 */  			writeq(DISABLE_ALL_INTRS, &bar0->rxdma_int_mask);  			temp64 = readq(&bar0->general_int_mask); @@ -1118,22 +1615,13 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)  			temp64 = readq(&bar0->general_int_mask);  			temp64 &= ~((u64) val64);  			writeq(temp64, &bar0->general_int_mask); -			/*  -			 * All MAC block error interrupts are disabled for now  -			 * except the link status change interrupt. +			/* +			 * All MAC block error interrupts are disabled for now  			 * TODO  			 */ -			val64 = MAC_INT_STATUS_RMAC_INT; -			temp64 = readq(&bar0->mac_int_mask); -			temp64 &= ~((u64) val64); -			writeq(temp64, &bar0->mac_int_mask); - -			val64 = readq(&bar0->mac_rmac_err_mask); -			val64 &= ~((u64) RMAC_LINK_STATE_CHANGE_INT); -			writeq(val64, &bar0->mac_rmac_err_mask);  		} else if (flag == DISABLE_INTRS) { -			/*   -			 * Disable MAC Intrs in the general intr mask register  +			/* +			 * Disable MAC Intrs in the general intr mask register  			 */  			writeq(DISABLE_ALL_INTRS, &bar0->mac_int_mask);  			writeq(DISABLE_ALL_INTRS, @@ -1152,14 +1640,14 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)  			temp64 = readq(&bar0->general_int_mask);  			temp64 &= ~((u64) val64);  			writeq(temp64, &bar0->general_int_mask); -			/*  +			/*  			 * All XGXS block error interrupts are disabled for now -			 * TODO  +			 * TODO  			 */  			writeq(DISABLE_ALL_INTRS, &bar0->xgxs_int_mask);  		} else if (flag == DISABLE_INTRS) { -			/*   -			 * Disable MC Intrs in the general intr mask register  +			/* +			 * Disable MC Intrs in the general intr mask register  			 */  			writeq(DISABLE_ALL_INTRS, &bar0->xgxs_int_mask);  			temp64 = readq(&bar0->general_int_mask); @@ -1175,11 +1663,11 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)  			temp64 = readq(&bar0->general_int_mask);  			temp64 &= ~((u64) val64);  			writeq(temp64, &bar0->general_int_mask); -			/*  -			 * All MC block error interrupts are disabled for now -			 * TODO  +			/* +			 * Enable all MC Intrs.  			 */ -			writeq(DISABLE_ALL_INTRS, &bar0->mc_int_mask); +			writeq(0x0, &bar0->mc_int_mask); +			writeq(0x0, &bar0->mc_err_mask);  		} else if (flag == DISABLE_INTRS) {  			/*  			 * Disable MC Intrs in the general intr mask register @@ -1199,14 +1687,14 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)  			temp64 = readq(&bar0->general_int_mask);  			temp64 &= ~((u64) val64);  			writeq(temp64, &bar0->general_int_mask); -			/*  +			/*  			 * Enable all the Tx side interrupts -			 * writing 0 Enables all 64 TX interrupt levels  +			 * writing 0 Enables all 64 TX interrupt levels  			 */  			writeq(0x0, &bar0->tx_traffic_mask);  		} else if (flag == DISABLE_INTRS) { -			/*  -			 * Disable Tx Traffic Intrs in the general intr mask  +			/* +			 * Disable Tx Traffic Intrs in the general intr mask  			 * register.  			 */  			writeq(DISABLE_ALL_INTRS, &bar0->tx_traffic_mask); @@ -1226,8 +1714,8 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)  			/* writing 0 Enables all 8 RX interrupt levels */  			writeq(0x0, &bar0->rx_traffic_mask);  		} else if (flag == DISABLE_INTRS) { -			/*   -			 * Disable Rx Traffic Intrs in the general intr mask  +			/* +			 * Disable Rx Traffic Intrs in the general intr mask  			 * register.  			 */  			writeq(DISABLE_ALL_INTRS, &bar0->rx_traffic_mask); @@ -1238,24 +1726,66 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag)  	}  } -/**   - *  verify_xena_quiescence - Checks whether the H/W is ready  +static int check_prc_pcc_state(u64 val64, int flag, int rev_id, int herc) +{ +	int ret = 0; + +	if (flag == FALSE) { +		if ((!herc && (rev_id >= 4)) || herc) { +			if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) && +			    ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == +			     ADAPTER_STATUS_RC_PRC_QUIESCENT)) { +				ret = 1; +			} +		}else { +			if (!(val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) && +			    ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == +			     ADAPTER_STATUS_RC_PRC_QUIESCENT)) { +				ret = 1; +			} +		} +	} else { +		if ((!herc && (rev_id >= 4)) || herc) { +			if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) == +			     ADAPTER_STATUS_RMAC_PCC_IDLE) && +			    (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) || +			     ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == +			      ADAPTER_STATUS_RC_PRC_QUIESCENT))) { +				ret = 1; +			} +		} else { +			if (((val64 & ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) == +			     ADAPTER_STATUS_RMAC_PCC_FOUR_IDLE) && +			    (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) || +			     ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == +			      ADAPTER_STATUS_RC_PRC_QUIESCENT))) { +				ret = 1; +			} +		} +	} + +	return ret; +} +/** + *  verify_xena_quiescence - Checks whether the H/W is ready   *  @val64 :  Value read from adapter status register.   *  @flag : indicates if the adapter enable bit was ever written once   *  before.   *  Description: Returns whether the H/W is ready to go or not. Depending - *  on whether adapter enable bit was written or not the comparison  + *  on whether adapter enable bit was written or not the comparison   *  differs and the calling function passes the input argument flag to   *  indicate this. - *  Return: 1 If xena is quiescence  + *  Return: 1 If xena is quiescence   *          0 If Xena is not quiescence   */ -static int verify_xena_quiescence(u64 val64, int flag) +static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag)  { -	int ret = 0; +	int ret = 0, herc;  	u64 tmp64 = ~((u64) val64); +	int rev_id = get_xena_rev_id(sp->pdev); +	herc = (sp->device_type == XFRAME_II_DEVICE);  	if (!  	    (tmp64 &  	     (ADAPTER_STATUS_TDMA_READY | ADAPTER_STATUS_RDMA_READY | @@ -1263,25 +1793,7 @@ static int verify_xena_quiescence(u64 val64, int flag)  	      ADAPTER_STATUS_PIC_QUIESCENT | ADAPTER_STATUS_MC_DRAM_READY |  	      ADAPTER_STATUS_MC_QUEUES_READY | ADAPTER_STATUS_M_PLL_LOCK |  	      ADAPTER_STATUS_P_PLL_LOCK))) { -		if (flag == FALSE) { -			if (!(val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) && -			    ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == -			     ADAPTER_STATUS_RC_PRC_QUIESCENT)) { - -				ret = 1; - -			} -		} else { -			if (((val64 & ADAPTER_STATUS_RMAC_PCC_IDLE) == -			     ADAPTER_STATUS_RMAC_PCC_IDLE) && -			    (!(val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) || -			     ((val64 & ADAPTER_STATUS_RC_PRC_QUIESCENT) == -			      ADAPTER_STATUS_RC_PRC_QUIESCENT))) { - -				ret = 1; - -			} -		} +		ret = check_prc_pcc_state(val64, flag, rev_id, herc);  	}  	return ret; @@ -1290,12 +1802,12 @@ static int verify_xena_quiescence(u64 val64, int flag)  /**   * fix_mac_address -  Fix for Mac addr problem on Alpha platforms   * @sp: Pointer to device specifc structure - * Description :  + * Description :   * New procedure to clear mac address reading  problems on Alpha platforms   *   */ -static void fix_mac_address(nic_t * sp) +void fix_mac_address(nic_t * sp)  {  	XENA_dev_config_t __iomem *bar0 = sp->bar0;  	u64 val64; @@ -1303,20 +1815,21 @@ static void fix_mac_address(nic_t * sp)  	while (fix_mac[i] != END_SIGN) {  		writeq(fix_mac[i++], &bar0->gpio_control); +		udelay(10);  		val64 = readq(&bar0->gpio_control);  	}  }  /** - *  start_nic - Turns the device on    + *  start_nic - Turns the device on   *  @nic : device private variable. - *  Description:  - *  This function actually turns the device on. Before this  function is  - *  called,all Registers are configured from their reset states  - *  and shared memory is allocated but the NIC is still quiescent. On  + *  Description: + *  This function actually turns the device on. Before this  function is + *  called,all Registers are configured from their reset states + *  and shared memory is allocated but the NIC is still quiescent. On   *  calling this function, the device interrupts are cleared and the NIC is   *  literally switched on by writing into the adapter control register. - *  Return Value:  + *  Return Value:   *  SUCCESS on success and -1 on failure.   */ @@ -1325,8 +1838,8 @@ static int start_nic(struct s2io_nic *nic)  	XENA_dev_config_t __iomem *bar0 = nic->bar0;  	struct net_device *dev = nic->dev;  	register u64 val64 = 0; -	u16 interruptible, i; -	u16 subid; +	u16 interruptible; +	u16 subid, i;  	mac_info_t *mac_control;  	struct config_param *config; @@ -1335,10 +1848,12 @@ static int start_nic(struct s2io_nic *nic)  	/*  PRC Initialization and configuration */  	for (i = 0; i < config->rx_ring_num; i++) { -		writeq((u64) nic->rx_blocks[i][0].block_dma_addr, +		writeq((u64) mac_control->rings[i].rx_blocks[0].block_dma_addr,  		       &bar0->prc_rxd0_n[i]);  		val64 = readq(&bar0->prc_ctrl_n[i]); +		if (nic->config.bimodal) +			val64 |= PRC_CTRL_BIMODAL_INTERRUPT;  #ifndef CONFIG_2BUFF_MODE  		val64 |= PRC_CTRL_RC_ENABLED;  #else @@ -1354,7 +1869,7 @@ static int start_nic(struct s2io_nic *nic)  	writeq(val64, &bar0->rx_pa_cfg);  #endif -	/*  +	/*  	 * Enabling MC-RLDRAM. After enabling the device, we timeout  	 * for around 100ms, which is approximately the time required  	 * for the device to be ready for operation. @@ -1364,27 +1879,27 @@ static int start_nic(struct s2io_nic *nic)  	SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_mrs, UF);  	val64 = readq(&bar0->mc_rldram_mrs); -	msleep(100);			/* Delay by around 100 ms. */ +	msleep(100);	/* Delay by around 100 ms. */  	/* Enabling ECC Protection. */  	val64 = readq(&bar0->adapter_control);  	val64 &= ~ADAPTER_ECC_EN;  	writeq(val64, &bar0->adapter_control); -	/*  -	 * Clearing any possible Link state change interrupts that  +	/* +	 * Clearing any possible Link state change interrupts that  	 * could have popped up just before Enabling the card.  	 */  	val64 = readq(&bar0->mac_rmac_err_reg);  	if (val64)  		writeq(val64, &bar0->mac_rmac_err_reg); -	/*  -	 * Verify if the device is ready to be enabled, if so enable  +	/* +	 * Verify if the device is ready to be enabled, if so enable  	 * it.  	 */  	val64 = readq(&bar0->adapter_status); -	if (!verify_xena_quiescence(val64, nic->device_enabled_once)) { +	if (!verify_xena_quiescence(nic, val64, nic->device_enabled_once)) {  		DBG_PRINT(ERR_DBG, "%s: device is not ready, ", dev->name);  		DBG_PRINT(ERR_DBG, "Adapter status reads: 0x%llx\n",  			  (unsigned long long) val64); @@ -1392,16 +1907,18 @@ static int start_nic(struct s2io_nic *nic)  	}  	/*  Enable select interrupts */ -	interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR | -	    RX_MAC_INTR; +	interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR; +	interruptible |= TX_PIC_INTR | RX_PIC_INTR; +	interruptible |= TX_MAC_INTR | RX_MAC_INTR; +  	en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS); -	/*  +	/*  	 * With some switches, link might be already up at this point. -	 * Because of this weird behavior, when we enable laser,  -	 * we may not get link. We need to handle this. We cannot  -	 * figure out which switch is misbehaving. So we are forced to  -	 * make a global change.  +	 * Because of this weird behavior, when we enable laser, +	 * we may not get link. We need to handle this. We cannot +	 * figure out which switch is misbehaving. So we are forced to +	 * make a global change.  	 */  	/* Enabling Laser. */ @@ -1411,44 +1928,30 @@ static int start_nic(struct s2io_nic *nic)  	/* SXE-002: Initialize link and activity LED */  	subid = nic->pdev->subsystem_device; -	if ((subid & 0xFF) >= 0x07) { +	if (((subid & 0xFF) >= 0x07) && +	    (nic->device_type == XFRAME_I_DEVICE)) {  		val64 = readq(&bar0->gpio_control);  		val64 |= 0x0000800000000000ULL;  		writeq(val64, &bar0->gpio_control);  		val64 = 0x0411040400000000ULL; -		writeq(val64, (void __iomem *) bar0 + 0x2700); +		writeq(val64, (void __iomem *) ((u8 *) bar0 + 0x2700));  	} -	/*  -	 * Don't see link state interrupts on certain switches, so  +	/* +	 * Don't see link state interrupts on certain switches, so  	 * directly scheduling a link state task from here.  	 */  	schedule_work(&nic->set_link_task); -	/*  -	 * Here we are performing soft reset on XGXS to  -	 * force link down. Since link is already up, we will get -	 * link state change interrupt after this reset -	 */ -	SPECIAL_REG_WRITE(0x80010515001E0000ULL, &bar0->dtx_control, UF); -	val64 = readq(&bar0->dtx_control); -	udelay(50); -	SPECIAL_REG_WRITE(0x80010515001E00E0ULL, &bar0->dtx_control, UF); -	val64 = readq(&bar0->dtx_control); -	udelay(50); -	SPECIAL_REG_WRITE(0x80070515001F00E4ULL, &bar0->dtx_control, UF); -	val64 = readq(&bar0->dtx_control); -	udelay(50); -  	return SUCCESS;  } -/**  - *  free_tx_buffers - Free all queued Tx buffers  +/** + *  free_tx_buffers - Free all queued Tx buffers   *  @nic : device private variable. - *  Description:  + *  Description:   *  Free all queued Tx buffers. - *  Return Value: void  + *  Return Value: void  */  static void free_tx_buffers(struct s2io_nic *nic) @@ -1459,39 +1962,61 @@ static void free_tx_buffers(struct s2io_nic *nic)  	int i, j;  	mac_info_t *mac_control;  	struct config_param *config; -	int cnt = 0; +	int cnt = 0, frg_cnt;  	mac_control = &nic->mac_control;  	config = &nic->config;  	for (i = 0; i < config->tx_fifo_num; i++) {  		for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) { -			txdp = (TxD_t *) nic->list_info[i][j]. +			txdp = (TxD_t *) mac_control->fifos[i].list_info[j].  			    list_virt_addr;  			skb =  			    (struct sk_buff *) ((unsigned long) txdp->  						Host_Control);  			if (skb == NULL) { -				memset(txdp, 0, sizeof(TxD_t)); +				memset(txdp, 0, sizeof(TxD_t) * +				       config->max_txds);  				continue;  			} +			frg_cnt = skb_shinfo(skb)->nr_frags; +			pci_unmap_single(nic->pdev, (dma_addr_t) +					 txdp->Buffer_Pointer, +					 skb->len - skb->data_len, +					 PCI_DMA_TODEVICE); +			if (frg_cnt) { +				TxD_t *temp; +				temp = txdp; +				txdp++; +				for (j = 0; j < frg_cnt; j++, txdp++) { +					skb_frag_t *frag = +					    &skb_shinfo(skb)->frags[j]; +					pci_unmap_page(nic->pdev, +						       (dma_addr_t) +						       txdp-> +						       Buffer_Pointer, +						       frag->size, +						       PCI_DMA_TODEVICE); +				} +				txdp = temp; +			}  			dev_kfree_skb(skb); -			memset(txdp, 0, sizeof(TxD_t)); +			memset(txdp, 0, sizeof(TxD_t) * config->max_txds);  			cnt++;  		}  		DBG_PRINT(INTR_DBG,  			  "%s:forcibly freeing %d skbs on FIFO%d\n",  			  dev->name, cnt, i); -		mac_control->tx_curr_get_info[i].offset = 0; -		mac_control->tx_curr_put_info[i].offset = 0; +		mac_control->fifos[i].tx_curr_get_info.offset = 0; +		mac_control->fifos[i].tx_curr_put_info.offset = 0;  	}  } -/**   - *   stop_nic -  To stop the nic   +/** + *   stop_nic -  To stop the nic   *   @nic ; device private variable. - *   Description:  - *   This function does exactly the opposite of what the start_nic()  + *   Description: + *   This function does exactly the opposite of what the start_nic()   *   function does. This function is called to stop the device.   *   Return Value:   *   void. @@ -1509,8 +2034,9 @@ static void stop_nic(struct s2io_nic *nic)  	config = &nic->config;  	/*  Disable all interrupts */ -	interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR | TX_MAC_INTR | -	    RX_MAC_INTR; +	interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR; +	interruptible |= TX_PIC_INTR | RX_PIC_INTR; +	interruptible |= TX_MAC_INTR | RX_MAC_INTR;  	en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);  	/*  Disable PRCs */ @@ -1521,11 +2047,11 @@ static void stop_nic(struct s2io_nic *nic)  	}  } -/**   - *  fill_rx_buffers - Allocates the Rx side skbs  +/** + *  fill_rx_buffers - Allocates the Rx side skbs   *  @nic:  device private variable - *  @ring_no: ring number  - *  Description:  + *  @ring_no: ring number + *  Description:   *  The function allocates Rx side skbs and puts the physical   *  address of these buffers into the RxD buffer pointers, so that the NIC   *  can DMA the received frame into these locations. @@ -1533,8 +2059,8 @@ static void stop_nic(struct s2io_nic *nic)   *  1. single buffer,   *  2. three buffer and   *  3. Five buffer modes. - *  Each mode defines how many fragments the received frame will be split  - *  up into by the NIC. The frame is split into L3 header, L4 Header,  + *  Each mode defines how many fragments the received frame will be split + *  up into by the NIC. The frame is split into L3 header, L4 Header,   *  L4 payload in three buffer mode and in 5 buffer mode, L4 payload itself   *  is split into 3 fragments. As of now only single buffer mode is   *  supported. @@ -1542,7 +2068,7 @@ static void stop_nic(struct s2io_nic *nic)   *  SUCCESS on success or an appropriate -ve value on failure.   */ -static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) +int fill_rx_buffers(struct s2io_nic *nic, int ring_no)  {  	struct net_device *dev = nic->dev;  	struct sk_buff *skb; @@ -1550,34 +2076,35 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)  	int off, off1, size, block_no, block_no1;  	int offset, offset1;  	u32 alloc_tab = 0; -	u32 alloc_cnt = nic->pkt_cnt[ring_no] - -	    atomic_read(&nic->rx_bufs_left[ring_no]); +	u32 alloc_cnt;  	mac_info_t *mac_control;  	struct config_param *config;  #ifdef CONFIG_2BUFF_MODE  	RxD_t *rxdpnext;  	int nextblk; -	unsigned long tmp; +	u64 tmp;  	buffAdd_t *ba;  	dma_addr_t rxdpphys;  #endif  #ifndef CONFIG_S2IO_NAPI  	unsigned long flags;  #endif +	RxD_t *first_rxdp = NULL;  	mac_control = &nic->mac_control;  	config = &nic->config; - +	alloc_cnt = mac_control->rings[ring_no].pkt_cnt - +	    atomic_read(&nic->rx_bufs_left[ring_no]);  	size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE +  	    HEADER_802_2_SIZE + HEADER_SNAP_SIZE;  	while (alloc_tab < alloc_cnt) { -		block_no = mac_control->rx_curr_put_info[ring_no]. +		block_no = mac_control->rings[ring_no].rx_curr_put_info.  		    block_index; -		block_no1 = mac_control->rx_curr_get_info[ring_no]. +		block_no1 = mac_control->rings[ring_no].rx_curr_get_info.  		    block_index; -		off = mac_control->rx_curr_put_info[ring_no].offset; -		off1 = mac_control->rx_curr_get_info[ring_no].offset; +		off = mac_control->rings[ring_no].rx_curr_put_info.offset; +		off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;  #ifndef CONFIG_2BUFF_MODE  		offset = block_no * (MAX_RXDS_PER_BLOCK + 1) + off;  		offset1 = block_no1 * (MAX_RXDS_PER_BLOCK + 1) + off1; @@ -1586,7 +2113,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)  		offset1 = block_no1 * (MAX_RXDS_PER_BLOCK) + off1;  #endif -		rxdp = nic->rx_blocks[ring_no][block_no]. +		rxdp = mac_control->rings[ring_no].rx_blocks[block_no].  		    block_virt_addr + off;  		if ((offset == offset1) && (rxdp->Host_Control)) {  			DBG_PRINT(INTR_DBG, "%s: Get and Put", dev->name); @@ -1595,15 +2122,15 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)  		}  #ifndef	CONFIG_2BUFF_MODE  		if (rxdp->Control_1 == END_OF_BLOCK) { -			mac_control->rx_curr_put_info[ring_no]. +			mac_control->rings[ring_no].rx_curr_put_info.  			    block_index++; -			mac_control->rx_curr_put_info[ring_no]. -			    block_index %= nic->block_count[ring_no]; -			block_no = mac_control->rx_curr_put_info -			    [ring_no].block_index; +			mac_control->rings[ring_no].rx_curr_put_info. +			    block_index %= mac_control->rings[ring_no].block_count; +			block_no = mac_control->rings[ring_no].rx_curr_put_info. +				block_index;  			off++;  			off %= (MAX_RXDS_PER_BLOCK + 1); -			mac_control->rx_curr_put_info[ring_no].offset = +			mac_control->rings[ring_no].rx_curr_put_info.offset =  			    off;  			rxdp = (RxD_t *) ((unsigned long) rxdp->Control_2);  			DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n", @@ -1611,30 +2138,30 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)  		}  #ifndef CONFIG_S2IO_NAPI  		spin_lock_irqsave(&nic->put_lock, flags); -		nic->put_pos[ring_no] = +		mac_control->rings[ring_no].put_pos =  		    (block_no * (MAX_RXDS_PER_BLOCK + 1)) + off;  		spin_unlock_irqrestore(&nic->put_lock, flags);  #endif  #else  		if (rxdp->Host_Control == END_OF_BLOCK) { -			mac_control->rx_curr_put_info[ring_no]. +			mac_control->rings[ring_no].rx_curr_put_info.  			    block_index++; -			mac_control->rx_curr_put_info[ring_no]. -			    block_index %= nic->block_count[ring_no]; -			block_no = mac_control->rx_curr_put_info -			    [ring_no].block_index; +			mac_control->rings[ring_no].rx_curr_put_info.block_index +			    %= mac_control->rings[ring_no].block_count; +			block_no = mac_control->rings[ring_no].rx_curr_put_info +			    .block_index;  			off = 0;  			DBG_PRINT(INTR_DBG, "%s: block%d at: 0x%llx\n",  				  dev->name, block_no,  				  (unsigned long long) rxdp->Control_1); -			mac_control->rx_curr_put_info[ring_no].offset = +			mac_control->rings[ring_no].rx_curr_put_info.offset =  			    off; -			rxdp = nic->rx_blocks[ring_no][block_no]. +			rxdp = mac_control->rings[ring_no].rx_blocks[block_no].  			    block_virt_addr;  		}  #ifndef CONFIG_S2IO_NAPI  		spin_lock_irqsave(&nic->put_lock, flags); -		nic->put_pos[ring_no] = (block_no * +		mac_control->rings[ring_no].put_pos = (block_no *  					 (MAX_RXDS_PER_BLOCK + 1)) + off;  		spin_unlock_irqrestore(&nic->put_lock, flags);  #endif @@ -1646,27 +2173,27 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)  		if (rxdp->Control_2 & BIT(0))  #endif  		{ -			mac_control->rx_curr_put_info[ring_no]. +			mac_control->rings[ring_no].rx_curr_put_info.  			    offset = off;  			goto end;  		}  #ifdef	CONFIG_2BUFF_MODE -		/*  -		 * RxDs Spanning cache lines will be replenished only  -		 * if the succeeding RxD is also owned by Host. It  -		 * will always be the ((8*i)+3) and ((8*i)+6)  -		 * descriptors for the 48 byte descriptor. The offending  +		/* +		 * RxDs Spanning cache lines will be replenished only +		 * if the succeeding RxD is also owned by Host. It +		 * will always be the ((8*i)+3) and ((8*i)+6) +		 * descriptors for the 48 byte descriptor. The offending  		 * decsriptor is of-course the 3rd descriptor.  		 */ -		rxdpphys = nic->rx_blocks[ring_no][block_no]. +		rxdpphys = mac_control->rings[ring_no].rx_blocks[block_no].  		    block_dma_addr + (off * sizeof(RxD_t));  		if (((u64) (rxdpphys)) % 128 > 80) { -			rxdpnext = nic->rx_blocks[ring_no][block_no]. +			rxdpnext = mac_control->rings[ring_no].rx_blocks[block_no].  			    block_virt_addr + (off + 1);  			if (rxdpnext->Host_Control == END_OF_BLOCK) {  				nextblk = (block_no + 1) % -				    (nic->block_count[ring_no]); -				rxdpnext = nic->rx_blocks[ring_no] +				    (mac_control->rings[ring_no].block_count); +				rxdpnext = mac_control->rings[ring_no].rx_blocks  				    [nextblk].block_virt_addr;  			}  			if (rxdpnext->Control_2 & BIT(0)) @@ -1682,6 +2209,10 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)  		if (!skb) {  			DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name);  			DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n"); +			if (first_rxdp) { +				wmb(); +				first_rxdp->Control_1 |= RXD_OWN_XENA; +			}  			return -ENOMEM;  		}  #ifndef	CONFIG_2BUFF_MODE @@ -1692,12 +2223,13 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)  		rxdp->Control_2 &= (~MASK_BUFFER0_SIZE);  		rxdp->Control_2 |= SET_BUFFER0_SIZE(size);  		rxdp->Host_Control = (unsigned long) (skb); -		rxdp->Control_1 |= RXD_OWN_XENA; +		if (alloc_tab & ((1 << rxsync_frequency) - 1)) +			rxdp->Control_1 |= RXD_OWN_XENA;  		off++;  		off %= (MAX_RXDS_PER_BLOCK + 1); -		mac_control->rx_curr_put_info[ring_no].offset = off; +		mac_control->rings[ring_no].rx_curr_put_info.offset = off;  #else -		ba = &nic->ba[ring_no][block_no][off]; +		ba = &mac_control->rings[ring_no].ba[block_no][off];  		skb_reserve(skb, BUF0_LEN);  		tmp = ((unsigned long) skb->data & ALIGN_SIZE);  		if (tmp) @@ -1719,22 +2251,41 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)  		rxdp->Control_2 |= SET_BUFFER1_SIZE(1);	/* dummy. */  		rxdp->Control_2 |= BIT(0);	/* Set Buffer_Empty bit. */  		rxdp->Host_Control = (u64) ((unsigned long) (skb)); -		rxdp->Control_1 |= RXD_OWN_XENA; +		if (alloc_tab & ((1 << rxsync_frequency) - 1)) +			rxdp->Control_1 |= RXD_OWN_XENA;  		off++; -		mac_control->rx_curr_put_info[ring_no].offset = off; +		mac_control->rings[ring_no].rx_curr_put_info.offset = off;  #endif +		rxdp->Control_2 |= SET_RXD_MARKER; + +		if (!(alloc_tab & ((1 << rxsync_frequency) - 1))) { +			if (first_rxdp) { +				wmb(); +				first_rxdp->Control_1 |= RXD_OWN_XENA; +			} +			first_rxdp = rxdp; +		}  		atomic_inc(&nic->rx_bufs_left[ring_no]);  		alloc_tab++;  	}        end: +	/* Transfer ownership of first descriptor to adapter just before +	 * exiting. Before that, use memory barrier so that ownership +	 * and other fields are seen by adapter correctly. +	 */ +	if (first_rxdp) { +		wmb(); +		first_rxdp->Control_1 |= RXD_OWN_XENA; +	} +  	return SUCCESS;  }  /** - *  free_rx_buffers - Frees all Rx buffers    + *  free_rx_buffers - Frees all Rx buffers   *  @sp: device private variable. - *  Description:  + *  Description:   *  This function will free all Rx buffers allocated by host.   *  Return Value:   *  NONE. @@ -1758,7 +2309,8 @@ static void free_rx_buffers(struct s2io_nic *sp)  	for (i = 0; i < config->rx_ring_num; i++) {  		for (j = 0, blk = 0; j < config->rx_cfg[i].num_rxd; j++) {  			off = j % (MAX_RXDS_PER_BLOCK + 1); -			rxdp = sp->rx_blocks[i][blk].block_virt_addr + off; +			rxdp = mac_control->rings[i].rx_blocks[blk]. +				block_virt_addr + off;  #ifndef CONFIG_2BUFF_MODE  			if (rxdp->Control_1 == END_OF_BLOCK) { @@ -1793,7 +2345,7 @@ static void free_rx_buffers(struct s2io_nic *sp)  						 HEADER_SNAP_SIZE,  						 PCI_DMA_FROMDEVICE);  #else -				ba = &sp->ba[i][blk][off]; +				ba = &mac_control->rings[i].ba[blk][off];  				pci_unmap_single(sp->pdev, (dma_addr_t)  						 rxdp->Buffer0_ptr,  						 BUF0_LEN, @@ -1813,10 +2365,10 @@ static void free_rx_buffers(struct s2io_nic *sp)  			}  			memset(rxdp, 0, sizeof(RxD_t));  		} -		mac_control->rx_curr_put_info[i].block_index = 0; -		mac_control->rx_curr_get_info[i].block_index = 0; -		mac_control->rx_curr_put_info[i].offset = 0; -		mac_control->rx_curr_get_info[i].offset = 0; +		mac_control->rings[i].rx_curr_put_info.block_index = 0; +		mac_control->rings[i].rx_curr_get_info.block_index = 0; +		mac_control->rings[i].rx_curr_put_info.offset = 0; +		mac_control->rings[i].rx_curr_get_info.offset = 0;  		atomic_set(&sp->rx_bufs_left[i], 0);  		DBG_PRINT(INIT_DBG, "%s:Freed 0x%x Rx Buffers on ring%d\n",  			  dev->name, buf_cnt, i); @@ -1826,7 +2378,7 @@ static void free_rx_buffers(struct s2io_nic *sp)  /**   * s2io_poll - Rx interrupt handler for NAPI support   * @dev : pointer to the device structure. - * @budget : The number of packets that were budgeted to be processed  + * @budget : The number of packets that were budgeted to be processed   * during  one pass through the 'Poll" function.   * Description:   * Comes into picture only if NAPI support has been incorporated. It does @@ -1836,160 +2388,36 @@ static void free_rx_buffers(struct s2io_nic *sp)   * 0 on success and 1 if there are No Rx packets to be processed.   */ -#ifdef CONFIG_S2IO_NAPI +#if defined(CONFIG_S2IO_NAPI)  static int s2io_poll(struct net_device *dev, int *budget)  {  	nic_t *nic = dev->priv; -	XENA_dev_config_t __iomem *bar0 = nic->bar0; -	int pkts_to_process = *budget, pkt_cnt = 0; -	register u64 val64 = 0; -	rx_curr_get_info_t get_info, put_info; -	int i, get_block, put_block, get_offset, put_offset, ring_bufs; -#ifndef CONFIG_2BUFF_MODE -	u16 val16, cksum; -#endif -	struct sk_buff *skb; -	RxD_t *rxdp; +	int pkt_cnt = 0, org_pkts_to_process;  	mac_info_t *mac_control;  	struct config_param *config; -#ifdef CONFIG_2BUFF_MODE -	buffAdd_t *ba; -#endif +	XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; +	u64 val64; +	int i; +	atomic_inc(&nic->isr_cnt);  	mac_control = &nic->mac_control;  	config = &nic->config; -	if (pkts_to_process > dev->quota) -		pkts_to_process = dev->quota; +	nic->pkts_to_process = *budget; +	if (nic->pkts_to_process > dev->quota) +		nic->pkts_to_process = dev->quota; +	org_pkts_to_process = nic->pkts_to_process;  	val64 = readq(&bar0->rx_traffic_int);  	writeq(val64, &bar0->rx_traffic_int);  	for (i = 0; i < config->rx_ring_num; i++) { -		get_info = mac_control->rx_curr_get_info[i]; -		get_block = get_info.block_index; -		put_info = mac_control->rx_curr_put_info[i]; -		put_block = put_info.block_index; -		ring_bufs = config->rx_cfg[i].num_rxd; -		rxdp = nic->rx_blocks[i][get_block].block_virt_addr + -		    get_info.offset; -#ifndef	CONFIG_2BUFF_MODE -		get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) + -		    get_info.offset; -		put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) + -		    put_info.offset; -		while ((!(rxdp->Control_1 & RXD_OWN_XENA)) && -		       (((get_offset + 1) % ring_bufs) != put_offset)) { -			if (--pkts_to_process < 0) { -				goto no_rx; -			} -			if (rxdp->Control_1 == END_OF_BLOCK) { -				rxdp = -				    (RxD_t *) ((unsigned long) rxdp-> -					       Control_2); -				get_info.offset++; -				get_info.offset %= -				    (MAX_RXDS_PER_BLOCK + 1); -				get_block++; -				get_block %= nic->block_count[i]; -				mac_control->rx_curr_get_info[i]. -				    offset = get_info.offset; -				mac_control->rx_curr_get_info[i]. -				    block_index = get_block; -				continue; -			} -			get_offset = -			    (get_block * (MAX_RXDS_PER_BLOCK + 1)) + -			    get_info.offset; -			skb = -			    (struct sk_buff *) ((unsigned long) rxdp-> -						Host_Control); -			if (skb == NULL) { -				DBG_PRINT(ERR_DBG, "%s: The skb is ", -					  dev->name); -				DBG_PRINT(ERR_DBG, "Null in Rx Intr\n"); -				goto no_rx; -			} -			val64 = RXD_GET_BUFFER0_SIZE(rxdp->Control_2); -			val16 = (u16) (val64 >> 48); -			cksum = RXD_GET_L4_CKSUM(rxdp->Control_1); -			pci_unmap_single(nic->pdev, (dma_addr_t) -					 rxdp->Buffer0_ptr, -					 dev->mtu + -					 HEADER_ETHERNET_II_802_3_SIZE + -					 HEADER_802_2_SIZE + -					 HEADER_SNAP_SIZE, -					 PCI_DMA_FROMDEVICE); -			rx_osm_handler(nic, val16, rxdp, i); -			pkt_cnt++; -			get_info.offset++; -			get_info.offset %= (MAX_RXDS_PER_BLOCK + 1); -			rxdp = -			    nic->rx_blocks[i][get_block].block_virt_addr + -			    get_info.offset; -			mac_control->rx_curr_get_info[i].offset = -			    get_info.offset; +		rx_intr_handler(&mac_control->rings[i]); +		pkt_cnt = org_pkts_to_process - nic->pkts_to_process; +		if (!nic->pkts_to_process) { +			/* Quota for the current iteration has been met */ +			goto no_rx;  		} -#else -		get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) + -		    get_info.offset; -		put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) + -		    put_info.offset; -		while (((!(rxdp->Control_1 & RXD_OWN_XENA)) && -			!(rxdp->Control_2 & BIT(0))) && -		       (((get_offset + 1) % ring_bufs) != put_offset)) { -			if (--pkts_to_process < 0) { -				goto no_rx; -			} -			skb = (struct sk_buff *) ((unsigned long) -						  rxdp->Host_Control); -			if (skb == NULL) { -				DBG_PRINT(ERR_DBG, "%s: The skb is ", -					  dev->name); -				DBG_PRINT(ERR_DBG, "Null in Rx Intr\n"); -				goto no_rx; -			} - -			pci_unmap_single(nic->pdev, (dma_addr_t) -					 rxdp->Buffer0_ptr, -					 BUF0_LEN, PCI_DMA_FROMDEVICE); -			pci_unmap_single(nic->pdev, (dma_addr_t) -					 rxdp->Buffer1_ptr, -					 BUF1_LEN, PCI_DMA_FROMDEVICE); -			pci_unmap_single(nic->pdev, (dma_addr_t) -					 rxdp->Buffer2_ptr, -					 dev->mtu + BUF0_LEN + 4, -					 PCI_DMA_FROMDEVICE); -			ba = &nic->ba[i][get_block][get_info.offset]; - -			rx_osm_handler(nic, rxdp, i, ba); - -			get_info.offset++; -			mac_control->rx_curr_get_info[i].offset = -			    get_info.offset; -			rxdp = -			    nic->rx_blocks[i][get_block].block_virt_addr + -			    get_info.offset; - -			if (get_info.offset && -			    (!(get_info.offset % MAX_RXDS_PER_BLOCK))) { -				get_info.offset = 0; -				mac_control->rx_curr_get_info[i]. -				    offset = get_info.offset; -				get_block++; -				get_block %= nic->block_count[i]; -				mac_control->rx_curr_get_info[i]. -				    block_index = get_block; -				rxdp = -				    nic->rx_blocks[i][get_block]. -				    block_virt_addr; -			} -			get_offset = -			    (get_block * (MAX_RXDS_PER_BLOCK + 1)) + -			    get_info.offset; -			pkt_cnt++; -		} -#endif  	}  	if (!pkt_cnt)  		pkt_cnt = 1; @@ -2007,9 +2435,10 @@ static int s2io_poll(struct net_device *dev, int *budget)  	}  	/* Re enable the Rx interrupts. */  	en_dis_able_nic_intrs(nic, RX_TRAFFIC_INTR, ENABLE_INTRS); +	atomic_dec(&nic->isr_cnt);  	return 0; -      no_rx: +no_rx:  	dev->quota -= pkt_cnt;  	*budget -= pkt_cnt; @@ -2020,279 +2449,204 @@ static int s2io_poll(struct net_device *dev, int *budget)  			break;  		}  	} +	atomic_dec(&nic->isr_cnt);  	return 1;  } -#else -/**   +#endif + +/**   *  rx_intr_handler - Rx interrupt handler   *  @nic: device private variable. - *  Description:  - *  If the interrupt is because of a received frame or if the  + *  Description: + *  If the interrupt is because of a received frame or if the   *  receive ring contains fresh as yet un-processed frames,this function is - *  called. It picks out the RxD at which place the last Rx processing had  - *  stopped and sends the skb to the OSM's Rx handler and then increments  + *  called. It picks out the RxD at which place the last Rx processing had + *  stopped and sends the skb to the OSM's Rx handler and then increments   *  the offset.   *  Return Value:   *  NONE.   */ - -static void rx_intr_handler(struct s2io_nic *nic) +static void rx_intr_handler(ring_info_t *ring_data)  { +	nic_t *nic = ring_data->nic;  	struct net_device *dev = (struct net_device *) nic->dev; -	XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; +	int get_block, get_offset, put_block, put_offset, ring_bufs;  	rx_curr_get_info_t get_info, put_info;  	RxD_t *rxdp;  	struct sk_buff *skb; -#ifndef CONFIG_2BUFF_MODE -	u16 val16, cksum; -#endif -	register u64 val64 = 0; -	int get_block, get_offset, put_block, put_offset, ring_bufs; -	int i, pkt_cnt = 0; -	mac_info_t *mac_control; -	struct config_param *config; -#ifdef CONFIG_2BUFF_MODE -	buffAdd_t *ba; +#ifndef CONFIG_S2IO_NAPI +	int pkt_cnt = 0;  #endif +	spin_lock(&nic->rx_lock); +	if (atomic_read(&nic->card_state) == CARD_DOWN) { +		DBG_PRINT(ERR_DBG, "%s: %s going down for reset\n", +			  __FUNCTION__, dev->name); +		spin_unlock(&nic->rx_lock); +	} -	mac_control = &nic->mac_control; -	config = &nic->config; - -	/*  -	 * rx_traffic_int reg is an R1 register, hence we read and write back  -	 * the samevalue in the register to clear it. -	 */ -	val64 = readq(&bar0->rx_traffic_int); -	writeq(val64, &bar0->rx_traffic_int); - -	for (i = 0; i < config->rx_ring_num; i++) { -		get_info = mac_control->rx_curr_get_info[i]; -		get_block = get_info.block_index; -		put_info = mac_control->rx_curr_put_info[i]; -		put_block = put_info.block_index; -		ring_bufs = config->rx_cfg[i].num_rxd; -		rxdp = nic->rx_blocks[i][get_block].block_virt_addr + -		    get_info.offset; -#ifndef	CONFIG_2BUFF_MODE -		get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) + +	get_info = ring_data->rx_curr_get_info; +	get_block = get_info.block_index; +	put_info = ring_data->rx_curr_put_info; +	put_block = put_info.block_index; +	ring_bufs = get_info.ring_len+1; +	rxdp = ring_data->rx_blocks[get_block].block_virt_addr +  		    get_info.offset; -		spin_lock(&nic->put_lock); -		put_offset = nic->put_pos[i]; -		spin_unlock(&nic->put_lock); -		while ((!(rxdp->Control_1 & RXD_OWN_XENA)) && -		       (((get_offset + 1) % ring_bufs) != put_offset)) { -			if (rxdp->Control_1 == END_OF_BLOCK) { -				rxdp = (RxD_t *) ((unsigned long) -						  rxdp->Control_2); -				get_info.offset++; -				get_info.offset %= -				    (MAX_RXDS_PER_BLOCK + 1); -				get_block++; -				get_block %= nic->block_count[i]; -				mac_control->rx_curr_get_info[i]. -				    offset = get_info.offset; -				mac_control->rx_curr_get_info[i]. -				    block_index = get_block; -				continue; -			} -			get_offset = -			    (get_block * (MAX_RXDS_PER_BLOCK + 1)) + -			    get_info.offset; -			skb = (struct sk_buff *) ((unsigned long) -						  rxdp->Host_Control); -			if (skb == NULL) { -				DBG_PRINT(ERR_DBG, "%s: The skb is ", -					  dev->name); -				DBG_PRINT(ERR_DBG, "Null in Rx Intr\n"); -				return; -			} -			val64 = RXD_GET_BUFFER0_SIZE(rxdp->Control_2); -			val16 = (u16) (val64 >> 48); -			cksum = RXD_GET_L4_CKSUM(rxdp->Control_1); -			pci_unmap_single(nic->pdev, (dma_addr_t) -					 rxdp->Buffer0_ptr, -					 dev->mtu + -					 HEADER_ETHERNET_II_802_3_SIZE + -					 HEADER_802_2_SIZE + -					 HEADER_SNAP_SIZE, -					 PCI_DMA_FROMDEVICE); -			rx_osm_handler(nic, val16, rxdp, i); -			get_info.offset++; -			get_info.offset %= (MAX_RXDS_PER_BLOCK + 1); -			rxdp = -			    nic->rx_blocks[i][get_block].block_virt_addr + -			    get_info.offset; -			mac_control->rx_curr_get_info[i].offset = -			    get_info.offset; -			pkt_cnt++; -			if ((indicate_max_pkts) -			    && (pkt_cnt > indicate_max_pkts)) -				break; +	get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) + +		get_info.offset; +#ifndef CONFIG_S2IO_NAPI +	spin_lock(&nic->put_lock); +	put_offset = ring_data->put_pos; +	spin_unlock(&nic->put_lock); +#else +	put_offset = (put_block * (MAX_RXDS_PER_BLOCK + 1)) + +		put_info.offset; +#endif +	while (RXD_IS_UP2DT(rxdp) && +	       (((get_offset + 1) % ring_bufs) != put_offset)) { +		skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control); +		if (skb == NULL) { +			DBG_PRINT(ERR_DBG, "%s: The skb is ", +				  dev->name); +			DBG_PRINT(ERR_DBG, "Null in Rx Intr\n"); +			spin_unlock(&nic->rx_lock); +			return;  		} +#ifndef CONFIG_2BUFF_MODE +		pci_unmap_single(nic->pdev, (dma_addr_t) +				 rxdp->Buffer0_ptr, +				 dev->mtu + +				 HEADER_ETHERNET_II_802_3_SIZE + +				 HEADER_802_2_SIZE + +				 HEADER_SNAP_SIZE, +				 PCI_DMA_FROMDEVICE);  #else -		get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) + +		pci_unmap_single(nic->pdev, (dma_addr_t) +				 rxdp->Buffer0_ptr, +				 BUF0_LEN, PCI_DMA_FROMDEVICE); +		pci_unmap_single(nic->pdev, (dma_addr_t) +				 rxdp->Buffer1_ptr, +				 BUF1_LEN, PCI_DMA_FROMDEVICE); +		pci_unmap_single(nic->pdev, (dma_addr_t) +				 rxdp->Buffer2_ptr, +				 dev->mtu + BUF0_LEN + 4, +				 PCI_DMA_FROMDEVICE); +#endif +		rx_osm_handler(ring_data, rxdp); +		get_info.offset++; +		ring_data->rx_curr_get_info.offset =  		    get_info.offset; -		spin_lock(&nic->put_lock); -		put_offset = nic->put_pos[i]; -		spin_unlock(&nic->put_lock); -		while (((!(rxdp->Control_1 & RXD_OWN_XENA)) && -			!(rxdp->Control_2 & BIT(0))) && -		       (((get_offset + 1) % ring_bufs) != put_offset)) { -			skb = (struct sk_buff *) ((unsigned long) -						  rxdp->Host_Control); -			if (skb == NULL) { -				DBG_PRINT(ERR_DBG, "%s: The skb is ", -					  dev->name); -				DBG_PRINT(ERR_DBG, "Null in Rx Intr\n"); -				return; -			} - -			pci_unmap_single(nic->pdev, (dma_addr_t) -					 rxdp->Buffer0_ptr, -					 BUF0_LEN, PCI_DMA_FROMDEVICE); -			pci_unmap_single(nic->pdev, (dma_addr_t) -					 rxdp->Buffer1_ptr, -					 BUF1_LEN, PCI_DMA_FROMDEVICE); -			pci_unmap_single(nic->pdev, (dma_addr_t) -					 rxdp->Buffer2_ptr, -					 dev->mtu + BUF0_LEN + 4, -					 PCI_DMA_FROMDEVICE); -			ba = &nic->ba[i][get_block][get_info.offset]; - -			rx_osm_handler(nic, rxdp, i, ba); - -			get_info.offset++; -			mac_control->rx_curr_get_info[i].offset = -			    get_info.offset; -			rxdp = -			    nic->rx_blocks[i][get_block].block_virt_addr + -			    get_info.offset; +		rxdp = ring_data->rx_blocks[get_block].block_virt_addr + +		    get_info.offset; +		if (get_info.offset && +		    (!(get_info.offset % MAX_RXDS_PER_BLOCK))) { +			get_info.offset = 0; +			ring_data->rx_curr_get_info.offset +			    = get_info.offset; +			get_block++; +			get_block %= ring_data->block_count; +			ring_data->rx_curr_get_info.block_index +			    = get_block; +			rxdp = ring_data->rx_blocks[get_block].block_virt_addr; +		} -			if (get_info.offset && -			    (!(get_info.offset % MAX_RXDS_PER_BLOCK))) { -				get_info.offset = 0; -				mac_control->rx_curr_get_info[i]. -				    offset = get_info.offset; -				get_block++; -				get_block %= nic->block_count[i]; -				mac_control->rx_curr_get_info[i]. -				    block_index = get_block; -				rxdp = -				    nic->rx_blocks[i][get_block]. -				    block_virt_addr; -			} -			get_offset = -			    (get_block * (MAX_RXDS_PER_BLOCK + 1)) + +		get_offset = (get_block * (MAX_RXDS_PER_BLOCK + 1)) +  			    get_info.offset; -			pkt_cnt++; -			if ((indicate_max_pkts) -			    && (pkt_cnt > indicate_max_pkts)) -				break; -		} -#endif +#ifdef CONFIG_S2IO_NAPI +		nic->pkts_to_process -= 1; +		if (!nic->pkts_to_process) +			break; +#else +		pkt_cnt++;  		if ((indicate_max_pkts) && (pkt_cnt > indicate_max_pkts))  			break; +#endif  	} +	spin_unlock(&nic->rx_lock);  } -#endif -/**   + +/**   *  tx_intr_handler - Transmit interrupt handler   *  @nic : device private variable - *  Description:  - *  If an interrupt was raised to indicate DMA complete of the  - *  Tx packet, this function is called. It identifies the last TxD  - *  whose buffer was freed and frees all skbs whose data have already  + *  Description: + *  If an interrupt was raised to indicate DMA complete of the + *  Tx packet, this function is called. It identifies the last TxD + *  whose buffer was freed and frees all skbs whose data have already   *  DMA'ed into the NICs internal memory.   *  Return Value:   *  NONE   */ -static void tx_intr_handler(struct s2io_nic *nic) +static void tx_intr_handler(fifo_info_t *fifo_data)  { -	XENA_dev_config_t __iomem *bar0 = nic->bar0; +	nic_t *nic = fifo_data->nic;  	struct net_device *dev = (struct net_device *) nic->dev;  	tx_curr_get_info_t get_info, put_info;  	struct sk_buff *skb;  	TxD_t *txdlp; -	register u64 val64 = 0; -	int i;  	u16 j, frg_cnt; -	mac_info_t *mac_control; -	struct config_param *config; -	mac_control = &nic->mac_control; -	config = &nic->config; - -	/*  -	 * tx_traffic_int reg is an R1 register, hence we read and write  -	 * back the samevalue in the register to clear it. -	 */ -	val64 = readq(&bar0->tx_traffic_int); -	writeq(val64, &bar0->tx_traffic_int); +	get_info = fifo_data->tx_curr_get_info; +	put_info = fifo_data->tx_curr_put_info; +	txdlp = (TxD_t *) fifo_data->list_info[get_info.offset]. +	    list_virt_addr; +	while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) && +	       (get_info.offset != put_info.offset) && +	       (txdlp->Host_Control)) { +		/* Check for TxD errors */ +		if (txdlp->Control_1 & TXD_T_CODE) { +			unsigned long long err; +			err = txdlp->Control_1 & TXD_T_CODE; +			DBG_PRINT(ERR_DBG, "***TxD error %llx\n", +				  err); +		} -	for (i = 0; i < config->tx_fifo_num; i++) { -		get_info = mac_control->tx_curr_get_info[i]; -		put_info = mac_control->tx_curr_put_info[i]; -		txdlp = (TxD_t *) nic->list_info[i][get_info.offset]. -		    list_virt_addr; -		while ((!(txdlp->Control_1 & TXD_LIST_OWN_XENA)) && -		       (get_info.offset != put_info.offset) && -		       (txdlp->Host_Control)) { -			/* Check for TxD errors */ -			if (txdlp->Control_1 & TXD_T_CODE) { -				unsigned long long err; -				err = txdlp->Control_1 & TXD_T_CODE; -				DBG_PRINT(ERR_DBG, "***TxD error %llx\n", -					  err); -			} +		skb = (struct sk_buff *) ((unsigned long) +				txdlp->Host_Control); +		if (skb == NULL) { +			DBG_PRINT(ERR_DBG, "%s: Null skb ", +			__FUNCTION__); +			DBG_PRINT(ERR_DBG, "in Tx Free Intr\n"); +			return; +		} -			skb = (struct sk_buff *) ((unsigned long) -						  txdlp->Host_Control); -			if (skb == NULL) { -				DBG_PRINT(ERR_DBG, "%s: Null skb ", -					  dev->name); -				DBG_PRINT(ERR_DBG, "in Tx Free Intr\n"); -				return; +		frg_cnt = skb_shinfo(skb)->nr_frags; +		nic->tx_pkt_count++; + +		pci_unmap_single(nic->pdev, (dma_addr_t) +				 txdlp->Buffer_Pointer, +				 skb->len - skb->data_len, +				 PCI_DMA_TODEVICE); +		if (frg_cnt) { +			TxD_t *temp; +			temp = txdlp; +			txdlp++; +			for (j = 0; j < frg_cnt; j++, txdlp++) { +				skb_frag_t *frag = +				    &skb_shinfo(skb)->frags[j]; +				if (!txdlp->Buffer_Pointer) +					break; +				pci_unmap_page(nic->pdev, +					       (dma_addr_t) +					       txdlp-> +					       Buffer_Pointer, +					       frag->size, +					       PCI_DMA_TODEVICE);  			} -			nic->tx_pkt_count++; - -			frg_cnt = skb_shinfo(skb)->nr_frags; - -			/*  For unfragmented skb */ -			pci_unmap_single(nic->pdev, (dma_addr_t) -					 txdlp->Buffer_Pointer, -					 skb->len - skb->data_len, -					 PCI_DMA_TODEVICE); -			if (frg_cnt) { -				TxD_t *temp = txdlp; -				txdlp++; -				for (j = 0; j < frg_cnt; j++, txdlp++) { -					skb_frag_t *frag = -					    &skb_shinfo(skb)->frags[j]; -					pci_unmap_page(nic->pdev, -						       (dma_addr_t) -						       txdlp-> -						       Buffer_Pointer, -						       frag->size, -						       PCI_DMA_TODEVICE); -				} -				txdlp = temp; -			} -			memset(txdlp, 0, -			       (sizeof(TxD_t) * config->max_txds)); - -			/* Updating the statistics block */ -			nic->stats.tx_packets++; -			nic->stats.tx_bytes += skb->len; -			dev_kfree_skb_irq(skb); - -			get_info.offset++; -			get_info.offset %= get_info.fifo_len + 1; -			txdlp = (TxD_t *) nic->list_info[i] -			    [get_info.offset].list_virt_addr; -			mac_control->tx_curr_get_info[i].offset = -			    get_info.offset; +			txdlp = temp;  		} +		memset(txdlp, 0, +		       (sizeof(TxD_t) * fifo_data->max_txds)); + +		/* Updating the statistics block */ +		nic->stats.tx_bytes += skb->len; +		dev_kfree_skb_irq(skb); + +		get_info.offset++; +		get_info.offset %= get_info.fifo_len + 1; +		txdlp = (TxD_t *) fifo_data->list_info +		    [get_info.offset].list_virt_addr; +		fifo_data->tx_curr_get_info.offset = +		    get_info.offset;  	}  	spin_lock(&nic->tx_lock); @@ -2301,13 +2655,13 @@ static void tx_intr_handler(struct s2io_nic *nic)  	spin_unlock(&nic->tx_lock);  } -/**   +/**   *  alarm_intr_handler - Alarm Interrrupt handler   *  @nic: device private variable - *  Description: If the interrupt was neither because of Rx packet or Tx  + *  Description: If the interrupt was neither because of Rx packet or Tx   *  complete, this function is called. If the interrupt was to indicate - *  a loss of link, the OSM link status handler is invoked for any other  - *  alarm interrupt the block that raised the interrupt is displayed  + *  a loss of link, the OSM link status handler is invoked for any other + *  alarm interrupt the block that raised the interrupt is displayed   *  and a H/W reset is issued.   *  Return Value:   *  NONE @@ -2320,10 +2674,32 @@ static void alarm_intr_handler(struct s2io_nic *nic)  	register u64 val64 = 0, err_reg = 0;  	/* Handling link status change error Intr */ -	err_reg = readq(&bar0->mac_rmac_err_reg); -	writeq(err_reg, &bar0->mac_rmac_err_reg); -	if (err_reg & RMAC_LINK_STATE_CHANGE_INT) { -		schedule_work(&nic->set_link_task); +	if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) { +		err_reg = readq(&bar0->mac_rmac_err_reg); +		writeq(err_reg, &bar0->mac_rmac_err_reg); +		if (err_reg & RMAC_LINK_STATE_CHANGE_INT) { +			schedule_work(&nic->set_link_task); +		} +	} + +	/* Handling Ecc errors */ +	val64 = readq(&bar0->mc_err_reg); +	writeq(val64, &bar0->mc_err_reg); +	if (val64 & (MC_ERR_REG_ECC_ALL_SNG | MC_ERR_REG_ECC_ALL_DBL)) { +		if (val64 & MC_ERR_REG_ECC_ALL_DBL) { +			nic->mac_control.stats_info->sw_stat. +				double_ecc_errs++; +			DBG_PRINT(ERR_DBG, "%s: Device indicates ", +				  dev->name); +			DBG_PRINT(ERR_DBG, "double ECC error!!\n"); +			if (nic->device_type != XFRAME_II_DEVICE) { +				netif_stop_queue(dev); +				schedule_work(&nic->rst_timer_task); +			} +		} else { +			nic->mac_control.stats_info->sw_stat. +				single_ecc_errs++; +		}  	}  	/* In case of a serious error, the device will be Reset. */ @@ -2338,7 +2714,7 @@ static void alarm_intr_handler(struct s2io_nic *nic)  	/*  	 * Also as mentioned in the latest Errata sheets if the PCC_FB_ECC  	 * Error occurs, the adapter will be recycled by disabling the -	 * adapter enable bit and enabling it again after the device  +	 * adapter enable bit and enabling it again after the device  	 * becomes Quiescent.  	 */  	val64 = readq(&bar0->pcc_err_reg); @@ -2354,18 +2730,18 @@ static void alarm_intr_handler(struct s2io_nic *nic)  	/* Other type of interrupts are not being handled now,  TODO */  } -/**  +/**   *  wait_for_cmd_complete - waits for a command to complete. - *  @sp : private member of the device structure, which is a pointer to the  + *  @sp : private member of the device structure, which is a pointer to the   *  s2io_nic structure. - *  Description: Function that waits for a command to Write into RMAC  - *  ADDR DATA registers to be completed and returns either success or  - *  error depending on whether the command was complete or not.  + *  Description: Function that waits for a command to Write into RMAC + *  ADDR DATA registers to be completed and returns either success or + *  error depending on whether the command was complete or not.   *  Return value:   *   SUCCESS on success and FAILURE on failure.   */ -static int wait_for_cmd_complete(nic_t * sp) +int wait_for_cmd_complete(nic_t * sp)  {  	XENA_dev_config_t __iomem *bar0 = sp->bar0;  	int ret = FAILURE, cnt = 0; @@ -2385,29 +2761,32 @@ static int wait_for_cmd_complete(nic_t * sp)  	return ret;  } -/**  - *  s2io_reset - Resets the card.  +/** + *  s2io_reset - Resets the card.   *  @sp : private member of the device structure.   *  Description: Function to Reset the card. This function then also - *  restores the previously saved PCI configuration space registers as  + *  restores the previously saved PCI configuration space registers as   *  the card reset also resets the configuration space.   *  Return value:   *  void.   */ -static void s2io_reset(nic_t * sp) +void s2io_reset(nic_t * sp)  {  	XENA_dev_config_t __iomem *bar0 = sp->bar0;  	u64 val64; -	u16 subid; +	u16 subid, pci_cmd; + +	/* Back up  the PCI-X CMD reg, dont want to lose MMRBC, OST settings */ +	pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd));  	val64 = SW_RESET_ALL;  	writeq(val64, &bar0->sw_reset); -	/*  -	 * At this stage, if the PCI write is indeed completed, the  -	 * card is reset and so is the PCI Config space of the device.  -	 * So a read cannot be issued at this stage on any of the  +	/* +	 * At this stage, if the PCI write is indeed completed, the +	 * card is reset and so is the PCI Config space of the device. +	 * So a read cannot be issued at this stage on any of the  	 * registers to ensure the write into "sw_reset" register  	 * has gone through.  	 * Question: Is there any system call that will explicitly force @@ -2418,42 +2797,72 @@ static void s2io_reset(nic_t * sp)  	 */  	msleep(250); -	/* Restore the PCI state saved during initializarion. */ +	/* Restore the PCI state saved during initialization. */  	pci_restore_state(sp->pdev); +	pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, +				     pci_cmd);  	s2io_init_pci(sp);  	msleep(250); +	/* Set swapper to enable I/O register access */ +	s2io_set_swapper(sp); + +	/* Clear certain PCI/PCI-X fields after reset */ +	if (sp->device_type == XFRAME_II_DEVICE) { +		/* Clear parity err detect bit */ +		pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000); + +		/* Clearing PCIX Ecc status register */ +		pci_write_config_dword(sp->pdev, 0x68, 0x7C); + +		/* Clearing PCI_STATUS error reflected here */ +		writeq(BIT(62), &bar0->txpic_int_reg); +	} + +	/* Reset device statistics maintained by OS */ +	memset(&sp->stats, 0, sizeof (struct net_device_stats)); +  	/* SXE-002: Configure link and activity LED to turn it off */  	subid = sp->pdev->subsystem_device; -	if ((subid & 0xFF) >= 0x07) { +	if (((subid & 0xFF) >= 0x07) && +	    (sp->device_type == XFRAME_I_DEVICE)) {  		val64 = readq(&bar0->gpio_control);  		val64 |= 0x0000800000000000ULL;  		writeq(val64, &bar0->gpio_control);  		val64 = 0x0411040400000000ULL; -		writeq(val64, (void __iomem *) bar0 + 0x2700); +		writeq(val64, (void __iomem *) ((u8 *) bar0 + 0x2700)); +	} + +	/* +	 * Clear spurious ECC interrupts that would have occured on +	 * XFRAME II cards after reset. +	 */ +	if (sp->device_type == XFRAME_II_DEVICE) { +		val64 = readq(&bar0->pcc_err_reg); +		writeq(val64, &bar0->pcc_err_reg);  	}  	sp->device_enabled_once = FALSE;  }  /** - *  s2io_set_swapper - to set the swapper controle on the card  - *  @sp : private member of the device structure,  + *  s2io_set_swapper - to set the swapper controle on the card + *  @sp : private member of the device structure,   *  pointer to the s2io_nic structure. - *  Description: Function to set the swapper control on the card  + *  Description: Function to set the swapper control on the card   *  correctly depending on the 'endianness' of the system.   *  Return value:   *  SUCCESS on success and FAILURE on failure.   */ -static int s2io_set_swapper(nic_t * sp) +int s2io_set_swapper(nic_t * sp)  {  	struct net_device *dev = sp->dev;  	XENA_dev_config_t __iomem *bar0 = sp->bar0;  	u64 val64, valt, valr; -	/*  +	/*  	 * Set proper endian settings and verify the same by reading  	 * the PIF Feed-back register.  	 */ @@ -2505,8 +2914,9 @@ static int s2io_set_swapper(nic_t * sp)  			i++;  		}  		if(i == 4) { +			unsigned long long x = val64;  			DBG_PRINT(ERR_DBG, "Write failed, Xmsi_addr "); -			DBG_PRINT(ERR_DBG, "reads:0x%llx\n",val64); +			DBG_PRINT(ERR_DBG, "reads:0x%llx\n", x);  			return FAILURE;  		}  	} @@ -2514,8 +2924,8 @@ static int s2io_set_swapper(nic_t * sp)  	val64 &= 0xFFFF000000000000ULL;  #ifdef  __BIG_ENDIAN -	/*  -	 * The device by default set to a big endian format, so a  +	/* +	 * The device by default set to a big endian format, so a  	 * big endian driver need not set anything.  	 */  	val64 |= (SWAPPER_CTRL_TXP_FE | @@ -2531,9 +2941,9 @@ static int s2io_set_swapper(nic_t * sp)  		 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);  	writeq(val64, &bar0->swapper_ctrl);  #else -	/*  +	/*  	 * Initially we enable all bits to make it accessible by the -	 * driver, then we selectively enable only those bits that  +	 * driver, then we selectively enable only those bits that  	 * we want to set.  	 */  	val64 |= (SWAPPER_CTRL_TXP_FE | @@ -2555,8 +2965,8 @@ static int s2io_set_swapper(nic_t * sp)  #endif  	val64 = readq(&bar0->swapper_ctrl); -	/*  -	 * Verifying if endian settings are accurate by reading a  +	/* +	 * Verifying if endian settings are accurate by reading a  	 * feedback register.  	 */  	val64 = readq(&bar0->pif_rd_swapper_fb); @@ -2576,55 +2986,63 @@ static int s2io_set_swapper(nic_t * sp)   * Functions defined below concern the OS part of the driver *   * ********************************************************* */ -/**   +/**   *  s2io_open - open entry point of the driver   *  @dev : pointer to the device structure.   *  Description:   *  This function is the open entry point of the driver. It mainly calls a   *  function to allocate Rx buffers and inserts them into the buffer - *  descriptors and then enables the Rx part of the NIC.  + *  descriptors and then enables the Rx part of the NIC.   *  Return value:   *  0 on success and an appropriate (-)ve integer as defined in errno.h   *   file on failure.   */ -static int s2io_open(struct net_device *dev) +int s2io_open(struct net_device *dev)  {  	nic_t *sp = dev->priv;  	int err = 0; -	/*  -	 * Make sure you have link off by default every time  +	/* +	 * Make sure you have link off by default every time  	 * Nic is initialized  	 */  	netif_carrier_off(dev); -	sp->last_link_state = LINK_DOWN; +	sp->last_link_state = 0;  	/* Initialize H/W and enable interrupts */  	if (s2io_card_up(sp)) {  		DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",  			  dev->name); -		return -ENODEV; +		err = -ENODEV; +		goto hw_init_failed;  	}  	/* After proper initialization of H/W, register ISR */ -	err = request_irq((int) sp->irq, s2io_isr, SA_SHIRQ, +	err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,  			  sp->name, dev);  	if (err) { -		s2io_reset(sp);  		DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",  			  dev->name); -		return err; +		goto isr_registration_failed;  	}  	if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {  		DBG_PRINT(ERR_DBG, "Set Mac Address Failed\n"); -		s2io_reset(sp); -		return -ENODEV; +		err = -ENODEV; +		goto setting_mac_address_failed;  	}  	netif_start_queue(dev);  	return 0; + +setting_mac_address_failed: +	free_irq(sp->pdev->irq, dev); +isr_registration_failed: +	del_timer_sync(&sp->alarm_timer); +	s2io_reset(sp); +hw_init_failed: +	return err;  }  /** @@ -2640,16 +3058,15 @@ static int s2io_open(struct net_device *dev)   *  file on failure.   */ -static int s2io_close(struct net_device *dev) +int s2io_close(struct net_device *dev)  {  	nic_t *sp = dev->priv; -  	flush_scheduled_work();  	netif_stop_queue(dev);  	/* Reset card, kill tasklet and free Tx and Rx buffers. */  	s2io_card_down(sp); -	free_irq(dev->irq, dev); +	free_irq(sp->pdev->irq, dev);  	sp->device_close_flag = TRUE;	/* Device is shut down. */  	return 0;  } @@ -2667,7 +3084,7 @@ static int s2io_close(struct net_device *dev)   *  0 on success & 1 on failure.   */ -static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) +int s2io_xmit(struct sk_buff *skb, struct net_device *dev)  {  	nic_t *sp = dev->priv;  	u16 frg_cnt, frg_len, i, queue, queue_len, put_off, get_off; @@ -2678,29 +3095,39 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)  #ifdef NETIF_F_TSO  	int mss;  #endif +	u16 vlan_tag = 0; +	int vlan_priority = 0;  	mac_info_t *mac_control;  	struct config_param *config; -	XENA_dev_config_t __iomem *bar0 = sp->bar0;  	mac_control = &sp->mac_control;  	config = &sp->config; -	DBG_PRINT(TX_DBG, "%s: In S2IO Tx routine\n", dev->name); +	DBG_PRINT(TX_DBG, "%s: In Neterion Tx routine\n", dev->name);  	spin_lock_irqsave(&sp->tx_lock, flags); -  	if (atomic_read(&sp->card_state) == CARD_DOWN) { -		DBG_PRINT(ERR_DBG, "%s: Card going down for reset\n", +		DBG_PRINT(TX_DBG, "%s: Card going down for reset\n",  			  dev->name);  		spin_unlock_irqrestore(&sp->tx_lock, flags); -		return 1; +		dev_kfree_skb(skb); +		return 0;  	}  	queue = 0; -	put_off = (u16) mac_control->tx_curr_put_info[queue].offset; -	get_off = (u16) mac_control->tx_curr_get_info[queue].offset; -	txdp = (TxD_t *) sp->list_info[queue][put_off].list_virt_addr; -	queue_len = mac_control->tx_curr_put_info[queue].fifo_len + 1; +	/* Get Fifo number to Transmit based on vlan priority */ +	if (sp->vlgrp && vlan_tx_tag_present(skb)) { +		vlan_tag = vlan_tx_tag_get(skb); +		vlan_priority = vlan_tag >> 13; +		queue = config->fifo_mapping[vlan_priority]; +	} + +	put_off = (u16) mac_control->fifos[queue].tx_curr_put_info.offset; +	get_off = (u16) mac_control->fifos[queue].tx_curr_get_info.offset; +	txdp = (TxD_t *) mac_control->fifos[queue].list_info[put_off]. +		list_virt_addr; + +	queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;  	/* Avoid "put" pointer going beyond "get" pointer */  	if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) {  		DBG_PRINT(ERR_DBG, "Error in xmit, No free TXDs.\n"); @@ -2709,6 +3136,15 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)  		spin_unlock_irqrestore(&sp->tx_lock, flags);  		return 0;  	} + +	/* A buffer with no data will be dropped */ +	if (!skb->len) { +		DBG_PRINT(TX_DBG, "%s:Buffer has no data..\n", dev->name); +		dev_kfree_skb(skb); +		spin_unlock_irqrestore(&sp->tx_lock, flags); +		return 0; +	} +  #ifdef NETIF_F_TSO  	mss = skb_shinfo(skb)->tso_size;  	if (mss) { @@ -2720,9 +3156,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)  	frg_cnt = skb_shinfo(skb)->nr_frags;  	frg_len = skb->len - skb->data_len; -	txdp->Host_Control = (unsigned long) skb;  	txdp->Buffer_Pointer = pci_map_single  	    (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); +	txdp->Host_Control = (unsigned long) skb;  	if (skb->ip_summed == CHECKSUM_HW) {  		txdp->Control_2 |=  		    (TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN | @@ -2731,6 +3167,11 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)  	txdp->Control_2 |= config->tx_intr_type; +	if (sp->vlgrp && vlan_tx_tag_present(skb)) { +		txdp->Control_2 |= TXD_VLAN_ENABLE; +		txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag); +	} +  	txdp->Control_1 |= (TXD_BUFFER0_SIZE(frg_len) |  			    TXD_GATHER_CODE_FIRST);  	txdp->Control_1 |= TXD_LIST_OWN_XENA; @@ -2738,6 +3179,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)  	/* For fragmented SKB. */  	for (i = 0; i < frg_cnt; i++) {  		skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; +		/* A '0' length fragment will be ignored */ +		if (!frag->size) +			continue;  		txdp++;  		txdp->Buffer_Pointer = (u64) pci_map_page  		    (sp->pdev, frag->page, frag->page_offset, @@ -2747,23 +3191,23 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)  	txdp->Control_1 |= TXD_GATHER_CODE_LAST;  	tx_fifo = mac_control->tx_FIFO_start[queue]; -	val64 = sp->list_info[queue][put_off].list_phy_addr; +	val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr;  	writeq(val64, &tx_fifo->TxDL_Pointer);  	val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST |  		 TX_FIFO_LAST_LIST); +  #ifdef NETIF_F_TSO  	if (mss)  		val64 |= TX_FIFO_SPECIAL_FUNC;  #endif  	writeq(val64, &tx_fifo->List_Control); -	/* Perform a PCI read to flush previous writes */ -	val64 = readq(&bar0->general_int_status); +	mmiowb();  	put_off++; -	put_off %= mac_control->tx_curr_put_info[queue].fifo_len + 1; -	mac_control->tx_curr_put_info[queue].offset = put_off; +	put_off %= mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1; +	mac_control->fifos[queue].tx_curr_put_info.offset = put_off;  	/* Avoid "put" pointer going beyond "get" pointer */  	if (((put_off + 1) % queue_len) == get_off) { @@ -2779,18 +3223,74 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)  	return 0;  } +static void +s2io_alarm_handle(unsigned long data) +{ +	nic_t *sp = (nic_t *)data; + +	alarm_intr_handler(sp); +	mod_timer(&sp->alarm_timer, jiffies + HZ / 2); +} + +static void s2io_txpic_intr_handle(nic_t *sp) +{ +	XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; +	u64 val64; + +	val64 = readq(&bar0->pic_int_status); +	if (val64 & PIC_INT_GPIO) { +		val64 = readq(&bar0->gpio_int_reg); +		if ((val64 & GPIO_INT_REG_LINK_DOWN) && +		    (val64 & GPIO_INT_REG_LINK_UP)) { +			val64 |=  GPIO_INT_REG_LINK_DOWN; +			val64 |= GPIO_INT_REG_LINK_UP; +			writeq(val64, &bar0->gpio_int_reg); +			goto masking; +		} + +		if (((sp->last_link_state == LINK_UP) && +			(val64 & GPIO_INT_REG_LINK_DOWN)) || +		((sp->last_link_state == LINK_DOWN) && +		(val64 & GPIO_INT_REG_LINK_UP))) { +			val64 = readq(&bar0->gpio_int_mask); +			val64 |=  GPIO_INT_MASK_LINK_DOWN; +			val64 |= GPIO_INT_MASK_LINK_UP; +			writeq(val64, &bar0->gpio_int_mask); +			s2io_set_link((unsigned long)sp); +		} +masking: +		if (sp->last_link_state == LINK_UP) { +			/*enable down interrupt */ +			val64 = readq(&bar0->gpio_int_mask); +			/* unmasks link down intr */ +			val64 &=  ~GPIO_INT_MASK_LINK_DOWN; +			/* masks link up intr */ +			val64 |= GPIO_INT_MASK_LINK_UP; +			writeq(val64, &bar0->gpio_int_mask); +		} else { +			/*enable UP Interrupt */ +			val64 = readq(&bar0->gpio_int_mask); +			/* unmasks link up interrupt */ +			val64 &= ~GPIO_INT_MASK_LINK_UP; +			/* masks link down interrupt */ +			val64 |=  GPIO_INT_MASK_LINK_DOWN; +			writeq(val64, &bar0->gpio_int_mask); +		} +	} +} +  /**   *  s2io_isr - ISR handler of the device .   *  @irq: the irq of the device.   *  @dev_id: a void pointer to the dev structure of the NIC.   *  @pt_regs: pointer to the registers pushed on the stack. - *  Description:  This function is the ISR handler of the device. It  - *  identifies the reason for the interrupt and calls the relevant  - *  service routines. As a contongency measure, this ISR allocates the  + *  Description:  This function is the ISR handler of the device. It + *  identifies the reason for the interrupt and calls the relevant + *  service routines. As a contongency measure, this ISR allocates the   *  recv buffers, if their numbers are below the panic value which is   *  presently set to 25% of the original number of rcv buffers allocated.   *  Return value: - *   IRQ_HANDLED: will be returned if IRQ was handled by this routine  + *   IRQ_HANDLED: will be returned if IRQ was handled by this routine   *   IRQ_NONE: will be returned if interrupt is not from our device   */  static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs) @@ -2798,40 +3298,31 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)  	struct net_device *dev = (struct net_device *) dev_id;  	nic_t *sp = dev->priv;  	XENA_dev_config_t __iomem *bar0 = sp->bar0; -#ifndef CONFIG_S2IO_NAPI -	int i, ret; -#endif -	u64 reason = 0; +	int i; +	u64 reason = 0, val64;  	mac_info_t *mac_control;  	struct config_param *config; +	atomic_inc(&sp->isr_cnt);  	mac_control = &sp->mac_control;  	config = &sp->config; -	/*  +	/*  	 * Identify the cause for interrupt and call the appropriate  	 * interrupt handler. Causes for the interrupt could be;  	 * 1. Rx of packet.  	 * 2. Tx complete.  	 * 3. Link down. -	 * 4. Error in any functional blocks of the NIC.  +	 * 4. Error in any functional blocks of the NIC.  	 */  	reason = readq(&bar0->general_int_status);  	if (!reason) {  		/* The interrupt was not raised by Xena. */ +		atomic_dec(&sp->isr_cnt);  		return IRQ_NONE;  	} -	/* If Intr is because of Tx Traffic */ -	if (reason & GEN_INTR_TXTRAFFIC) { -		tx_intr_handler(sp); -	} - -	/* If Intr is because of an error */ -	if (reason & (GEN_ERROR_INTR)) -		alarm_intr_handler(sp); -  #ifdef CONFIG_S2IO_NAPI  	if (reason & GEN_INTR_RXTRAFFIC) {  		if (netif_rx_schedule_prep(dev)) { @@ -2843,17 +3334,43 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)  #else  	/* If Intr is because of Rx Traffic */  	if (reason & GEN_INTR_RXTRAFFIC) { -		rx_intr_handler(sp); +		/* +		 * rx_traffic_int reg is an R1 register, writing all 1's +		 * will ensure that the actual interrupt causing bit get's +		 * cleared and hence a read can be avoided. +		 */ +		val64 = 0xFFFFFFFFFFFFFFFFULL; +		writeq(val64, &bar0->rx_traffic_int); +		for (i = 0; i < config->rx_ring_num; i++) { +			rx_intr_handler(&mac_control->rings[i]); +		}  	}  #endif -	/*  -	 * If the Rx buffer count is below the panic threshold then  -	 * reallocate the buffers from the interrupt handler itself,  +	/* If Intr is because of Tx Traffic */ +	if (reason & GEN_INTR_TXTRAFFIC) { +		/* +		 * tx_traffic_int reg is an R1 register, writing all 1's +		 * will ensure that the actual interrupt causing bit get's +		 * cleared and hence a read can be avoided. +		 */ +		val64 = 0xFFFFFFFFFFFFFFFFULL; +		writeq(val64, &bar0->tx_traffic_int); + +		for (i = 0; i < config->tx_fifo_num; i++) +			tx_intr_handler(&mac_control->fifos[i]); +	} + +	if (reason & GEN_INTR_TXPIC) +		s2io_txpic_intr_handle(sp); +	/* +	 * If the Rx buffer count is below the panic threshold then +	 * reallocate the buffers from the interrupt handler itself,  	 * else schedule a tasklet to reallocate the buffers.  	 */  #ifndef CONFIG_S2IO_NAPI  	for (i = 0; i < config->rx_ring_num; i++) { +		int ret;  		int rxb_size = atomic_read(&sp->rx_bufs_left[i]);  		int level = rx_buffer_level(sp, rxb_size, i); @@ -2865,6 +3382,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)  					  dev->name);  				DBG_PRINT(ERR_DBG, " in ISR!!\n");  				clear_bit(0, (&sp->tasklet_status)); +				atomic_dec(&sp->isr_cnt);  				return IRQ_HANDLED;  			}  			clear_bit(0, (&sp->tasklet_status)); @@ -2874,33 +3392,69 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs)  	}  #endif +	atomic_dec(&sp->isr_cnt);  	return IRQ_HANDLED;  }  /** - *  s2io_get_stats - Updates the device statistics structure.  + * s2io_updt_stats - + */ +static void s2io_updt_stats(nic_t *sp) +{ +	XENA_dev_config_t __iomem *bar0 = sp->bar0; +	u64 val64; +	int cnt = 0; + +	if (atomic_read(&sp->card_state) == CARD_UP) { +		/* Apprx 30us on a 133 MHz bus */ +		val64 = SET_UPDT_CLICKS(10) | +			STAT_CFG_ONE_SHOT_EN | STAT_CFG_STAT_EN; +		writeq(val64, &bar0->stat_cfg); +		do { +			udelay(100); +			val64 = readq(&bar0->stat_cfg); +			if (!(val64 & BIT(0))) +				break; +			cnt++; +			if (cnt == 5) +				break; /* Updt failed */ +		} while(1); +	} +} + +/** + *  s2io_get_stats - Updates the device statistics structure.   *  @dev : pointer to the device structure.   *  Description: - *  This function updates the device statistics structure in the s2io_nic  + *  This function updates the device statistics structure in the s2io_nic   *  structure and returns a pointer to the same.   *  Return value:   *  pointer to the updated net_device_stats structure.   */ -static struct net_device_stats *s2io_get_stats(struct net_device *dev) +struct net_device_stats *s2io_get_stats(struct net_device *dev)  {  	nic_t *sp = dev->priv;  	mac_info_t *mac_control;  	struct config_param *config; +  	mac_control = &sp->mac_control;  	config = &sp->config; -	sp->stats.tx_errors = mac_control->stats_info->tmac_any_err_frms; -	sp->stats.rx_errors = mac_control->stats_info->rmac_drop_frms; -	sp->stats.multicast = mac_control->stats_info->rmac_vld_mcst_frms; +	/* Configure Stats for immediate updt */ +	s2io_updt_stats(sp); + +	sp->stats.tx_packets = +		le32_to_cpu(mac_control->stats_info->tmac_frms); +	sp->stats.tx_errors = +		le32_to_cpu(mac_control->stats_info->tmac_any_err_frms); +	sp->stats.rx_errors = +		le32_to_cpu(mac_control->stats_info->rmac_drop_frms); +	sp->stats.multicast = +		le32_to_cpu(mac_control->stats_info->rmac_vld_mcst_frms);  	sp->stats.rx_length_errors = -	    mac_control->stats_info->rmac_long_frms; +		le32_to_cpu(mac_control->stats_info->rmac_long_frms);  	return (&sp->stats);  } @@ -2909,8 +3463,8 @@ static struct net_device_stats *s2io_get_stats(struct net_device *dev)   *  s2io_set_multicast - entry point for multicast address enable/disable.   *  @dev : pointer to the device structure   *  Description: - *  This function is a driver entry point which gets called by the kernel  - *  whenever multicast addresses must be enabled/disabled. This also gets  + *  This function is a driver entry point which gets called by the kernel + *  whenever multicast addresses must be enabled/disabled. This also gets   *  called to set/reset promiscuous mode. Depending on the deivce flag, we   *  determine, if multicast address must be enabled or if promiscuous mode   *  is to be disabled etc. @@ -2948,6 +3502,8 @@ static void s2io_set_multicast(struct net_device *dev)  		/*  Disable all Multicast addresses */  		writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),  		       &bar0->rmac_addr_data0_mem); +		writeq(RMAC_ADDR_DATA1_MEM_MASK(0x0), +		       &bar0->rmac_addr_data1_mem);  		val64 = RMAC_ADDR_CMD_MEM_WE |  		    RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |  		    RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos); @@ -3010,7 +3566,7 @@ static void s2io_set_multicast(struct net_device *dev)  			writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),  			       &bar0->rmac_addr_data0_mem);  			writeq(RMAC_ADDR_DATA1_MEM_MASK(0ULL), -		       		&bar0->rmac_addr_data1_mem); +				&bar0->rmac_addr_data1_mem);  			val64 = RMAC_ADDR_CMD_MEM_WE |  			    RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |  			    RMAC_ADDR_CMD_MEM_OFFSET @@ -3039,8 +3595,7 @@ static void s2io_set_multicast(struct net_device *dev)  			writeq(RMAC_ADDR_DATA0_MEM_ADDR(mac_addr),  			       &bar0->rmac_addr_data0_mem);  			writeq(RMAC_ADDR_DATA1_MEM_MASK(0ULL), -		       		&bar0->rmac_addr_data1_mem); - +				&bar0->rmac_addr_data1_mem);  			val64 = RMAC_ADDR_CMD_MEM_WE |  			    RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |  			    RMAC_ADDR_CMD_MEM_OFFSET @@ -3059,12 +3614,12 @@ static void s2io_set_multicast(struct net_device *dev)  }  /** - *  s2io_set_mac_addr - Programs the Xframe mac address  + *  s2io_set_mac_addr - Programs the Xframe mac address   *  @dev : pointer to the device structure.   *  @addr: a uchar pointer to the new mac address which is to be set. - *  Description : This procedure will program the Xframe to receive  + *  Description : This procedure will program the Xframe to receive   *  frames with new Mac Address - *  Return value: SUCCESS on success and an appropriate (-)ve integer  + *  Return value: SUCCESS on success and an appropriate (-)ve integer   *  as defined in errno.h file on failure.   */ @@ -3075,10 +3630,10 @@ int s2io_set_mac_addr(struct net_device *dev, u8 * addr)  	register u64 val64, mac_addr = 0;  	int i; -	/*  +	/*  	 * Set the new MAC address as the new unicast filter and reflect this  	 * change on the device address registered with the OS. It will be -	 * at offset 0.  +	 * at offset 0.  	 */  	for (i = 0; i < ETH_ALEN; i++) {  		mac_addr <<= 8; @@ -3102,12 +3657,12 @@ int s2io_set_mac_addr(struct net_device *dev, u8 * addr)  }  /** - * s2io_ethtool_sset - Sets different link parameters.  + * s2io_ethtool_sset - Sets different link parameters.   * @sp : private member of the device structure, which is a pointer to the  * s2io_nic structure.   * @info: pointer to the structure with parameters given by ethtool to set   * link information.   * Description: - * The function sets different link parameters provided by the user onto  + * The function sets different link parameters provided by the user onto   * the NIC.   * Return value:   * 0 on success. @@ -3129,7 +3684,7 @@ static int s2io_ethtool_sset(struct net_device *dev,  }  /** - * s2io_ethtol_gset - Return link specific information.  + * s2io_ethtol_gset - Return link specific information.   * @sp : private member of the device structure, pointer to the   *      s2io_nic structure.   * @info : pointer to the structure with parameters given by ethtool @@ -3161,8 +3716,8 @@ static int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info)  }  /** - * s2io_ethtool_gdrvinfo - Returns driver specific information.  - * @sp : private member of the device structure, which is a pointer to the  + * s2io_ethtool_gdrvinfo - Returns driver specific information. + * @sp : private member of the device structure, which is a pointer to the   * s2io_nic structure.   * @info : pointer to the structure with parameters given by ethtool to   * return driver information. @@ -3190,9 +3745,9 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,  /**   *  s2io_ethtool_gregs - dumps the entire space of Xfame into the buffer. - *  @sp: private member of the device structure, which is a pointer to the  + *  @sp: private member of the device structure, which is a pointer to the   *  s2io_nic structure. - *  @regs : pointer to the structure with parameters given by ethtool for  + *  @regs : pointer to the structure with parameters given by ethtool for   *  dumping the registers.   *  @reg_space: The input argumnet into which all the registers are dumped.   *  Description: @@ -3221,11 +3776,11 @@ static void s2io_ethtool_gregs(struct net_device *dev,  /**   *  s2io_phy_id  - timer function that alternates adapter LED. - *  @data : address of the private member of the device structure, which  + *  @data : address of the private member of the device structure, which   *  is a pointer to the s2io_nic structure, provided as an u32. - * Description: This is actually the timer function that alternates the  - * adapter LED bit of the adapter control bit to set/reset every time on  - * invocation. The timer is set for 1/2 a second, hence tha NIC blinks  + * Description: This is actually the timer function that alternates the + * adapter LED bit of the adapter control bit to set/reset every time on + * invocation. The timer is set for 1/2 a second, hence tha NIC blinks   *  once every second.  */  static void s2io_phy_id(unsigned long data) @@ -3236,7 +3791,8 @@ static void s2io_phy_id(unsigned long data)  	u16 subid;  	subid = sp->pdev->subsystem_device; -	if ((subid & 0xFF) >= 0x07) { +	if ((sp->device_type == XFRAME_II_DEVICE) || +		   ((subid & 0xFF) >= 0x07)) {  		val64 = readq(&bar0->gpio_control);  		val64 ^= GPIO_CTRL_GPIO_0;  		writeq(val64, &bar0->gpio_control); @@ -3253,12 +3809,12 @@ static void s2io_phy_id(unsigned long data)   * s2io_ethtool_idnic - To physically identify the nic on the system.   * @sp : private member of the device structure, which is a pointer to the   * s2io_nic structure. - * @id : pointer to the structure with identification parameters given by  + * @id : pointer to the structure with identification parameters given by   * ethtool.   * Description: Used to physically identify the NIC on the system. - * The Link LED will blink for a time specified by the user for  + * The Link LED will blink for a time specified by the user for   * identification. - * NOTE: The Link has to be Up to be able to blink the LED. Hence  + * NOTE: The Link has to be Up to be able to blink the LED. Hence   * identification is possible only if it's link is up.   * Return value:   * int , returns 0 on success @@ -3273,7 +3829,8 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)  	subid = sp->pdev->subsystem_device;  	last_gpio_ctrl_val = readq(&bar0->gpio_control); -	if ((subid & 0xFF) < 0x07) { +	if ((sp->device_type == XFRAME_I_DEVICE) && +		((subid & 0xFF) < 0x07)) {  		val64 = readq(&bar0->adapter_control);  		if (!(val64 & ADAPTER_CNTL_EN)) {  			printk(KERN_ERR @@ -3288,12 +3845,12 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)  	}  	mod_timer(&sp->id_timer, jiffies);  	if (data) -		msleep(data * 1000); +		msleep_interruptible(data * HZ);  	else -		msleep(0xFFFFFFFF); +		msleep_interruptible(MAX_FLICKER_TIME);  	del_timer_sync(&sp->id_timer); -	if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) { +	if (CARDS_WITH_FAULTY_LINK_INDICATORS(sp->device_type, subid)) {  		writeq(last_gpio_ctrl_val, &bar0->gpio_control);  		last_gpio_ctrl_val = readq(&bar0->gpio_control);  	} @@ -3303,7 +3860,8 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)  /**   * s2io_ethtool_getpause_data -Pause frame frame generation and reception. - * @sp : private member of the device structure, which is a pointer to the  * s2io_nic structure. + * @sp : private member of the device structure, which is a pointer to the + *	s2io_nic structure.   * @ep : pointer to the structure with pause parameters given by ethtool.   * Description:   * Returns the Pause frame generation and reception capability of the NIC. @@ -3327,7 +3885,7 @@ static void s2io_ethtool_getpause_data(struct net_device *dev,  /**   * s2io_ethtool_setpause_data -  set/reset pause frame generation. - * @sp : private member of the device structure, which is a pointer to the  + * @sp : private member of the device structure, which is a pointer to the   *      s2io_nic structure.   * @ep : pointer to the structure with pause parameters given by ethtool.   * Description: @@ -3338,7 +3896,7 @@ static void s2io_ethtool_getpause_data(struct net_device *dev,   */  static int s2io_ethtool_setpause_data(struct net_device *dev, -				      struct ethtool_pauseparam *ep) +			       struct ethtool_pauseparam *ep)  {  	u64 val64;  	nic_t *sp = dev->priv; @@ -3359,13 +3917,13 @@ static int s2io_ethtool_setpause_data(struct net_device *dev,  /**   * read_eeprom - reads 4 bytes of data from user given offset. - * @sp : private member of the device structure, which is a pointer to the  + * @sp : private member of the device structure, which is a pointer to the   *      s2io_nic structure.   * @off : offset at which the data must be written   * @data : Its an output parameter where the data read at the given - * 	offset is stored. + *	offset is stored.   * Description: - * Will read 4 bytes of data from the user given offset and return the  + * Will read 4 bytes of data from the user given offset and return the   * read data.   * NOTE: Will allow to read only part of the EEPROM visible through the   *   I2C bus. @@ -3406,7 +3964,7 @@ static int read_eeprom(nic_t * sp, int off, u32 * data)   *       s2io_nic structure.   *  @off : offset at which the data must be written   *  @data : The data that is to be written - *  @cnt : Number of bytes of the data that are actually to be written into  + *  @cnt : Number of bytes of the data that are actually to be written into   *  the Eeprom. (max of 3)   * Description:   *  Actually writes the relevant part of the data value into the Eeprom @@ -3443,7 +4001,7 @@ static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)  /**   *  s2io_ethtool_geeprom  - reads the value stored in the Eeprom.   *  @sp : private member of the device structure, which is a pointer to the *       s2io_nic structure. - *  @eeprom : pointer to the user level structure provided by ethtool,  + *  @eeprom : pointer to the user level structure provided by ethtool,   *  containing all relevant information.   *  @data_buf : user defined value to be written into Eeprom.   *  Description: Reads the values stored in the Eeprom at given offset @@ -3454,7 +4012,7 @@ static int write_eeprom(nic_t * sp, int off, u32 data, int cnt)   */  static int s2io_ethtool_geeprom(struct net_device *dev, -				struct ethtool_eeprom *eeprom, u8 * data_buf) +			 struct ethtool_eeprom *eeprom, u8 * data_buf)  {  	u32 data, i, valid;  	nic_t *sp = dev->priv; @@ -3479,7 +4037,7 @@ static int s2io_ethtool_geeprom(struct net_device *dev,   *  s2io_ethtool_seeprom - tries to write the user provided value in Eeprom   *  @sp : private member of the device structure, which is a pointer to the   *  s2io_nic structure. - *  @eeprom : pointer to the user level structure provided by ethtool,  + *  @eeprom : pointer to the user level structure provided by ethtool,   *  containing all relevant information.   *  @data_buf ; user defined value to be written into Eeprom.   *  Description: @@ -3527,8 +4085,8 @@ static int s2io_ethtool_seeprom(struct net_device *dev,  }  /** - * s2io_register_test - reads and writes into all clock domains.  - * @sp : private member of the device structure, which is a pointer to the  + * s2io_register_test - reads and writes into all clock domains. + * @sp : private member of the device structure, which is a pointer to the   * s2io_nic structure.   * @data : variable that returns the result of each of the test conducted b   * by the driver. @@ -3545,8 +4103,8 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)  	u64 val64 = 0;  	int fail = 0; -	val64 = readq(&bar0->pcc_enable); -	if (val64 != 0xff00000000000000ULL) { +	val64 = readq(&bar0->pif_rd_swapper_fb); +	if (val64 != 0x123456789abcdefULL) {  		fail = 1;  		DBG_PRINT(INFO_DBG, "Read Test level 1 fails\n");  	} @@ -3590,13 +4148,13 @@ static int s2io_register_test(nic_t * sp, uint64_t * data)  }  /** - * s2io_eeprom_test - to verify that EEprom in the xena can be programmed.  + * s2io_eeprom_test - to verify that EEprom in the xena can be programmed.   * @sp : private member of the device structure, which is a pointer to the   * s2io_nic structure.   * @data:variable that returns the result of each of the test conducted by   * the driver.   * Description: - * Verify that EEPROM in the xena can be programmed using I2C_CONTROL  + * Verify that EEPROM in the xena can be programmed using I2C_CONTROL   * register.   * Return value:   * 0 on success. @@ -3661,14 +4219,14 @@ static int s2io_eeprom_test(nic_t * sp, uint64_t * data)  /**   * s2io_bist_test - invokes the MemBist test of the card . - * @sp : private member of the device structure, which is a pointer to the  + * @sp : private member of the device structure, which is a pointer to the   * s2io_nic structure. - * @data:variable that returns the result of each of the test conducted by  + * @data:variable that returns the result of each of the test conducted by   * the driver.   * Description:   * This invokes the MemBist test of the card. We give around   * 2 secs time for the Test to complete. If it's still not complete - * within this peiod, we consider that the test failed.  + * within this peiod, we consider that the test failed.   * Return value:   * 0 on success and -1 on failure.   */ @@ -3697,13 +4255,13 @@ static int s2io_bist_test(nic_t * sp, uint64_t * data)  }  /** - * s2io-link_test - verifies the link state of the nic   - * @sp ; private member of the device structure, which is a pointer to the  + * s2io-link_test - verifies the link state of the nic + * @sp ; private member of the device structure, which is a pointer to the   * s2io_nic structure.   * @data: variable that returns the result of each of the test conducted by   * the driver.   * Description: - * The function verifies the link state of the NIC and updates the input  + * The function verifies the link state of the NIC and updates the input   * argument 'data' appropriately.   * Return value:   * 0 on success. @@ -3722,13 +4280,13 @@ static int s2io_link_test(nic_t * sp, uint64_t * data)  }  /** - * s2io_rldram_test - offline test for access to the RldRam chip on the NIC  - * @sp - private member of the device structure, which is a pointer to the   + * s2io_rldram_test - offline test for access to the RldRam chip on the NIC + * @sp - private member of the device structure, which is a pointer to the   * s2io_nic structure. - * @data - variable that returns the result of each of the test  + * @data - variable that returns the result of each of the test   * conducted by the driver.   * Description: - *  This is one of the offline test that tests the read and write  + *  This is one of the offline test that tests the read and write   *  access to the RldRam chip on the NIC.   * Return value:   *  0 on success. @@ -3833,7 +4391,7 @@ static int s2io_rldram_test(nic_t * sp, uint64_t * data)   *  s2io_nic structure.   *  @ethtest : pointer to a ethtool command specific structure that will be   *  returned to the user. - *  @data : variable that returns the result of each of the test  + *  @data : variable that returns the result of each of the test   * conducted by the driver.   * Description:   *  This function conducts 6 tests ( 4 offline and 2 online) to determine @@ -3851,23 +4409,18 @@ static void s2io_ethtool_test(struct net_device *dev,  	if (ethtest->flags == ETH_TEST_FL_OFFLINE) {  		/* Offline Tests. */ -		if (orig_state) { +		if (orig_state)  			s2io_close(sp->dev); -			s2io_set_swapper(sp); -		} else -			s2io_set_swapper(sp);  		if (s2io_register_test(sp, &data[0]))  			ethtest->flags |= ETH_TEST_FL_FAILED;  		s2io_reset(sp); -		s2io_set_swapper(sp);  		if (s2io_rldram_test(sp, &data[3]))  			ethtest->flags |= ETH_TEST_FL_FAILED;  		s2io_reset(sp); -		s2io_set_swapper(sp);  		if (s2io_eeprom_test(sp, &data[1]))  			ethtest->flags |= ETH_TEST_FL_FAILED; @@ -3910,61 +4463,111 @@ static void s2io_get_ethtool_stats(struct net_device *dev,  	nic_t *sp = dev->priv;  	StatInfo_t *stat_info = sp->mac_control.stats_info; -	tmp_stats[i++] = le32_to_cpu(stat_info->tmac_frms); -	tmp_stats[i++] = le32_to_cpu(stat_info->tmac_data_octets); +	s2io_updt_stats(sp); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->tmac_frms_oflow) << 32  | +		le32_to_cpu(stat_info->tmac_frms); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->tmac_data_octets_oflow) << 32 | +		le32_to_cpu(stat_info->tmac_data_octets);  	tmp_stats[i++] = le64_to_cpu(stat_info->tmac_drop_frms); -	tmp_stats[i++] = le32_to_cpu(stat_info->tmac_mcst_frms); -	tmp_stats[i++] = le32_to_cpu(stat_info->tmac_bcst_frms); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->tmac_mcst_frms_oflow) << 32 | +		le32_to_cpu(stat_info->tmac_mcst_frms); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->tmac_bcst_frms_oflow) << 32 | +		le32_to_cpu(stat_info->tmac_bcst_frms);  	tmp_stats[i++] = le64_to_cpu(stat_info->tmac_pause_ctrl_frms); -	tmp_stats[i++] = le32_to_cpu(stat_info->tmac_any_err_frms); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->tmac_any_err_frms_oflow) << 32 | +		le32_to_cpu(stat_info->tmac_any_err_frms);  	tmp_stats[i++] = le64_to_cpu(stat_info->tmac_vld_ip_octets); -	tmp_stats[i++] = le32_to_cpu(stat_info->tmac_vld_ip); -	tmp_stats[i++] = le32_to_cpu(stat_info->tmac_drop_ip); -	tmp_stats[i++] = le32_to_cpu(stat_info->tmac_icmp); -	tmp_stats[i++] = le32_to_cpu(stat_info->tmac_rst_tcp); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->tmac_vld_ip_oflow) << 32 | +		le32_to_cpu(stat_info->tmac_vld_ip); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->tmac_drop_ip_oflow) << 32 | +		le32_to_cpu(stat_info->tmac_drop_ip); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->tmac_icmp_oflow) << 32 | +		le32_to_cpu(stat_info->tmac_icmp); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->tmac_rst_tcp_oflow) << 32 | +		le32_to_cpu(stat_info->tmac_rst_tcp);  	tmp_stats[i++] = le64_to_cpu(stat_info->tmac_tcp); -	tmp_stats[i++] = le32_to_cpu(stat_info->tmac_udp); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_frms); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_data_octets); +	tmp_stats[i++] = (u64)le32_to_cpu(stat_info->tmac_udp_oflow) << 32 | +		le32_to_cpu(stat_info->tmac_udp); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->rmac_vld_frms_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_vld_frms); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->rmac_data_octets_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_data_octets);  	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_fcs_err_frms);  	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_drop_frms); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_mcst_frms); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_vld_bcst_frms); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->rmac_vld_mcst_frms_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_vld_mcst_frms); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->rmac_vld_bcst_frms_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_vld_bcst_frms);  	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_in_rng_len_err_frms);  	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_long_frms);  	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_pause_ctrl_frms); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_discarded_frms); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_usized_frms); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_osized_frms); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_frag_frms); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_jabber_frms); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ip); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->rmac_discarded_frms_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_discarded_frms); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->rmac_usized_frms_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_usized_frms); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->rmac_osized_frms_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_osized_frms); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->rmac_frag_frms_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_frag_frms); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->rmac_jabber_frms_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_jabber_frms); +	tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_ip);  	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ip_octets);  	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_hdr_err_ip); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_drop_ip); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_icmp); +	tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_drop_ip); +	tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_icmp);  	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_tcp); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_udp); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_drp_udp); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pause_cnt); -	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_accepted_ip); +	tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_udp); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->rmac_err_drp_udp_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_err_drp_udp); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->rmac_pause_cnt_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_pause_cnt); +	tmp_stats[i++] = +		(u64)le32_to_cpu(stat_info->rmac_accepted_ip_oflow) << 32 | +		le32_to_cpu(stat_info->rmac_accepted_ip);  	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_tcp); +	tmp_stats[i++] = 0; +	tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs; +	tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs;  } -static int s2io_ethtool_get_regs_len(struct net_device *dev) +int s2io_ethtool_get_regs_len(struct net_device *dev)  {  	return (XENA_REG_SPACE);  } -static u32 s2io_ethtool_get_rx_csum(struct net_device * dev) +u32 s2io_ethtool_get_rx_csum(struct net_device * dev)  {  	nic_t *sp = dev->priv;  	return (sp->rx_csum);  } - -static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data) +int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)  {  	nic_t *sp = dev->priv; @@ -3975,19 +4578,17 @@ static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)  	return 0;  } - -static int s2io_get_eeprom_len(struct net_device *dev) +int s2io_get_eeprom_len(struct net_device *dev)  {  	return (XENA_EEPROM_SPACE);  } -static int s2io_ethtool_self_test_count(struct net_device *dev) +int s2io_ethtool_self_test_count(struct net_device *dev)  {  	return (S2IO_TEST_LEN);  } - -static void s2io_ethtool_get_strings(struct net_device *dev, -				     u32 stringset, u8 * data) +void s2io_ethtool_get_strings(struct net_device *dev, +			      u32 stringset, u8 * data)  {  	switch (stringset) {  	case ETH_SS_TEST: @@ -3998,13 +4599,12 @@ static void s2io_ethtool_get_strings(struct net_device *dev,  		       sizeof(ethtool_stats_keys));  	}  } -  static int s2io_ethtool_get_stats_count(struct net_device *dev)  {  	return (S2IO_STAT_LEN);  } -static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) +int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)  {  	if (data)  		dev->features |= NETIF_F_IP_CSUM; @@ -4046,21 +4646,18 @@ static struct ethtool_ops netdev_ethtool_ops = {  };  /** - *  s2io_ioctl - Entry point for the Ioctl  + *  s2io_ioctl - Entry point for the Ioctl   *  @dev :  Device pointer.   *  @ifr :  An IOCTL specefic structure, that can contain a pointer to   *  a proprietary structure used to pass information to the driver.   *  @cmd :  This is used to distinguish between the different commands that   *  can be passed to the IOCTL functions.   *  Description: - *  This function has support for ethtool, adding multiple MAC addresses on  - *  the NIC and some DBG commands for the util tool. - *  Return value: - *  Currently the IOCTL supports no operations, hence by default this - *  function returns OP NOT SUPPORTED value. + *  Currently there are no special functionality supported in IOCTL, hence + *  function always return EOPNOTSUPPORTED   */ -static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)  {  	return -EOPNOTSUPP;  } @@ -4076,17 +4673,9 @@ static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)   *   file on failure.   */ -static int s2io_change_mtu(struct net_device *dev, int new_mtu) +int s2io_change_mtu(struct net_device *dev, int new_mtu)  {  	nic_t *sp = dev->priv; -	XENA_dev_config_t __iomem *bar0 = sp->bar0; -	register u64 val64; - -	if (netif_running(dev)) { -		DBG_PRINT(ERR_DBG, "%s: Must be stopped to ", dev->name); -		DBG_PRINT(ERR_DBG, "change its MTU \n"); -		return -EBUSY; -	}  	if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) {  		DBG_PRINT(ERR_DBG, "%s: MTU size is invalid.\n", @@ -4094,11 +4683,22 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)  		return -EPERM;  	} -	/* Set the new MTU into the PYLD register of the NIC */ -	val64 = new_mtu; -	writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len); -  	dev->mtu = new_mtu; +	if (netif_running(dev)) { +		s2io_card_down(sp); +		netif_stop_queue(dev); +		if (s2io_card_up(sp)) { +			DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n", +				  __FUNCTION__); +		} +		if (netif_queue_stopped(dev)) +			netif_wake_queue(dev); +	} else { /* Device is down */ +		XENA_dev_config_t __iomem *bar0 = sp->bar0; +		u64 val64 = new_mtu; + +		writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len); +	}  	return 0;  } @@ -4108,9 +4708,9 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)   *  @dev_adr : address of the device structure in dma_addr_t format.   *  Description:   *  This is the tasklet or the bottom half of the ISR. This is - *  an extension of the ISR which is scheduled by the scheduler to be run  + *  an extension of the ISR which is scheduled by the scheduler to be run   *  when the load on the CPU is low. All low priority tasks of the ISR can - *  be pushed into the tasklet. For now the tasklet is used only to  + *  be pushed into the tasklet. For now the tasklet is used only to   *  replenish the Rx buffers in the Rx buffer descriptors.   *  Return value:   *  void. @@ -4166,19 +4766,22 @@ static void s2io_set_link(unsigned long data)  	}  	subid = nic->pdev->subsystem_device; -	/*  -	 * Allow a small delay for the NICs self initiated  -	 * cleanup to complete. -	 */ -	msleep(100); +	if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) { +		/* +		 * Allow a small delay for the NICs self initiated +		 * cleanup to complete. +		 */ +		msleep(100); +	}  	val64 = readq(&bar0->adapter_status); -	if (verify_xena_quiescence(val64, nic->device_enabled_once)) { +	if (verify_xena_quiescence(nic, val64, nic->device_enabled_once)) {  		if (LINK_IS_UP(val64)) {  			val64 = readq(&bar0->adapter_control);  			val64 |= ADAPTER_CNTL_EN;  			writeq(val64, &bar0->adapter_control); -			if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) { +			if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type, +							     subid)) {  				val64 = readq(&bar0->gpio_control);  				val64 |= GPIO_CTRL_GPIO_0;  				writeq(val64, &bar0->gpio_control); @@ -4187,20 +4790,24 @@ static void s2io_set_link(unsigned long data)  				val64 |= ADAPTER_LED_ON;  				writeq(val64, &bar0->adapter_control);  			} -			val64 = readq(&bar0->adapter_status); -			if (!LINK_IS_UP(val64)) { -				DBG_PRINT(ERR_DBG, "%s:", dev->name); -				DBG_PRINT(ERR_DBG, " Link down"); -				DBG_PRINT(ERR_DBG, "after "); -				DBG_PRINT(ERR_DBG, "enabling "); -				DBG_PRINT(ERR_DBG, "device \n"); +			if (s2io_link_fault_indication(nic) == +						MAC_RMAC_ERR_TIMER) { +				val64 = readq(&bar0->adapter_status); +				if (!LINK_IS_UP(val64)) { +					DBG_PRINT(ERR_DBG, "%s:", dev->name); +					DBG_PRINT(ERR_DBG, " Link down"); +					DBG_PRINT(ERR_DBG, "after "); +					DBG_PRINT(ERR_DBG, "enabling "); +					DBG_PRINT(ERR_DBG, "device \n"); +				}  			}  			if (nic->device_enabled_once == FALSE) {  				nic->device_enabled_once = TRUE;  			}  			s2io_link(nic, LINK_UP);  		} else { -			if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) { +			if (CARDS_WITH_FAULTY_LINK_INDICATORS(nic->device_type, +							      subid)) {  				val64 = readq(&bar0->gpio_control);  				val64 &= ~GPIO_CTRL_GPIO_0;  				writeq(val64, &bar0->gpio_control); @@ -4223,9 +4830,11 @@ static void s2io_card_down(nic_t * sp)  	unsigned long flags;  	register u64 val64 = 0; +	del_timer_sync(&sp->alarm_timer);  	/* If s2io_set_link task is executing, wait till it completes. */ -	while (test_and_set_bit(0, &(sp->link_state))) +	while (test_and_set_bit(0, &(sp->link_state))) {  		msleep(50); +	}  	atomic_set(&sp->card_state, CARD_DOWN);  	/* disable Tx and Rx traffic on the NIC */ @@ -4237,7 +4846,7 @@ static void s2io_card_down(nic_t * sp)  	/* Check if the device is Quiescent and then Reset the NIC */  	do {  		val64 = readq(&bar0->adapter_status); -		if (verify_xena_quiescence(val64, sp->device_enabled_once)) { +		if (verify_xena_quiescence(sp, val64, sp->device_enabled_once)) {  			break;  		} @@ -4251,14 +4860,27 @@ static void s2io_card_down(nic_t * sp)  			break;  		}  	} while (1); -	spin_lock_irqsave(&sp->tx_lock, flags);  	s2io_reset(sp); -	/* Free all unused Tx and Rx buffers */ +	/* Waiting till all Interrupt handlers are complete */ +	cnt = 0; +	do { +		msleep(10); +		if (!atomic_read(&sp->isr_cnt)) +			break; +		cnt++; +	} while(cnt < 5); + +	spin_lock_irqsave(&sp->tx_lock, flags); +	/* Free all Tx buffers */  	free_tx_buffers(sp); +	spin_unlock_irqrestore(&sp->tx_lock, flags); + +	/* Free all Rx buffers */ +	spin_lock_irqsave(&sp->rx_lock, flags);  	free_rx_buffers(sp); +	spin_unlock_irqrestore(&sp->rx_lock, flags); -	spin_unlock_irqrestore(&sp->tx_lock, flags);  	clear_bit(0, &(sp->link_state));  } @@ -4276,8 +4898,8 @@ static int s2io_card_up(nic_t * sp)  		return -ENODEV;  	} -	/*  -	 * Initializing the Rx buffers. For now we are considering only 1  +	/* +	 * Initializing the Rx buffers. For now we are considering only 1  	 * Rx ring and initializing buffers into 30 Rx blocks  	 */  	mac_control = &sp->mac_control; @@ -4311,16 +4933,18 @@ static int s2io_card_up(nic_t * sp)  		return -ENODEV;  	} +	S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2)); +  	atomic_set(&sp->card_state, CARD_UP);  	return 0;  } -/**  +/**   * s2io_restart_nic - Resets the NIC.   * @data : long pointer to the device private structure   * Description:   * This function is scheduled to be run by the s2io_tx_watchdog - * function after 0.5 secs to reset the NIC. The idea is to reduce  + * function after 0.5 secs to reset the NIC. The idea is to reduce   * the run time of the watch dog routine which is run holding a   * spin lock.   */ @@ -4338,10 +4962,11 @@ static void s2io_restart_nic(unsigned long data)  	netif_wake_queue(dev);  	DBG_PRINT(ERR_DBG, "%s: was reset by Tx watchdog timer\n",  		  dev->name); +  } -/**  - *  s2io_tx_watchdog - Watchdog for transmit side.  +/** + *  s2io_tx_watchdog - Watchdog for transmit side.   *  @dev : Pointer to net device structure   *  Description:   *  This function is triggered if the Tx Queue is stopped @@ -4369,7 +4994,7 @@ static void s2io_tx_watchdog(struct net_device *dev)   *   @len : length of the packet   *   @cksum : FCS checksum of the frame.   *   @ring_no : the ring from which this RxD was extracted. - *   Description:  + *   Description:   *   This function is called by the Tx interrupt serivce routine to perform   *   some OS related operations on the SKB before passing it to the upper   *   layers. It mainly checks if the checksum is OK, if so adds it to the @@ -4379,35 +5004,68 @@ static void s2io_tx_watchdog(struct net_device *dev)   *   Return value:   *   SUCCESS on success and -1 on failure.   */ -#ifndef CONFIG_2BUFF_MODE -static int rx_osm_handler(nic_t * sp, u16 len, RxD_t * rxdp, int ring_no) -#else -static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no, -			  buffAdd_t * ba) -#endif +static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp)  { +	nic_t *sp = ring_data->nic;  	struct net_device *dev = (struct net_device *) sp->dev; -	struct sk_buff *skb = -	    (struct sk_buff *) ((unsigned long) rxdp->Host_Control); +	struct sk_buff *skb = (struct sk_buff *) +		((unsigned long) rxdp->Host_Control); +	int ring_no = ring_data->ring_no;  	u16 l3_csum, l4_csum;  #ifdef CONFIG_2BUFF_MODE -	int buf0_len, buf2_len; +	int buf0_len = RXD_GET_BUFFER0_SIZE(rxdp->Control_2); +	int buf2_len = RXD_GET_BUFFER2_SIZE(rxdp->Control_2); +	int get_block = ring_data->rx_curr_get_info.block_index; +	int get_off = ring_data->rx_curr_get_info.offset; +	buffAdd_t *ba = &ring_data->ba[get_block][get_off];  	unsigned char *buff; +#else +	u16 len = (u16) ((RXD_GET_BUFFER0_SIZE(rxdp->Control_2)) >> 48);;  #endif +	skb->dev = dev; +	if (rxdp->Control_1 & RXD_T_CODE) { +		unsigned long long err = rxdp->Control_1 & RXD_T_CODE; +		DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n", +			  dev->name, err); +		dev_kfree_skb(skb); +		sp->stats.rx_crc_errors++; +		atomic_dec(&sp->rx_bufs_left[ring_no]); +		rxdp->Host_Control = 0; +		return 0; +	} -	l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1); -	if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && (sp->rx_csum)) { +	/* Updating statistics */ +	rxdp->Host_Control = 0; +	sp->rx_pkt_count++; +	sp->stats.rx_packets++; +#ifndef CONFIG_2BUFF_MODE +	sp->stats.rx_bytes += len; +#else +	sp->stats.rx_bytes += buf0_len + buf2_len; +#endif + +#ifndef CONFIG_2BUFF_MODE +	skb_put(skb, len); +#else +	buff = skb_push(skb, buf0_len); +	memcpy(buff, ba->ba_0, buf0_len); +	skb_put(skb, buf2_len); +#endif + +	if ((rxdp->Control_1 & TCP_OR_UDP_FRAME) && +	    (sp->rx_csum)) { +		l3_csum = RXD_GET_L3_CKSUM(rxdp->Control_1);  		l4_csum = RXD_GET_L4_CKSUM(rxdp->Control_1);  		if ((l3_csum == L3_CKSUM_OK) && (l4_csum == L4_CKSUM_OK)) { -			/*  +			/*  			 * NIC verifies if the Checksum of the received  			 * frame is Ok or not and accordingly returns  			 * a flag in the RxD.  			 */  			skb->ip_summed = CHECKSUM_UNNECESSARY;  		} else { -			/*  -			 * Packet with erroneous checksum, let the  +			/* +			 * Packet with erroneous checksum, let the  			 * upper layers deal with it.  			 */  			skb->ip_summed = CHECKSUM_NONE; @@ -4416,44 +5074,26 @@ static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,  		skb->ip_summed = CHECKSUM_NONE;  	} -	if (rxdp->Control_1 & RXD_T_CODE) { -		unsigned long long err = rxdp->Control_1 & RXD_T_CODE; -		DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n", -			  dev->name, err); -	} -#ifdef CONFIG_2BUFF_MODE -	buf0_len = RXD_GET_BUFFER0_SIZE(rxdp->Control_2); -	buf2_len = RXD_GET_BUFFER2_SIZE(rxdp->Control_2); -#endif - -	skb->dev = dev; -#ifndef CONFIG_2BUFF_MODE -	skb_put(skb, len); -	skb->protocol = eth_type_trans(skb, dev); -#else -	buff = skb_push(skb, buf0_len); -	memcpy(buff, ba->ba_0, buf0_len); -	skb_put(skb, buf2_len);  	skb->protocol = eth_type_trans(skb, dev); -#endif -  #ifdef CONFIG_S2IO_NAPI -	netif_receive_skb(skb); +	if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { +		/* Queueing the vlan frame to the upper layer */ +		vlan_hwaccel_receive_skb(skb, sp->vlgrp, +			RXD_GET_VLAN_TAG(rxdp->Control_2)); +	} else { +		netif_receive_skb(skb); +	}  #else -	netif_rx(skb); +	if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { +		/* Queueing the vlan frame to the upper layer */ +		vlan_hwaccel_rx(skb, sp->vlgrp, +			RXD_GET_VLAN_TAG(rxdp->Control_2)); +	} else { +		netif_rx(skb); +	}  #endif -  	dev->last_rx = jiffies; -	sp->rx_pkt_count++; -	sp->stats.rx_packets++; -#ifndef CONFIG_2BUFF_MODE -	sp->stats.rx_bytes += len; -#else -	sp->stats.rx_bytes += buf0_len + buf2_len; -#endif -  	atomic_dec(&sp->rx_bufs_left[ring_no]); -	rxdp->Host_Control = 0;  	return SUCCESS;  } @@ -4464,13 +5104,13 @@ static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,   *  @link : inidicates whether link is UP/DOWN.   *  Description:   *  This function stops/starts the Tx queue depending on whether the link - *  status of the NIC is is down or up. This is called by the Alarm  - *  interrupt handler whenever a link change interrupt comes up.  + *  status of the NIC is is down or up. This is called by the Alarm + *  interrupt handler whenever a link change interrupt comes up.   *  Return value:   *  void.   */ -static void s2io_link(nic_t * sp, int link) +void s2io_link(nic_t * sp, int link)  {  	struct net_device *dev = (struct net_device *) sp->dev; @@ -4487,8 +5127,25 @@ static void s2io_link(nic_t * sp, int link)  }  /** - *  s2io_init_pci -Initialization of PCI and PCI-X configuration registers .  - *  @sp : private member of the device structure, which is a pointer to the  + *  get_xena_rev_id - to identify revision ID of xena. + *  @pdev : PCI Dev structure + *  Description: + *  Function to identify the Revision ID of xena. + *  Return value: + *  returns the revision ID of the device. + */ + +int get_xena_rev_id(struct pci_dev *pdev) +{ +	u8 id = 0; +	int ret; +	ret = pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) & id); +	return id; +} + +/** + *  s2io_init_pci -Initialization of PCI and PCI-X configuration registers . + *  @sp : private member of the device structure, which is a pointer to the   *  s2io_nic structure.   *  Description:   *  This function initializes a few of the PCI and PCI-X configuration registers @@ -4499,15 +5156,15 @@ static void s2io_link(nic_t * sp, int link)  static void s2io_init_pci(nic_t * sp)  { -	u16 pci_cmd = 0; +	u16 pci_cmd = 0, pcix_cmd = 0;  	/* Enable Data Parity Error Recovery in PCI-X command register. */  	pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, -			     &(sp->pcix_cmd)); +			     &(pcix_cmd));  	pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, -			      (sp->pcix_cmd | 1)); +			      (pcix_cmd | 1));  	pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, -			     &(sp->pcix_cmd)); +			     &(pcix_cmd));  	/* Set the PErr Response bit in PCI command register. */  	pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); @@ -4515,53 +5172,43 @@ static void s2io_init_pci(nic_t * sp)  			      (pci_cmd | PCI_COMMAND_PARITY));  	pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); -	/* Set MMRB count to 1024 in PCI-X Command register. */ -	sp->pcix_cmd &= 0xFFF3; -	pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, (sp->pcix_cmd | (0x1 << 2)));	/* MMRBC 1K */ -	pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, -			     &(sp->pcix_cmd)); - -	/*  Setting Maximum outstanding splits based on system type. */ -	sp->pcix_cmd &= 0xFF8F; - -	sp->pcix_cmd |= XENA_MAX_OUTSTANDING_SPLITS(0x1);	/* 2 splits. */ -	pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, -			      sp->pcix_cmd); -	pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, -			     &(sp->pcix_cmd));  	/* Forcibly disabling relaxed ordering capability of the card. */ -	sp->pcix_cmd &= 0xfffd; +	pcix_cmd &= 0xfffd;  	pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER, -			      sp->pcix_cmd); +			      pcix_cmd);  	pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, -			     &(sp->pcix_cmd)); +			     &(pcix_cmd));  }  MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");  MODULE_LICENSE("GPL");  module_param(tx_fifo_num, int, 0); -module_param_array(tx_fifo_len, int, NULL, 0);  module_param(rx_ring_num, int, 0); -module_param_array(rx_ring_sz, int, NULL, 0); -module_param(Stats_refresh_time, int, 0); +module_param_array(tx_fifo_len, uint, NULL, 0); +module_param_array(rx_ring_sz, uint, NULL, 0); +module_param_array(rts_frm_len, uint, NULL, 0); +module_param(use_continuous_tx_intrs, int, 1);  module_param(rmac_pause_time, int, 0);  module_param(mc_pause_threshold_q0q3, int, 0);  module_param(mc_pause_threshold_q4q7, int, 0);  module_param(shared_splits, int, 0);  module_param(tmac_util_period, int, 0);  module_param(rmac_util_period, int, 0); +module_param(bimodal, bool, 0);  #ifndef CONFIG_S2IO_NAPI  module_param(indicate_max_pkts, int, 0);  #endif +module_param(rxsync_frequency, int, 0); +  /** - *  s2io_init_nic - Initialization of the adapter .  + *  s2io_init_nic - Initialization of the adapter .   *  @pdev : structure containing the PCI related information of the device.   *  @pre: List of PCI devices supported by the driver listed in s2io_tbl.   *  Description:   *  The function initializes an adapter identified by the pci_dec structure. - *  All OS related initialization including memory and device structure and  - *  initlaization of the device private variable is done. Also the swapper  - *  control register is initialized to enable read and write into the I/O  + *  All OS related initialization including memory and device structure and + *  initlaization of the device private variable is done. Also the swapper + *  control register is initialized to enable read and write into the I/O   *  registers of the device.   *  Return value:   *  returns 0 on success and negative on failure. @@ -4572,7 +5219,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)  {  	nic_t *sp;  	struct net_device *dev; -	char *dev_name = "S2IO 10GE NIC";  	int i, j, ret;  	int dma_flag = FALSE;  	u32 mac_up, mac_down; @@ -4581,10 +5227,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)  	u16 subid;  	mac_info_t *mac_control;  	struct config_param *config; +	int mode; - -	DBG_PRINT(ERR_DBG, "Loading S2IO driver with %s\n", -		s2io_driver_version); +#ifdef CONFIG_S2IO_NAPI +	DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n"); +#endif  	if ((ret = pci_enable_device(pdev))) {  		DBG_PRINT(ERR_DBG, @@ -4595,7 +5242,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)  	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {  		DBG_PRINT(INIT_DBG, "s2io_init_nic: Using 64bit DMA\n");  		dma_flag = TRUE; -  		if (pci_set_consistent_dma_mask  		    (pdev, DMA_64BIT_MASK)) {  			DBG_PRINT(ERR_DBG, @@ -4635,34 +5281,41 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)  	memset(sp, 0, sizeof(nic_t));  	sp->dev = dev;  	sp->pdev = pdev; -	sp->vendor_id = pdev->vendor; -	sp->device_id = pdev->device;  	sp->high_dma_flag = dma_flag; -	sp->irq = pdev->irq;  	sp->device_enabled_once = FALSE; -	strcpy(sp->name, dev_name); + +	if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) || +		(pdev->device == PCI_DEVICE_ID_HERC_UNI)) +		sp->device_type = XFRAME_II_DEVICE; +	else +		sp->device_type = XFRAME_I_DEVICE;  	/* Initialize some PCI/PCI-X fields of the NIC. */  	s2io_init_pci(sp); -	/*  +	/*  	 * Setting the device configuration parameters. -	 * Most of these parameters can be specified by the user during  -	 * module insertion as they are module loadable parameters. If  -	 * these parameters are not not specified during load time, they  +	 * Most of these parameters can be specified by the user during +	 * module insertion as they are module loadable parameters. If +	 * these parameters are not not specified during load time, they  	 * are initialized with default values.  	 */  	mac_control = &sp->mac_control;  	config = &sp->config;  	/* Tx side parameters. */ -	tx_fifo_len[0] = DEFAULT_FIFO_LEN;	/* Default value. */ +	if (tx_fifo_len[0] == 0) +		tx_fifo_len[0] = DEFAULT_FIFO_LEN; /* Default value. */  	config->tx_fifo_num = tx_fifo_num;  	for (i = 0; i < MAX_TX_FIFOS; i++) {  		config->tx_cfg[i].fifo_len = tx_fifo_len[i];  		config->tx_cfg[i].fifo_priority = i;  	} +	/* mapping the QoS priority to the configured fifos */ +	for (i = 0; i < MAX_TX_FIFOS; i++) +		config->fifo_mapping[i] = fifo_map[config->tx_fifo_num][i]; +  	config->tx_intr_type = TXD_INT_TYPE_UTILZ;  	for (i = 0; i < config->tx_fifo_num; i++) {  		config->tx_cfg[i].f_no_snoop = @@ -4675,7 +5328,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)  	config->max_txds = MAX_SKB_FRAGS;  	/* Rx side parameters. */ -	rx_ring_sz[0] = SMALL_BLK_CNT;	/* Default value. */ +	if (rx_ring_sz[0] == 0) +		rx_ring_sz[0] = SMALL_BLK_CNT; /* Default value. */  	config->rx_ring_num = rx_ring_num;  	for (i = 0; i < MAX_RX_RINGS; i++) {  		config->rx_cfg[i].num_rxd = rx_ring_sz[i] * @@ -4699,10 +5353,13 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)  	for (i = 0; i < config->rx_ring_num; i++)  		atomic_set(&sp->rx_bufs_left[i], 0); +	/* Initialize the number of ISRs currently running */ +	atomic_set(&sp->isr_cnt, 0); +  	/*  initialize the shared memory used by the NIC and the host */  	if (init_shared_mem(sp)) {  		DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", -			  dev->name); +			  __FUNCTION__);  		ret = -ENOMEM;  		goto mem_alloc_failed;  	} @@ -4743,13 +5400,17 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)  	dev->do_ioctl = &s2io_ioctl;  	dev->change_mtu = &s2io_change_mtu;  	SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); +	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; +	dev->vlan_rx_register = s2io_vlan_rx_register; +	dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid; +  	/*  	 * will use eth_mac_addr() for  dev->set_mac_address  	 * mac address will be set every time dev->open() is called  	 */ -#ifdef CONFIG_S2IO_NAPI +#if defined(CONFIG_S2IO_NAPI)  	dev->poll = s2io_poll; -	dev->weight = 90; +	dev->weight = 32;  #endif  	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; @@ -4776,22 +5437,28 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)  		goto set_swap_failed;  	} -	/* Fix for all "FFs" MAC address problems observed on Alpha platforms */ -	fix_mac_address(sp); -	s2io_reset(sp); +	/* Verify if the Herc works on the slot its placed into */ +	if (sp->device_type & XFRAME_II_DEVICE) { +		mode = s2io_verify_pci_mode(sp); +		if (mode < 0) { +			DBG_PRINT(ERR_DBG, "%s: ", __FUNCTION__); +			DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode\n"); +			ret = -EBADSLT; +			goto set_swap_failed; +		} +	} -	/* -	 * Setting swapper control on the NIC, so the MAC address can be read. -	 */ -	if (s2io_set_swapper(sp)) { -		DBG_PRINT(ERR_DBG, -			  "%s: S2IO: swapper settings are wrong\n", -			  dev->name); -		ret = -EAGAIN; -		goto set_swap_failed; +	/* Not needed for Herc */ +	if (sp->device_type & XFRAME_I_DEVICE) { +		/* +		 * Fix for all "FFs" MAC address problems observed on +		 * Alpha platforms +		 */ +		fix_mac_address(sp); +		s2io_reset(sp);  	} -	/*   +	/*  	 * MAC address initialization.  	 * For now only one mac address will be read and used.  	 */ @@ -4814,37 +5481,28 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)  	sp->def_mac_addr[0].mac_addr[5] = (u8) (mac_down >> 16);  	sp->def_mac_addr[0].mac_addr[4] = (u8) (mac_down >> 24); -	DBG_PRINT(INIT_DBG, -		  "DEFAULT MAC ADDR:0x%02x-%02x-%02x-%02x-%02x-%02x\n", -		  sp->def_mac_addr[0].mac_addr[0], -		  sp->def_mac_addr[0].mac_addr[1], -		  sp->def_mac_addr[0].mac_addr[2], -		  sp->def_mac_addr[0].mac_addr[3], -		  sp->def_mac_addr[0].mac_addr[4], -		  sp->def_mac_addr[0].mac_addr[5]); -  	/*  Set the factory defined MAC address initially   */  	dev->addr_len = ETH_ALEN;  	memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN);  	/* -	 * Initialize the tasklet status and link state flags  -	 * and the card statte parameter +	 * Initialize the tasklet status and link state flags +	 * and the card state parameter  	 */  	atomic_set(&(sp->card_state), 0);  	sp->tasklet_status = 0;  	sp->link_state = 0; -  	/* Initialize spinlocks */  	spin_lock_init(&sp->tx_lock);  #ifndef CONFIG_S2IO_NAPI  	spin_lock_init(&sp->put_lock);  #endif +	spin_lock_init(&sp->rx_lock); -	/*  -	 * SXE-002: Configure link and activity LED to init state  -	 * on driver load.  +	/* +	 * SXE-002: Configure link and activity LED to init state +	 * on driver load.  	 */  	subid = sp->pdev->subsystem_device;  	if ((subid & 0xFF) >= 0x07) { @@ -4864,13 +5522,61 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)  		goto register_failed;  	} -	/*  -	 * Make Link state as off at this point, when the Link change  -	 * interrupt comes the state will be automatically changed to  +	if (sp->device_type & XFRAME_II_DEVICE) { +		DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ", +			  dev->name); +		DBG_PRINT(ERR_DBG, "(rev %d), Driver %s\n", +				get_xena_rev_id(sp->pdev), +				s2io_driver_version); +		DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", +			  sp->def_mac_addr[0].mac_addr[0], +			  sp->def_mac_addr[0].mac_addr[1], +			  sp->def_mac_addr[0].mac_addr[2], +			  sp->def_mac_addr[0].mac_addr[3], +			  sp->def_mac_addr[0].mac_addr[4], +			  sp->def_mac_addr[0].mac_addr[5]); +		mode = s2io_print_pci_mode(sp); +		if (mode < 0) { +			DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode "); +			ret = -EBADSLT; +			goto set_swap_failed; +		} +	} else { +		DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ", +			  dev->name); +		DBG_PRINT(ERR_DBG, "(rev %d), Driver %s\n", +					get_xena_rev_id(sp->pdev), +					s2io_driver_version); +		DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", +			  sp->def_mac_addr[0].mac_addr[0], +			  sp->def_mac_addr[0].mac_addr[1], +			  sp->def_mac_addr[0].mac_addr[2], +			  sp->def_mac_addr[0].mac_addr[3], +			  sp->def_mac_addr[0].mac_addr[4], +			  sp->def_mac_addr[0].mac_addr[5]); +	} + +	/* Initialize device name */ +	strcpy(sp->name, dev->name); +	if (sp->device_type & XFRAME_II_DEVICE) +		strcat(sp->name, ": Neterion Xframe II 10GbE adapter"); +	else +		strcat(sp->name, ": Neterion Xframe I 10GbE adapter"); + +	/* Initialize bimodal Interrupts */ +	sp->config.bimodal = bimodal; +	if (!(sp->device_type & XFRAME_II_DEVICE) && bimodal) { +		sp->config.bimodal = 0; +		DBG_PRINT(ERR_DBG,"%s:Bimodal intr not supported by Xframe I\n", +			dev->name); +	} + +	/* +	 * Make Link state as off at this point, when the Link change +	 * interrupt comes the state will be automatically changed to  	 * the right state.  	 */  	netif_carrier_off(dev); -	sp->last_link_state = LINK_DOWN;  	return 0; @@ -4891,11 +5597,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)  }  /** - * s2io_rem_nic - Free the PCI device  + * s2io_rem_nic - Free the PCI device   * @pdev: structure containing the PCI related information of the device. - * Description: This function is called by the Pci subsystem to release a  + * Description: This function is called by the Pci subsystem to release a   * PCI device and free up all resource held up by the device. This could - * be in response to a Hot plug event or when the driver is to be removed  + * be in response to a Hot plug event or when the driver is to be removed   * from memory.   */ @@ -4919,7 +5625,6 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)  	pci_disable_device(pdev);  	pci_release_regions(pdev);  	pci_set_drvdata(pdev, NULL); -  	free_netdev(dev);  } @@ -4935,11 +5640,11 @@ int __init s2io_starter(void)  }  /** - * s2io_closer - Cleanup routine for the driver  + * s2io_closer - Cleanup routine for the driver   * Description: This function is the cleanup routine for the driver. It unregist * ers the driver.   */ -static void s2io_closer(void) +void s2io_closer(void)  {  	pci_unregister_driver(&s2io_driver);  	DBG_PRINT(INIT_DBG, "cleanup done\n"); | 
