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

📄 myri10ge.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/************************************************************************* * myri10ge.c: Myricom Myri-10G Ethernet driver. * * Copyright (C) 2005 - 2007 Myricom, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of Myricom, Inc. nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * * If the eeprom on your board is not recent enough, you will need to get a * newer firmware image at: *   http://www.myri.com/scs/download-Myri10GE.html * * Contact Information: *   <help@myri.com> *   Myricom, Inc., 325N Santa Anita Avenue, Arcadia, CA 91006 *************************************************************************/#include <linux/tcp.h>#include <linux/netdevice.h>#include <linux/skbuff.h>#include <linux/string.h>#include <linux/module.h>#include <linux/pci.h>#include <linux/dma-mapping.h>#include <linux/etherdevice.h>#include <linux/if_ether.h>#include <linux/if_vlan.h>#include <linux/inet_lro.h>#include <linux/ip.h>#include <linux/inet.h>#include <linux/in.h>#include <linux/ethtool.h>#include <linux/firmware.h>#include <linux/delay.h>#include <linux/version.h>#include <linux/timer.h>#include <linux/vmalloc.h>#include <linux/crc32.h>#include <linux/moduleparam.h>#include <linux/io.h>#include <linux/log2.h>#include <net/checksum.h>#include <net/ip.h>#include <net/tcp.h>#include <asm/byteorder.h>#include <asm/io.h>#include <asm/processor.h>#ifdef CONFIG_MTRR#include <asm/mtrr.h>#endif#include "myri10ge_mcp.h"#include "myri10ge_mcp_gen_header.h"#define MYRI10GE_VERSION_STR "1.3.2-1.287"MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");MODULE_AUTHOR("Maintainer: help@myri.com");MODULE_VERSION(MYRI10GE_VERSION_STR);MODULE_LICENSE("Dual BSD/GPL");#define MYRI10GE_MAX_ETHER_MTU 9014#define MYRI10GE_ETH_STOPPED 0#define MYRI10GE_ETH_STOPPING 1#define MYRI10GE_ETH_STARTING 2#define MYRI10GE_ETH_RUNNING 3#define MYRI10GE_ETH_OPEN_FAILED 4#define MYRI10GE_EEPROM_STRINGS_SIZE 256#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2)#define MYRI10GE_MAX_LRO_DESCRIPTORS 8#define MYRI10GE_LRO_MAX_PKTS 64#define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff)#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff#define MYRI10GE_ALLOC_ORDER 0#define MYRI10GE_ALLOC_SIZE ((1 << MYRI10GE_ALLOC_ORDER) * PAGE_SIZE)#define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1)struct myri10ge_rx_buffer_state {	struct page *page;	int page_offset;	 DECLARE_PCI_UNMAP_ADDR(bus)	 DECLARE_PCI_UNMAP_LEN(len)};struct myri10ge_tx_buffer_state {	struct sk_buff *skb;	int last;	 DECLARE_PCI_UNMAP_ADDR(bus)	 DECLARE_PCI_UNMAP_LEN(len)};struct myri10ge_cmd {	u32 data0;	u32 data1;	u32 data2;};struct myri10ge_rx_buf {	struct mcp_kreq_ether_recv __iomem *lanai;	/* lanai ptr for recv ring */	u8 __iomem *wc_fifo;	/* w/c rx dma addr fifo address */	struct mcp_kreq_ether_recv *shadow;	/* host shadow of recv ring */	struct myri10ge_rx_buffer_state *info;	struct page *page;	dma_addr_t bus;	int page_offset;	int cnt;	int fill_cnt;	int alloc_fail;	int mask;		/* number of rx slots -1 */	int watchdog_needed;};struct myri10ge_tx_buf {	struct mcp_kreq_ether_send __iomem *lanai;	/* lanai ptr for sendq */	u8 __iomem *wc_fifo;	/* w/c send fifo address */	struct mcp_kreq_ether_send *req_list;	/* host shadow of sendq */	char *req_bytes;	struct myri10ge_tx_buffer_state *info;	int mask;		/* number of transmit slots -1  */	int boundary;		/* boundary transmits cannot cross */	int req ____cacheline_aligned;	/* transmit slots submitted     */	int pkt_start;		/* packets started */	int done ____cacheline_aligned;	/* transmit slots completed     */	int pkt_done;		/* packets completed */};struct myri10ge_rx_done {	struct mcp_slot *entry;	dma_addr_t bus;	int cnt;	int idx;	struct net_lro_mgr lro_mgr;	struct net_lro_desc lro_desc[MYRI10GE_MAX_LRO_DESCRIPTORS];};struct myri10ge_priv {	int running;		/* running?             */	int csum_flag;		/* rx_csums?            */	struct myri10ge_tx_buf tx;	/* transmit ring        */	struct myri10ge_rx_buf rx_small;	struct myri10ge_rx_buf rx_big;	struct myri10ge_rx_done rx_done;	int small_bytes;	int big_bytes;	struct net_device *dev;	struct napi_struct napi;	struct net_device_stats stats;	u8 __iomem *sram;	int sram_size;	unsigned long board_span;	unsigned long iomem_base;	__be32 __iomem *irq_claim;	__be32 __iomem *irq_deassert;	char *mac_addr_string;	struct mcp_cmd_response *cmd;	dma_addr_t cmd_bus;	struct mcp_irq_data *fw_stats;	dma_addr_t fw_stats_bus;	struct pci_dev *pdev;	int msi_enabled;	__be32 link_state;	unsigned int rdma_tags_available;	int intr_coal_delay;	__be32 __iomem *intr_coal_delay_ptr;	int mtrr;	int wc_enabled;	int wake_queue;	int stop_queue;	int down_cnt;	wait_queue_head_t down_wq;	struct work_struct watchdog_work;	struct timer_list watchdog_timer;	int watchdog_tx_done;	int watchdog_tx_req;	int watchdog_pause;	int watchdog_resets;	int tx_linearized;	int pause;	char *fw_name;	char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE];	char fw_version[128];	int fw_ver_major;	int fw_ver_minor;	int fw_ver_tiny;	int adopted_rx_filter_bug;	u8 mac_addr[6];		/* eeprom mac address */	unsigned long serial_number;	int vendor_specific_offset;	int fw_multicast_support;	unsigned long features;	u32 max_tso6;	u32 read_dma;	u32 write_dma;	u32 read_write_dma;	u32 link_changes;	u32 msg_enable;};static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat";static char *myri10ge_fw_aligned = "myri10ge_eth_z8e.dat";static char *myri10ge_fw_name = NULL;module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name\n");static int myri10ge_ecrc_enable = 1;module_param(myri10ge_ecrc_enable, int, S_IRUGO);MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E\n");static int myri10ge_max_intr_slots = 1024;module_param(myri10ge_max_intr_slots, int, S_IRUGO);MODULE_PARM_DESC(myri10ge_max_intr_slots, "Interrupt queue slots\n");static int myri10ge_small_bytes = -1;	/* -1 == auto */module_param(myri10ge_small_bytes, int, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(myri10ge_small_bytes, "Threshold of small packets\n");static int myri10ge_msi = 1;	/* enable msi by default */module_param(myri10ge_msi, int, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(myri10ge_msi, "Enable Message Signalled Interrupts\n");static int myri10ge_intr_coal_delay = 75;module_param(myri10ge_intr_coal_delay, int, S_IRUGO);MODULE_PARM_DESC(myri10ge_intr_coal_delay, "Interrupt coalescing delay\n");static int myri10ge_flow_control = 1;module_param(myri10ge_flow_control, int, S_IRUGO);MODULE_PARM_DESC(myri10ge_flow_control, "Pause parameter\n");static int myri10ge_deassert_wait = 1;module_param(myri10ge_deassert_wait, int, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(myri10ge_deassert_wait,		 "Wait when deasserting legacy interrupts\n");static int myri10ge_force_firmware = 0;module_param(myri10ge_force_firmware, int, S_IRUGO);MODULE_PARM_DESC(myri10ge_force_firmware,		 "Force firmware to assume aligned completions\n");static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;module_param(myri10ge_initial_mtu, int, S_IRUGO);MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n");static int myri10ge_napi_weight = 64;module_param(myri10ge_napi_weight, int, S_IRUGO);MODULE_PARM_DESC(myri10ge_napi_weight, "Set NAPI weight\n");static int myri10ge_watchdog_timeout = 1;module_param(myri10ge_watchdog_timeout, int, S_IRUGO);MODULE_PARM_DESC(myri10ge_watchdog_timeout, "Set watchdog timeout\n");static int myri10ge_max_irq_loops = 1048576;module_param(myri10ge_max_irq_loops, int, S_IRUGO);MODULE_PARM_DESC(myri10ge_max_irq_loops,		 "Set stuck legacy IRQ detection threshold\n");#define MYRI10GE_MSG_DEFAULT NETIF_MSG_LINKstatic int myri10ge_debug = -1;	/* defaults above */module_param(myri10ge_debug, int, 0);MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");static int myri10ge_lro = 1;module_param(myri10ge_lro, int, S_IRUGO);MODULE_PARM_DESC(myri10ge_lro, "Enable large receive offload\n");static int myri10ge_lro_max_pkts = MYRI10GE_LRO_MAX_PKTS;module_param(myri10ge_lro_max_pkts, int, S_IRUGO);MODULE_PARM_DESC(myri10ge_lro, "Number of LRO packets to be aggregated\n");static int myri10ge_fill_thresh = 256;module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n");static int myri10ge_reset_recover = 1;static int myri10ge_wcfifo = 0;module_param(myri10ge_wcfifo, int, S_IRUGO);MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n");#define MYRI10GE_FW_OFFSET 1024*1024#define MYRI10GE_HIGHPART_TO_U32(X) \(sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)#define MYRI10GE_LOWPART_TO_U32(X) ((u32)(X))#define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)static void myri10ge_set_multicast_list(struct net_device *dev);static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev);static inline void put_be32(__be32 val, __be32 __iomem * p){	__raw_writel((__force __u32) val, (__force void __iomem *)p);}static intmyri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,		  struct myri10ge_cmd *data, int atomic){	struct mcp_cmd *buf;	char buf_bytes[sizeof(*buf) + 8];	struct mcp_cmd_response *response = mgp->cmd;	char __iomem *cmd_addr = mgp->sram + MXGEFW_ETH_CMD;	u32 dma_low, dma_high, result, value;	int sleep_total = 0;	/* ensure buf is aligned to 8 bytes */	buf = (struct mcp_cmd *)ALIGN((unsigned long)buf_bytes, 8);	buf->data0 = htonl(data->data0);	buf->data1 = htonl(data->data1);	buf->data2 = htonl(data->data2);	buf->cmd = htonl(cmd);	dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);	dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);	buf->response_addr.low = htonl(dma_low);	buf->response_addr.high = htonl(dma_high);	response->result = htonl(MYRI10GE_NO_RESPONSE_RESULT);	mb();	myri10ge_pio_copy(cmd_addr, buf, sizeof(*buf));	/* wait up to 15ms. Longest command is the DMA benchmark,	 * which is capped at 5ms, but runs from a timeout handler	 * that runs every 7.8ms. So a 15ms timeout leaves us with	 * a 2.2ms margin	 */	if (atomic) {		/* if atomic is set, do not sleep,		 * and try to get the completion quickly		 * (1ms will be enough for those commands) */		for (sleep_total = 0;		     sleep_total < 1000		     && response->result == htonl(MYRI10GE_NO_RESPONSE_RESULT);		     sleep_total += 10)			udelay(10);	} else {		/* use msleep for most command */		for (sleep_total = 0;		     sleep_total < 15		     && response->result == htonl(MYRI10GE_NO_RESPONSE_RESULT);		     sleep_total++)			msleep(1);	}	result = ntohl(response->result);	value = ntohl(response->data);	if (result != MYRI10GE_NO_RESPONSE_RESULT) {		if (result == 0) {			data->data0 = value;			return 0;		} else if (result == MXGEFW_CMD_UNKNOWN) {			return -ENOSYS;		} else if (result == MXGEFW_CMD_ERROR_UNALIGNED) {			return -E2BIG;		} else {			dev_err(&mgp->pdev->dev,				"command %d failed, result = %d\n",				cmd, result);			return -ENXIO;		}	}	dev_err(&mgp->pdev->dev, "command %d timed out, result = %d\n",		cmd, result);	return -EAGAIN;}/* * The eeprom strings on the lanaiX have the format * SN=x\0 * MAC=x:x:x:x:x:x\0 * PT:ddd mmm xx xx:xx:xx xx\0 * PV:ddd mmm xx xx:xx:xx xx\0 */static int myri10ge_read_mac_addr(struct myri10ge_priv *mgp){	char *ptr, *limit;	int i;	ptr = mgp->eeprom_strings;	limit = mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE;	while (*ptr != '\0' && ptr < limit) {		if (memcmp(ptr, "MAC=", 4) == 0) {			ptr += 4;			mgp->mac_addr_string = ptr;			for (i = 0; i < 6; i++) {				if ((ptr + 2) > limit)					goto abort;				mgp->mac_addr[i] =				    simple_strtoul(ptr, &ptr, 16);				ptr += 1;			}		}		if (memcmp((const void *)ptr, "SN=", 3) == 0) {			ptr += 3;			mgp->serial_number = simple_strtoul(ptr, &ptr, 10);		}		while (ptr < limit && *ptr++) ;	}	return 0;abort:	dev_err(&mgp->pdev->dev, "failed to parse eeprom_strings\n");	return -ENXIO;}/* * Enable or disable periodic RDMAs from the host to make certain * chipsets resend dropped PCIe messages */static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable){	char __iomem *submit;	__be32 buf[16];	u32 dma_low, dma_high;	int i;	/* clear confirmation addr */	mgp->cmd->data = 0;	mb();	/* send a rdma command to the PCIe engine, and wait for the

⌨️ 快捷键说明

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