⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s2io.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
/************************************************************************ * s2io.c: A Linux PCI-X Ethernet driver for S2IO 10GbE Server NIC * Copyright(c) 2002-2005 S2IO Technologies * This software may be used and distributed according to the terms of * the GNU General Public License (GPL), incorporated herein by reference. * Drivers based on or derived from this code fall under the GPL and must * retain the authorship, copyright and license notice.  This file is not * a complete program and may only be used when the entire operating * system is licensed under the GPL. * 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  *			  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  *			  deprecated and also styling related comments. * 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. * ring_num : This can be used to program the number of receive rings used  * in the driver.  					 * frame_len: This is an array of size 8. Using this we can set the maximum  * size of the received frame that can be steered into the corrsponding  * receive ring. * ring_len: This defines the number of descriptors each ring can have. This  * is also an array of size 8. * fifo_num: This defines the number of Tx FIFOs thats used int the driver. * 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. * latency_timer: This input is programmed into the Latency timer register * in PCI Configuration space. ************************************************************************/#include<linux/config.h>#include<linux/module.h>#include<linux/types.h>#include<linux/errno.h>#include<linux/ioport.h>#include<linux/pci.h>#include<linux/kernel.h>#include<linux/netdevice.h>#include<linux/etherdevice.h>#include<linux/skbuff.h>#include<linux/init.h>#include<linux/delay.h>#include<linux/stddef.h>#include<linux/ioctl.h>#include<linux/timex.h>#include<linux/sched.h>#include<linux/ethtool.h>#include<asm/system.h>#include<asm/uaccess.h>#include<linux/version.h>#include<asm/io.h>#include<linux/workqueue.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.0";#define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \				      ADAPTER_STATUS_RMAC_LOCAL_FAULT)))#define TASKLET_IN_USE test_and_set_bit(0, \				(unsigned long *)(&sp->tasklet_status))#define PANIC	1#define LOW	2static inline int rx_buffer_level(nic_t * sp, int rxb_size, int ring){	int level = 0;	if ((sp->pkt_cnt[ring] - rxb_size) > 128) {		level = LOW;		if (rxb_size < sp->pkt_cnt[ring] / 8)			level = PANIC;	}	return level;}/* Ethtool related variables and Macros. */static char s2io_gstrings[][ETH_GSTRING_LEN] = {	"Register test\t(offline)",	"Eeprom test\t(offline)",	"Link test\t(online)",	"RLDRAM test\t(offline)",	"BIST Test\t(offline)"};static char ethtool_stats_keys[][ETH_GSTRING_LEN] = {	"tmac_frms",	"tmac_data_octets",	"tmac_drop_frms",	"tmac_mcst_frms",	"tmac_bcst_frms",	"tmac_pause_ctrl_frms",	"tmac_any_err_frms",	"tmac_vld_ip_octets",	"tmac_vld_ip",	"tmac_drop_ip",	"tmac_icmp",	"tmac_rst_tcp",	"tmac_tcp",	"tmac_udp",	"rmac_vld_frms",	"rmac_data_octets",	"rmac_fcs_err_frms",	"rmac_drop_frms",	"rmac_vld_mcst_frms",	"rmac_vld_bcst_frms",	"rmac_in_rng_len_err_frms",	"rmac_long_frms",	"rmac_pause_ctrl_frms",	"rmac_discarded_frms",	"rmac_usized_frms",	"rmac_osized_frms",	"rmac_frag_frms",	"rmac_jabber_frms",	"rmac_ip",	"rmac_ip_octets",	"rmac_hdr_err_ip",	"rmac_drop_ip",	"rmac_icmp",	"rmac_tcp",	"rmac_udp",	"rmac_err_drp_udp",	"rmac_pause_cnt",	"rmac_accepted_ip",	"rmac_err_tcp",};#define S2IO_STAT_LEN sizeof(ethtool_stats_keys)/ ETH_GSTRING_LEN#define S2IO_STAT_STRINGS_LEN S2IO_STAT_LEN * ETH_GSTRING_LEN#define S2IO_TEST_LEN	sizeof(s2io_gstrings) / ETH_GSTRING_LEN#define S2IO_STRINGS_LEN	S2IO_TEST_LEN * ETH_GSTRING_LEN/* Constants to be programmed into the Xena's registers to configure * the XAUI. */#define SWITCH_SIGN	0xA5A5A5A5A5A5A5A5ULL#define	END_SIGN	0x0static u64 default_mdio_cfg[] = {	/* Reset PMA PLL */	0xC001010000000000ULL, 0xC0010100000000E0ULL,	0xC0010100008000E4ULL,	/* Remove Reset from PMA PLL */	0xC001010000000000ULL, 0xC0010100000000E0ULL,	0xC0010100000000E4ULL,	END_SIGN};static u64 default_dtx_cfg[] = {	0x8000051500000000ULL, 0x80000515000000E0ULL,	0x80000515D93500E4ULL, 0x8001051500000000ULL,	0x80010515000000E0ULL, 0x80010515001E00E4ULL,	0x8002051500000000ULL, 0x80020515000000E0ULL,	0x80020515F21000E4ULL,	/* Set PADLOOPBACKN */	0x8002051500000000ULL, 0x80020515000000E0ULL,	0x80020515B20000E4ULL, 0x8003051500000000ULL,	0x80030515000000E0ULL, 0x80030515B20000E4ULL,	0x8004051500000000ULL, 0x80040515000000E0ULL,	0x80040515B20000E4ULL, 0x8005051500000000ULL,	0x80050515000000E0ULL, 0x80050515B20000E4ULL,	SWITCH_SIGN,	/* Remove PADLOOPBACKN */	0x8002051500000000ULL, 0x80020515000000E0ULL,	0x80020515F20000E4ULL, 0x8003051500000000ULL,	0x80030515000000E0ULL, 0x80030515F20000E4ULL,	0x8004051500000000ULL, 0x80040515000000E0ULL,	0x80040515F20000E4ULL, 0x8005051500000000ULL,	0x80050515000000E0ULL, 0x80050515F20000E4ULL,	END_SIGN};/* Constants for Fixing the MacAddress problem seen mostly on * Alpha machines. */static u64 fix_mac[] = {	0x0060000000000000ULL, 0x0060600000000000ULL,	0x0040600000000000ULL, 0x0000600000000000ULL,	0x0020600000000000ULL, 0x0060600000000000ULL,	0x0020600000000000ULL, 0x0060600000000000ULL,	0x0020600000000000ULL, 0x0060600000000000ULL,	0x0020600000000000ULL, 0x0060600000000000ULL,	0x0020600000000000ULL, 0x0060600000000000ULL,	0x0020600000000000ULL, 0x0060600000000000ULL,	0x0020600000000000ULL, 0x0060600000000000ULL,	0x0020600000000000ULL, 0x0060600000000000ULL,	0x0020600000000000ULL, 0x0060600000000000ULL,	0x0020600000000000ULL, 0x0060600000000000ULL,	0x0020600000000000ULL, 0x0000600000000000ULL,	0x0040600000000000ULL, 0x0060600000000000ULL,	END_SIGN};/* Module Loadable parameters. */static u32 ring_num;static u32 frame_len[MAX_RX_RINGS];static u32 ring_len[MAX_RX_RINGS];static u32 fifo_num;static u32 fifo_len[MAX_TX_FIFOS];static u32 rx_prio;static u32 tx_prio;static u8 latency_timer = 0;/*  * S2IO device table. * 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,	 PCI_ANY_ID, PCI_ANY_ID},	{PCI_VENDOR_ID_S2IO, PCI_DEVICE_ID_S2IO_UNI,	 PCI_ANY_ID, PCI_ANY_ID},	{0,}};MODULE_DEVICE_TABLE(pci, s2io_tbl);static struct pci_driver s2io_driver = {      .name = "S2IO",      .id_table = s2io_tbl,      .probe = s2io_init_nic,      .remove = __devexit_p(s2io_rem_nic),};/*   *  Input Arguments:  *  Device private variable. *  Return Value:  *  SUCCESS on success and an appropriate -ve value on failure. *  Description:  *  The function allocates the all memory areas shared  *  between the NIC and the driver. This includes Tx descriptors,  *  Rx descriptors and the statistics block. */static int initSharedMem(struct s2io_nic *nic){	u32 size;	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;	struct net_device *dev = nic->dev;	mac_info_t *mac_control;	struct config_param *config;	mac_control = &nic->mac_control;	config = &nic->config;	/* Allocation and initialization of TXDLs in FIOFs */	size = 0;	for (i = 0; i < config->TxFIFONum; i++) {		size += config->TxCfg[i].FifoLen;	}	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");		return FAILURE;	}	size *= (sizeof(TxD_t) * config->MaxTxDs);	mac_control->txd_list_mem = pci_alloc_consistent	    (nic->pdev, size, &mac_control->txd_list_mem_phy);	if (!mac_control->txd_list_mem) {		return -ENOMEM;	}	mac_control->txd_list_mem_sz = size;	tmp_v_addr = mac_control->txd_list_mem;	tmp_p_addr = mac_control->txd_list_mem_phy;	memset(tmp_v_addr, 0, size);	DBG_PRINT(INIT_DBG, "%s:List Mem PHY: 0x%llx\n", dev->name,		  (unsigned long long) tmp_p_addr);	for (i = 0; i < config->TxFIFONum; i++) {		mac_control->txdl_start_phy[i] = tmp_p_addr;		mac_control->txdl_start[i] = (TxD_t *) tmp_v_addr;		mac_control->tx_curr_put_info[i].offset = 0;		mac_control->tx_curr_put_info[i].fifo_len =		    config->TxCfg[i].FifoLen - 1;		mac_control->tx_curr_get_info[i].offset = 0;		mac_control->tx_curr_get_info[i].fifo_len =		    config->TxCfg[i].FifoLen - 1;		tmp_p_addr +=		    (config->TxCfg[i].FifoLen * (sizeof(TxD_t)) *		     config->MaxTxDs);		tmp_v_addr +=		    (config->TxCfg[i].FifoLen * (sizeof(TxD_t)) *		     config->MaxTxDs);	}	/* Allocation and initialization of RXDs in Rings */	size = 0;	for (i = 0; i < config->RxRingNum; i++) {		if (config->RxCfg[i].NumRxd % (MAX_RXDS_PER_BLOCK + 1)) {			DBG_PRINT(ERR_DBG, "%s: RxD count of ", dev->name);			DBG_PRINT(ERR_DBG, "Ring%d is not a multiple of ",				  i);			DBG_PRINT(ERR_DBG, "RxDs per Block");			return FAILURE;		}		size += config->RxCfg[i].NumRxd;		nic->block_count[i] =		    config->RxCfg[i].NumRxd / (MAX_RXDS_PER_BLOCK + 1);		nic->pkt_cnt[i] =		    config->RxCfg[i].NumRxd - nic->block_count[i];	}	size = (size * (sizeof(RxD_t)));	mac_control->rxd_ring_mem_sz = size;	for (i = 0; i < config->RxRingNum; 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 =		    config->RxCfg[i].NumRxd - 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 =		    config->RxCfg[i].NumRxd - 1;		blk_cnt =		    config->RxCfg[i].NumRxd / (MAX_RXDS_PER_BLOCK + 1);		/*  Allocating all the Rx blocks */		for (j = 0; j < blk_cnt; j++) {			size = (MAX_RXDS_PER_BLOCK + 1) * (sizeof(RxD_t));			tmp_v_addr = pci_alloc_consistent(nic->pdev, size,							  &tmp_p_addr);			if (tmp_v_addr == NULL) {				/* In case of failure, freeSharedMem() 				 * is called, which should free any 				 * memory that was alloced till the 				 * failure happened.				 */				nic->rx_blocks[i][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;		}		/* 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_next =			    nic->rx_blocks[i][(j + 1) %					      blk_cnt].block_virt_addr;			tmp_p_addr = nic->rx_blocks[i][j].block_dma_addr;			tmp_p_addr_next =			    nic->rx_blocks[i][(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 								 * marker.								 */			pre_rxd_blk->reserved_2_pNext_RxD_block =			    (unsigned long) tmp_v_addr_next;			pre_rxd_blk->pNext_RxD_Blk_physical =			    (u64) tmp_p_addr_next;		}	}	/* Allocation and initialization of Statistics block */	size = sizeof(StatInfo_t);	mac_control->stats_mem = pci_alloc_consistent	    (nic->pdev, size, &mac_control->stats_mem_phy);	if (!mac_control->stats_mem) {		/* In case of failure, freeSharedMem() is called, which 		 * should free any memory that was alloced till the 		 * failure happened.		 */		return -ENOMEM;	}	mac_control->stats_mem_sz = size;	tmp_v_addr = mac_control->stats_mem;	mac_control->StatsInfo = (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;}/*   *  Input Arguments:  *  Device peivate variable. *  Return Value:  *  NONE *  Description:  *  This function is to free all memory locations allocated by *  the initSharedMem() function and return it to the kernel. */static void freeSharedMem(struct s2io_nic *nic){	int i, j, blk_cnt, size;	void *tmp_v_addr;	dma_addr_t tmp_p_addr;	mac_info_t *mac_control;	struct config_param *config;	if (!nic)		return;	mac_control = &nic->mac_control;	config = &nic->config;	if (mac_control->txd_list_mem) {		pci_free_consistent(nic->pdev,				    mac_control->txd_list_mem_sz,				    mac_control->txd_list_mem,				    mac_control->txd_list_mem_phy);	}	size = (MAX_RXDS_PER_BLOCK + 1) * (sizeof(RxD_t));	for (i = 0; i < config->RxRingNum; i++) {		blk_cnt = nic->block_count[i];		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;			if (tmp_v_addr == NULL)				break;			pci_free_consistent(nic->pdev, size,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -