📄 s2io.c
字号:
/************************************************************************ * s2io.c: A Linux PCI-X Ethernet driver for Neterion 10GbE Server NIC * Copyright(c) 2002-2007 Neterion Inc. * 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. * * rx_ring_num : This can be used to program the number of receive rings used * in the driver. * rx_ring_sz: This defines the number of receive blocks each ring can have. * This is also an array of size 8. * rx_ring_mode: This defines the operation mode of all 8 rings. The valid * values are 1, 2. * 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 descriptors that can be associated with each corresponding FIFO. * intr_type: This defines the type of interrupt. The values can be 0(INTA), * 2(MSI_X). Default value is '2(MSI_X)' * lro_enable: Specifies whether to enable Large Receive Offload (LRO) or not. * Possible values '1' for enable '0' for disable. Default is '0' * lro_max_pkts: This parameter defines maximum number of packets can be * aggregated as a single large packet * napi: This parameter used to enable/disable NAPI (polling Rx) * Possible values '1' for enable and '0' for disable. Default is '1' * ufo: This parameter used to enable/disable UDP Fragmentation Offload(UFO) * Possible values '1' for enable and '0' for disable. Default is '0' * vlan_tag_strip: This can be used to enable or disable vlan stripping. * Possible values '1' for enable , '0' for disable. * Default is '2' - which means disable in promisc mode * and enable in non-promiscuous mode. ************************************************************************/#include <linux/module.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/pci.h>#include <linux/dma-mapping.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/ethtool.h>#include <linux/workqueue.h>#include <linux/if_vlan.h>#include <linux/ip.h>#include <linux/tcp.h>#include <net/tcp.h>#include <asm/system.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/div64.h>#include <asm/irq.h>/* local include */#include "s2io.h"#include "s2io-regs.h"#define DRV_VERSION "2.0.26.17"/* S2io Driver name & version. */static char s2io_driver_name[] = "Neterion";static char s2io_driver_version[] = DRV_VERSION;static int rxd_size[2] = {32,48};static int rxd_count[2] = {127,85};static inline int RXD_IS_UP2DT(struct 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(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)))#define TASKLET_IN_USE test_and_set_bit(0, (&sp->tasklet_status))#define PANIC 1#define LOW 2static inline int rx_buffer_level(struct s2io_nic * sp, int rxb_size, int ring){ struct mac_info *mac_control; mac_control = &sp->mac_control; if (rxb_size <= rxd_count[sp->rxd_mode]) return PANIC; else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) return LOW; return 0;}static inline int is_s2io_card_up(const struct s2io_nic * sp){ return test_bit(__S2IO_STATE_CARD_UP, &sp->state);}/* 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_xena_stats_keys[][ETH_GSTRING_LEN] = { {"tmac_frms"}, {"tmac_data_octets"}, {"tmac_drop_frms"}, {"tmac_mcst_frms"}, {"tmac_bcst_frms"}, {"tmac_pause_ctrl_frms"}, {"tmac_ttl_octets"}, {"tmac_ucst_frms"}, {"tmac_nucst_frms"}, {"tmac_any_err_frms"}, {"tmac_ttl_less_fb_octets"}, {"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_out_rng_len_err_frms"}, {"rmac_long_frms"}, {"rmac_pause_ctrl_frms"}, {"rmac_unsup_ctrl_frms"}, {"rmac_ttl_octets"}, {"rmac_accepted_ucst_frms"}, {"rmac_accepted_nucst_frms"}, {"rmac_discarded_frms"}, {"rmac_drop_events"}, {"rmac_ttl_less_fb_octets"}, {"rmac_ttl_frms"}, {"rmac_usized_frms"}, {"rmac_osized_frms"}, {"rmac_frag_frms"}, {"rmac_jabber_frms"}, {"rmac_ttl_64_frms"}, {"rmac_ttl_65_127_frms"}, {"rmac_ttl_128_255_frms"}, {"rmac_ttl_256_511_frms"}, {"rmac_ttl_512_1023_frms"}, {"rmac_ttl_1024_1518_frms"}, {"rmac_ip"}, {"rmac_ip_octets"}, {"rmac_hdr_err_ip"}, {"rmac_drop_ip"}, {"rmac_icmp"}, {"rmac_tcp"}, {"rmac_udp"}, {"rmac_err_drp_udp"}, {"rmac_xgmii_err_sym"}, {"rmac_frms_q0"}, {"rmac_frms_q1"}, {"rmac_frms_q2"}, {"rmac_frms_q3"}, {"rmac_frms_q4"}, {"rmac_frms_q5"}, {"rmac_frms_q6"}, {"rmac_frms_q7"}, {"rmac_full_q0"}, {"rmac_full_q1"}, {"rmac_full_q2"}, {"rmac_full_q3"}, {"rmac_full_q4"}, {"rmac_full_q5"}, {"rmac_full_q6"}, {"rmac_full_q7"}, {"rmac_pause_cnt"}, {"rmac_xgmii_data_err_cnt"}, {"rmac_xgmii_ctrl_err_cnt"}, {"rmac_accepted_ip"}, {"rmac_err_tcp"}, {"rd_req_cnt"}, {"new_rd_req_cnt"}, {"new_rd_req_rtry_cnt"}, {"rd_rtry_cnt"}, {"wr_rtry_rd_ack_cnt"}, {"wr_req_cnt"}, {"new_wr_req_cnt"}, {"new_wr_req_rtry_cnt"}, {"wr_rtry_cnt"}, {"wr_disc_cnt"}, {"rd_rtry_wr_ack_cnt"}, {"txp_wr_cnt"}, {"txd_rd_cnt"}, {"txd_wr_cnt"}, {"rxd_rd_cnt"}, {"rxd_wr_cnt"}, {"txf_rd_cnt"}, {"rxf_wr_cnt"}};static char ethtool_enhanced_stats_keys[][ETH_GSTRING_LEN] = { {"rmac_ttl_1519_4095_frms"}, {"rmac_ttl_4096_8191_frms"}, {"rmac_ttl_8192_max_frms"}, {"rmac_ttl_gt_max_frms"}, {"rmac_osized_alt_frms"}, {"rmac_jabber_alt_frms"}, {"rmac_gt_max_alt_frms"}, {"rmac_vlan_frms"}, {"rmac_len_discard"}, {"rmac_fcs_discard"}, {"rmac_pf_discard"}, {"rmac_da_discard"}, {"rmac_red_discard"}, {"rmac_rts_discard"}, {"rmac_ingm_full_discard"}, {"link_fault_cnt"}};static char ethtool_driver_stats_keys[][ETH_GSTRING_LEN] = { {"\n DRIVER STATISTICS"}, {"single_bit_ecc_errs"}, {"double_bit_ecc_errs"}, {"parity_err_cnt"}, {"serious_err_cnt"}, {"soft_reset_cnt"}, {"fifo_full_cnt"}, {"ring_0_full_cnt"}, {"ring_1_full_cnt"}, {"ring_2_full_cnt"}, {"ring_3_full_cnt"}, {"ring_4_full_cnt"}, {"ring_5_full_cnt"}, {"ring_6_full_cnt"}, {"ring_7_full_cnt"}, {"alarm_transceiver_temp_high"}, {"alarm_transceiver_temp_low"}, {"alarm_laser_bias_current_high"}, {"alarm_laser_bias_current_low"}, {"alarm_laser_output_power_high"}, {"alarm_laser_output_power_low"}, {"warn_transceiver_temp_high"}, {"warn_transceiver_temp_low"}, {"warn_laser_bias_current_high"}, {"warn_laser_bias_current_low"}, {"warn_laser_output_power_high"}, {"warn_laser_output_power_low"}, {"lro_aggregated_pkts"}, {"lro_flush_both_count"}, {"lro_out_of_sequence_pkts"}, {"lro_flush_due_to_max_pkts"}, {"lro_avg_aggr_pkts"}, {"mem_alloc_fail_cnt"}, {"pci_map_fail_cnt"}, {"watchdog_timer_cnt"}, {"mem_allocated"}, {"mem_freed"}, {"link_up_cnt"}, {"link_down_cnt"}, {"link_up_time"}, {"link_down_time"}, {"tx_tcode_buf_abort_cnt"}, {"tx_tcode_desc_abort_cnt"}, {"tx_tcode_parity_err_cnt"}, {"tx_tcode_link_loss_cnt"}, {"tx_tcode_list_proc_err_cnt"}, {"rx_tcode_parity_err_cnt"}, {"rx_tcode_abort_cnt"}, {"rx_tcode_parity_abort_cnt"}, {"rx_tcode_rda_fail_cnt"}, {"rx_tcode_unkn_prot_cnt"}, {"rx_tcode_fcs_err_cnt"}, {"rx_tcode_buf_size_err_cnt"}, {"rx_tcode_rxd_corrupt_cnt"}, {"rx_tcode_unkn_err_cnt"}, {"tda_err_cnt"}, {"pfc_err_cnt"}, {"pcc_err_cnt"}, {"tti_err_cnt"}, {"tpa_err_cnt"}, {"sm_err_cnt"}, {"lso_err_cnt"}, {"mac_tmac_err_cnt"}, {"mac_rmac_err_cnt"}, {"xgxs_txgxs_err_cnt"}, {"xgxs_rxgxs_err_cnt"}, {"rc_err_cnt"}, {"prc_pcix_err_cnt"}, {"rpa_err_cnt"}, {"rda_err_cnt"}, {"rti_err_cnt"}, {"mc_err_cnt"}};#define S2IO_XENA_STAT_LEN sizeof(ethtool_xena_stats_keys)/ ETH_GSTRING_LEN#define S2IO_ENHANCED_STAT_LEN sizeof(ethtool_enhanced_stats_keys)/ \ ETH_GSTRING_LEN#define S2IO_DRIVER_STAT_LEN sizeof(ethtool_driver_stats_keys)/ ETH_GSTRING_LEN#define XFRAME_I_STAT_LEN (S2IO_XENA_STAT_LEN + S2IO_DRIVER_STAT_LEN )#define XFRAME_II_STAT_LEN (XFRAME_I_STAT_LEN + S2IO_ENHANCED_STAT_LEN )#define XFRAME_I_STAT_STRINGS_LEN ( XFRAME_I_STAT_LEN * ETH_GSTRING_LEN )#define XFRAME_II_STAT_STRINGS_LEN ( XFRAME_II_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#define S2IO_TIMER_CONF(timer, handle, arg, exp) \ init_timer(&timer); \ timer.function = handle; \ timer.data = (unsigned long) arg; \ mod_timer(&timer, (jiffies + exp)) \/* copy mac addr to def_mac_addr array */static void do_s2io_copy_mac_addr(struct s2io_nic *sp, int offset, u64 mac_addr){ sp->def_mac_addr[offset].mac_addr[5] = (u8) (mac_addr); sp->def_mac_addr[offset].mac_addr[4] = (u8) (mac_addr >> 8); sp->def_mac_addr[offset].mac_addr[3] = (u8) (mac_addr >> 16); sp->def_mac_addr[offset].mac_addr[2] = (u8) (mac_addr >> 24); sp->def_mac_addr[offset].mac_addr[1] = (u8) (mac_addr >> 32); sp->def_mac_addr[offset].mac_addr[0] = (u8) (mac_addr >> 40);}/* Add the vlan */static void s2io_vlan_rx_register(struct net_device *dev, struct vlan_group *grp){ struct s2io_nic *nic = dev->priv; unsigned long flags; spin_lock_irqsave(&nic->tx_lock, flags); nic->vlgrp = grp; spin_unlock_irqrestore(&nic->tx_lock, flags);}/* A flag indicating whether 'RX_PA_CFG_STRIP_VLAN_TAG' bit is set or not */static int vlan_strip_flag;/* * Constants to be programmed into the Xena's registers, to configure * the XAUI. */#define END_SIGN 0x0static const 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 const u64 xena_dtx_cfg[] = { /* Set address */ 0x8000051500000000ULL, 0x80000515000000E0ULL, /* Write data */ 0x80000515D9350004ULL, 0x80000515D93500E4ULL, /* Set address */ 0x8001051500000000ULL, 0x80010515000000E0ULL, /* Write data */ 0x80010515001E0004ULL, 0x80010515001E00E4ULL, /* Set address */ 0x8002051500000000ULL, 0x80020515000000E0ULL, /* Write data */ 0x80020515F2100004ULL, 0x80020515F21000E4ULL, END_SIGN};/* * Constants for Fixing the MacAddress problem seen mostly on * Alpha machines. */static const 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};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -