diff options
Diffstat (limited to 'drivers/net/netxen')
-rw-r--r-- | drivers/net/netxen/Makefile | 9 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic.h | 572 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_ctx.c | 116 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_ethtool.c | 123 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hdr.h | 125 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 854 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.h | 132 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 400 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 1462 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_niu.c | 550 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_phan_reg.h | 178 |
11 files changed, 2203 insertions, 2318 deletions
diff --git a/drivers/net/netxen/Makefile b/drivers/net/netxen/Makefile index cf01a9130c9..11d94e2434e 100644 --- a/drivers/net/netxen/Makefile +++ b/drivers/net/netxen/Makefile @@ -1,4 +1,5 @@ # Copyright (C) 2003 - 2009 NetXen, Inc. +# Copyright (C) 2009 - QLogic Corporation. # All rights reserved. # # This program is free software; you can redistribute it and/or @@ -19,16 +20,10 @@ # The full GNU General Public License is included in this distribution # in the file called LICENSE. # -# Contact Information: -# info@netxen.com -# NetXen Inc, -# 18922 Forge Drive -# Cupertino, CA 95014-0701 -# # obj-$(CONFIG_NETXEN_NIC) := netxen_nic.o netxen_nic-y := netxen_nic_hw.o netxen_nic_main.o netxen_nic_init.o \ - netxen_nic_ethtool.o netxen_nic_niu.o netxen_nic_ctx.o + netxen_nic_ethtool.o netxen_nic_ctx.o diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index a9c1fcca5e7..7384f59df61 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2003 - 2009 NetXen, Inc. + * Copyright (C) 2009 - QLogic Corporation. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -20,12 +21,6 @@ * The full GNU General Public License is included in this distribution * in the file called LICENSE. * - * Contact Information: - * info@netxen.com - * NetXen Inc, - * 18922 Forge Drive - * Cupertino, CA 95014-0701 - * */ #ifndef _NETXEN_NIC_H_ @@ -53,12 +48,13 @@ #include <asm/io.h> #include <asm/byteorder.h> +#include "netxen_nic_hdr.h" #include "netxen_nic_hw.h" #define _NETXEN_NIC_LINUX_MAJOR 4 #define _NETXEN_NIC_LINUX_MINOR 0 -#define _NETXEN_NIC_LINUX_SUBVERSION 30 -#define NETXEN_NIC_LINUX_VERSIONID "4.0.30" +#define _NETXEN_NIC_LINUX_SUBVERSION 50 +#define NETXEN_NIC_LINUX_VERSIONID "4.0.50" #define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) #define _major(v) (((v) >> 24) & 0xff) @@ -143,18 +139,14 @@ #define NX_ETHERMTU 1500 #define NX_MAX_ETHERHDR 32 /* This contains some padding */ -#define NX_RX_NORMAL_BUF_MAX_LEN (NX_MAX_ETHERHDR + NX_ETHERMTU) +#define NX_P2_RX_BUF_MAX_LEN 1760 +#define NX_P3_RX_BUF_MAX_LEN (NX_MAX_ETHERHDR + NX_ETHERMTU) #define NX_P2_RX_JUMBO_BUF_MAX_LEN (NX_MAX_ETHERHDR + P2_MAX_MTU) #define NX_P3_RX_JUMBO_BUF_MAX_LEN (NX_MAX_ETHERHDR + P3_MAX_MTU) #define NX_CT_DEFAULT_RX_BUF_LEN 2048 +#define NX_LRO_BUFFER_EXTRA 2048 -#define MAX_RX_BUFFER_LENGTH 1760 -#define MAX_RX_JUMBO_BUFFER_LENGTH 8062 -#define MAX_RX_LRO_BUFFER_LENGTH (8062) -#define RX_DMA_MAP_LEN (MAX_RX_BUFFER_LENGTH - 2) -#define RX_JUMBO_DMA_MAP_LEN \ - (MAX_RX_JUMBO_BUFFER_LENGTH - 2) -#define RX_LRO_DMA_MAP_LEN (MAX_RX_LRO_BUFFER_LENGTH - 2) +#define NX_RX_LRO_BUFFER_LENGTH (8060) /* * Maximum number of ring contexts @@ -181,6 +173,7 @@ #define MAX_BUFFERS_PER_CMD 32 #define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + 4) +#define NX_MAX_TX_TIMEOUTS 2 /* * Following are the states of the Phantom. Phantom will set them and @@ -200,13 +193,20 @@ #define RCV_RING_JUMBO 1 #define RCV_RING_LRO 2 -#define MAX_CMD_DESCRIPTORS 4096 -#define MAX_RCV_DESCRIPTORS 16384 -#define MAX_CMD_DESCRIPTORS_HOST 1024 -#define MAX_RCV_DESCRIPTORS_1G 2048 -#define MAX_RCV_DESCRIPTORS_10G 4096 -#define MAX_JUMBO_RCV_DESCRIPTORS 1024 +#define MIN_CMD_DESCRIPTORS 64 +#define MIN_RCV_DESCRIPTORS 64 +#define MIN_JUMBO_DESCRIPTORS 32 + +#define MAX_CMD_DESCRIPTORS 1024 +#define MAX_RCV_DESCRIPTORS_1G 4096 +#define MAX_RCV_DESCRIPTORS_10G 8192 +#define MAX_JUMBO_RCV_DESCRIPTORS_1G 512 +#define MAX_JUMBO_RCV_DESCRIPTORS_10G 1024 #define MAX_LRO_RCV_DESCRIPTORS 8 + +#define DEFAULT_RCV_DESCRIPTORS_1G 2048 +#define DEFAULT_RCV_DESCRIPTORS_10G 4096 + #define NETXEN_CTX_SIGNATURE 0xdee0 #define NETXEN_CTX_SIGNATURE_V2 0x0002dee0 #define NETXEN_CTX_RESET 0xbad0 @@ -225,7 +225,7 @@ #define MPORT_SINGLE_FUNCTION_MODE 0x1111 #define MPORT_MULTI_FUNCTION_MODE 0x2222 -#include "netxen_nic_phan_reg.h" +#define NX_MAX_PCI_FUNC 8 /* * NetXen host-peg signal message structure @@ -302,6 +302,10 @@ struct netxen_ring_ctx { #define FLAGS_IPSEC_SA_ADD 0x04 #define FLAGS_IPSEC_SA_DELETE 0x08 #define FLAGS_VLAN_TAGGED 0x10 +#define FLAGS_VLAN_OOB 0x40 + +#define netxen_set_tx_vlan_tci(cmd_desc, v) \ + (cmd_desc)->vlan_TCI = cpu_to_le16(v); #define netxen_set_cmd_desc_port(cmd_desc, var) \ ((cmd_desc)->port_ctxid |= ((var) & 0x0F)) @@ -316,58 +320,33 @@ struct netxen_ring_ctx { cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)) #define netxen_set_tx_frags_len(_desc, _frags, _len) \ - (_desc)->num_of_buffers_total_length = \ + (_desc)->nfrags__length = \ cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8)) struct cmd_desc_type0 { u8 tcp_hdr_offset; /* For LSO only */ u8 ip_hdr_offset; /* For LSO only */ - /* Bit pattern: 0-6 flags, 7-12 opcode, 13-15 unused */ - __le16 flags_opcode; - /* Bit pattern: 0-7 total number of segments, - 8-31 Total size of the packet */ - __le32 num_of_buffers_total_length; - union { - struct { - __le32 addr_low_part2; - __le32 addr_high_part2; - }; - __le64 addr_buffer2; - }; + __le16 flags_opcode; /* 15:13 unused, 12:7 opcode, 6:0 flags */ + __le32 nfrags__length; /* 31:8 total len, 7:0 frag count */ - __le16 reference_handle; /* changed to u16 to add mss */ - __le16 mss; /* passed by NDIS_PACKET for LSO */ - /* Bit pattern 0-3 port, 0-3 ctx id */ - u8 port_ctxid; + __le64 addr_buffer2; + + __le16 reference_handle; + __le16 mss; + u8 port_ctxid; /* 7:4 ctxid 3:0 port */ u8 total_hdr_length; /* LSO only : MAC+IP+TCP Hdr size */ __le16 conn_id; /* IPSec offoad only */ - union { - struct { - __le32 addr_low_part3; - __le32 addr_high_part3; - }; - __le64 addr_buffer3; - }; - union { - struct { - __le32 addr_low_part1; - __le32 addr_high_part1; - }; - __le64 addr_buffer1; - }; + __le64 addr_buffer3; + __le64 addr_buffer1; __le16 buffer_length[4]; - union { - struct { - __le32 addr_low_part4; - __le32 addr_high_part4; - }; - __le64 addr_buffer4; - }; + __le64 addr_buffer4; - __le64 unused; + __le32 reserved2; + __le16 reserved; + __le16 vlan_TCI; } __attribute__ ((aligned(64))); @@ -380,9 +359,11 @@ struct rcv_desc { }; /* opcode field in status_desc */ +#define NETXEN_NIC_SYN_OFFLOAD 0x03 #define NETXEN_NIC_RXPKT_DESC 0x04 #define NETXEN_OLD_RXPKT_DESC 0x3f #define NETXEN_NIC_RESPONSE_DESC 0x05 +#define NETXEN_NIC_LRO_DESC 0x12 /* for status field in status_desc */ #define STATUS_NEED_CKSUM (1) @@ -416,6 +397,24 @@ struct rcv_desc { #define netxen_get_sts_opcode(sts_data) \ (((sts_data) >> 58) & 0x03F) +#define netxen_get_lro_sts_refhandle(sts_data) \ + ((sts_data) & 0x0FFFF) +#define netxen_get_lro_sts_length(sts_data) \ + (((sts_data) >> 16) & 0x0FFFF) +#define netxen_get_lro_sts_l2_hdr_offset(sts_data) \ + (((sts_data) >> 32) & 0x0FF) +#define netxen_get_lro_sts_l4_hdr_offset(sts_data) \ + (((sts_data) >> 40) & 0x0FF) +#define netxen_get_lro_sts_timestamp(sts_data) \ + (((sts_data) >> 48) & 0x1) +#define netxen_get_lro_sts_type(sts_data) \ + (((sts_data) >> 49) & 0x7) +#define netxen_get_lro_sts_push_flag(sts_data) \ + (((sts_data) >> 52) & 0x1) +#define netxen_get_lro_sts_seq_number(sts_data) \ + ((sts_data) & 0x0FFFFFFFF) + + struct status_desc { __le64 status_desc_data[2]; } __attribute__ ((aligned(16))); @@ -459,154 +458,6 @@ struct status_desc { #define NETXEN_BRDTYPE_P3_10G_XFP 0x0032 #define NETXEN_BRDTYPE_P3_10G_TP 0x0080 -struct netxen_board_info { - u32 header_version; - - u32 board_mfg; - u32 board_type; - u32 board_num; - u32 chip_id; - u32 chip_minor; - u32 chip_major; - u32 chip_pkg; - u32 chip_lot; - - u32 port_mask; /* available niu ports */ - u32 peg_mask; /* available pegs */ - u32 icache_ok; /* can we run with icache? */ - u32 dcache_ok; /* can we run with dcache? */ - u32 casper_ok; - - u32 mac_addr_lo_0; - u32 mac_addr_lo_1; - u32 mac_addr_lo_2; - u32 mac_addr_lo_3; - - /* MN-related config */ - u32 mn_sync_mode; /* enable/ sync shift cclk/ sync shift mclk */ - u32 mn_sync_shift_cclk; - u32 mn_sync_shift_mclk; - u32 mn_wb_en; - u32 mn_crystal_freq; /* in MHz */ - u32 mn_speed; /* in MHz */ - u32 mn_org; - u32 mn_depth; - u32 mn_ranks_0; /* ranks per slot */ - u32 mn_ranks_1; /* ranks per slot */ - u32 mn_rd_latency_0; - u32 mn_rd_latency_1; - u32 mn_rd_latency_2; - u32 mn_rd_latency_3; - u32 mn_rd_latency_4; - u32 mn_rd_latency_5; - u32 mn_rd_latency_6; - u32 mn_rd_latency_7; - u32 mn_rd_latency_8; - u32 mn_dll_val[18]; - u32 mn_mode_reg; /* MIU DDR Mode Register */ - u32 mn_ext_mode_reg; /* MIU DDR Extended Mode Register */ - u32 mn_timing_0; /* MIU Memory Control Timing Rgister */ - u32 mn_timing_1; /* MIU Extended Memory Ctrl Timing Register */ - u32 mn_timing_2; /* MIU Extended Memory Ctrl Timing2 Register */ - - /* SN-related config */ - u32 sn_sync_mode; /* enable/ sync shift cclk / sync shift mclk */ - u32 sn_pt_mode; /* pass through mode */ - u32 sn_ecc_en; - u32 sn_wb_en; - u32 sn_crystal_freq; - u32 sn_speed; - u32 sn_org; - u32 sn_depth; - u32 sn_dll_tap; - u32 sn_rd_latency; - - u32 mac_addr_hi_0; - u32 mac_addr_hi_1; - u32 mac_addr_hi_2; - u32 mac_addr_hi_3; - - u32 magic; /* indicates flash has been initialized */ - - u32 mn_rdimm; - u32 mn_dll_override; - -}; - -#define FLASH_NUM_PORTS (4) - -struct netxen_flash_mac_addr { - u32 flash_addr[32]; -}; - -struct netxen_user_old_info { - u8 flash_md5[16]; - u8 crbinit_md5[16]; - u8 brdcfg_md5[16]; - /* bootloader */ - u32 bootld_version; - u32 bootld_size; - u8 bootld_md5[16]; - /* image */ - u32 image_version; - u32 image_size; - u8 image_md5[16]; - /* primary image status */ - u32 primary_status; - u32 secondary_present; - - /* MAC address , 4 ports */ - struct netxen_flash_mac_addr mac_addr[FLASH_NUM_PORTS]; -}; -#define FLASH_NUM_MAC_PER_PORT 32 -struct netxen_user_info { - u8 flash_md5[16 * 64]; - /* bootloader */ - u32 bootld_version; - u32 bootld_size; - /* image */ - u32 image_version; - u32 image_size; - /* primary image status */ - u32 primary_status; - u32 secondary_present; - - /* MAC address , 4 ports, 32 address per port */ - u64 mac_addr[FLASH_NUM_PORTS * FLASH_NUM_MAC_PER_PORT]; - u32 sub_sys_id; - u8 serial_num[32]; - - /* Any user defined data */ -}; - -/* - * Flash Layout - new format. - */ -struct netxen_new_user_info { - u8 flash_md5[16 * 64]; - /* bootloader */ - u32 bootld_version; - u32 bootld_size; - /* image */ - u32 image_version; - u32 image_size; - /* primary image status */ - u32 primary_status; - u32 secondary_present; - - /* MAC address , 4 ports, 32 address per port */ - u64 mac_addr[FLASH_NUM_PORTS * FLASH_NUM_MAC_PER_PORT]; - u32 sub_sys_id; - u8 serial_num[32]; - - /* Any user defined data */ -}; - -#define SECONDARY_IMAGE_PRESENT 0xb3b4b5b6 -#define SECONDARY_IMAGE_ABSENT 0xffffffff -#define PRIMARY_IMAGE_GOOD 0x5a5a5a5a -#define PRIMARY_IMAGE_BAD 0xffffffff - /* Flash memory map */ #define NETXEN_CRBINIT_START 0 /* crbinit section */ #define NETXEN_BRDCFG_START 0x4000 /* board config */ @@ -617,28 +468,25 @@ struct netxen_new_user_info { #define NETXEN_PXE_START 0x3E0000 /* PXE boot rom */ #define NETXEN_USER_START 0x3E8000 /* Firmare info */ #define NETXEN_FIXED_START 0x3F0000 /* backup of crbinit */ +#define NETXEN_USER_START_OLD NETXEN_PXE_START /* very old flash */ +#define NX_OLD_MAC_ADDR_OFFSET (NETXEN_USER_START) #define NX_FW_VERSION_OFFSET (NETXEN_USER_START+0x408) #define NX_FW_SIZE_OFFSET (NETXEN_USER_START+0x40c) +#define NX_FW_MAC_ADDR_OFFSET (NETXEN_USER_START+0x418) +#define NX_FW_SERIAL_NUM_OFFSET (NETXEN_USER_START+0x81c) #define NX_BIOS_VERSION_OFFSET (NETXEN_USER_START+0x83c) + +#define NX_HDR_VERSION_OFFSET (NETXEN_BRDCFG_START) +#define NX_BRDTYPE_OFFSET (NETXEN_BRDCFG_START+0x8) #define NX_FW_MAGIC_OFFSET (NETXEN_BRDCFG_START+0x128) + #define NX_FW_MIN_SIZE (0x3fffff) #define NX_P2_MN_ROMIMAGE 0 #define NX_P3_CT_ROMIMAGE 1 #define NX_P3_MN_ROMIMAGE 2 #define NX_FLASH_ROMIMAGE 3 -#define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */ - -#define NETXEN_FLASH_START (NETXEN_CRBINIT_START) -#define NETXEN_INIT_SECTOR (0) -#define NETXEN_PRIMARY_START (NETXEN_BOOTLD_START) -#define NETXEN_FLASH_CRBINIT_SIZE (0x4000) -#define NETXEN_FLASH_BRDCFG_SIZE (sizeof(struct netxen_board_info)) -#define NETXEN_FLASH_USER_SIZE (sizeof(struct netxen_user_info)/sizeof(u32)) -#define NETXEN_FLASH_SECONDARY_SIZE (NETXEN_USER_START-NETXEN_SECONDARY_START) -#define NETXEN_NUM_PRIMARY_SECTORS (0x20) -#define NETXEN_NUM_CONFIG_SECTORS (1) extern char netxen_nic_driver_name[]; /* Number of status descriptors to handle per interrupt */ @@ -653,17 +501,11 @@ struct netxen_skb_frag { u64 length; }; -#define _netxen_set_bits(config_word, start, bits, val) {\ - unsigned long long __tmask = (((1ULL << (bits)) - 1) << (start));\ - unsigned long long __tvalue = (val); \ - (config_word) &= ~__tmask; \ - (config_word) |= (((__tvalue) << (start)) & __tmask); \ -} - -#define _netxen_clear_bits(config_word, start, bits) {\ - unsigned long long __tmask = (((1ULL << (bits)) - 1) << (start)); \ - (config_word) &= ~__tmask; \ -} +struct netxen_recv_crb { + u32 crb_rcv_producer[NUM_RCV_DESC_RINGS]; + u32 crb_sts_consumer[NUM_STS_DESC_RINGS]; + u32 sw_int_mask[NUM_STS_DESC_RINGS]; +}; /* Following defines are for the state of the buffers */ #define NETXEN_BUFFER_FREE 0 @@ -706,8 +548,8 @@ struct netxen_hardware_context { int qdr_sn_window; int ddr_mn_window; - unsigned long mn_win_crb; - unsigned long ms_win_crb; + u32 mn_win_crb; + u32 ms_win_crb; u8 cut_through; u8 revision_id; @@ -726,7 +568,8 @@ struct netxen_adapter_stats { u64 rxdropped; u64 txdropped; u64 csummed; - u64 no_rcv; + u64 rx_pkts; + u64 lro_pkts; u64 rxbytes; u64 txbytes; }; @@ -737,11 +580,11 @@ struct netxen_adapter_stats { */ struct nx_host_rds_ring { u32 producer; - u32 crb_rcv_producer; u32 num_desc; u32 dma_size; u32 skb_size; u32 flags; + void __iomem *crb_rcv_producer; struct rcv_desc *desc_head; struct netxen_rx_buffer *rx_buf_arr; struct list_head free_list; @@ -751,9 +594,9 @@ struct nx_host_rds_ring { struct nx_host_sds_ring { u32 consumer; - u32 crb_sts_consumer; - u32 crb_intr_mask; u32 num_desc; + void __iomem *crb_sts_consumer; + void __iomem *crb_intr_mask; struct status_desc *desc_head; struct netxen_adapter *adapter; @@ -770,8 +613,8 @@ struct nx_host_tx_ring { u32 producer; __le32 *hw_consumer; u32 sw_consumer; - u32 crb_cmd_producer; - u32 crb_cmd_consumer; + void __iomem *crb_cmd_producer; + void __iomem *crb_cmd_consumer; u32 num_desc; struct netdev_queue *txq; @@ -840,7 +683,19 @@ struct netxen_recv_context { #define NX_CDRP_CMD_GET_STATISTICS 0x0000000f #define NX_CDRP_CMD_DELETE_STATISTICS 0x00000010 #define NX_CDRP_CMD_SET_MTU 0x00000012 -#define NX_CDRP_CMD_MAX 0x00000013 +#define NX_CDRP_CMD_READ_PHY 0x00000013 +#define NX_CDRP_CMD_WRITE_PHY 0x00000014 +#define NX_CDRP_CMD_READ_HW_REG 0x00000015 +#define NX_CDRP_CMD_GET_FLOW_CTL 0x00000016 +#define NX_CDRP_CMD_SET_FLOW_CTL 0x00000017 +#define NX_CDRP_CMD_READ_MAX_MTU 0x00000018 +#define NX_CDRP_CMD_READ_MAX_LRO 0x00000019 +#define NX_CDRP_CMD_CONFIGURE_TOE 0x0000001a +#define NX_CDRP_CMD_FUNC_ATTRIB 0x0000001b +#define NX_CDRP_CMD_READ_PEXQ_PARAMETERS 0x0000001c +#define NX_CDRP_CMD_GET_LIC_CAPABILITIES 0x0000001d +#define NX_CDRP_CMD_READ_MAX_LRO_PER_BOARD 0x0000001e +#define NX_CDRP_CMD_MAX 0x0000001f #define NX_RCODE_SUCCESS 0 #define NX_RCODE_NO_HOST_MEM 1 @@ -881,6 +736,7 @@ struct netxen_recv_context { #define NX_CAP0_LSO NX_CAP_BIT(0, 6) #define NX_CAP0_JUMBO_CONTIGUOUS NX_CAP_BIT(0, 7) #define NX_CAP0_LRO_CONTIGUOUS NX_CAP_BIT(0, 8) +#define NX_CAP0_HW_LRO NX_CAP_BIT(0, 10) /* * Context state @@ -1078,6 +934,9 @@ typedef struct { #define NX_MAC_EVENT 0x1 +#define NX_IP_UP 2 +#define NX_IP_DOWN 3 + /* * Driver --> Firmware */ @@ -1104,7 +963,9 @@ typedef struct { #define NX_NIC_H2C_OPCODE_PROXY_STOP_DONE 20 #define NX_NIC_H2C_OPCODE_GET_LINKEVENT 21 #define NX_NIC_C2C_OPCODE 22 -#define NX_NIC_H2C_OPCODE_LAST 23 +#define NX_NIC_H2C_OPCODE_CONFIG_BRIDGING 23 +#define NX_NIC_H2C_OPCODE_CONFIG_HW_LRO 24 +#define NX_NIC_H2C_OPCODE_LAST 25 /* * Firmware --> Driver @@ -1130,8 +991,25 @@ typedef struct { #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ #define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */ +#define NX_NIC_LRO_REQUEST_FIRST 0 +#define NX_NIC_LRO_REQUEST_ADD_FLOW 1 +#define NX_NIC_LRO_REQUEST_DELETE_FLOW 2 +#define NX_NIC_LRO_REQUEST_TIMER 3 +#define NX_NIC_LRO_REQUEST_CLEANUP 4 +#define NX_NIC_LRO_REQUEST_ADD_FLOW_SCHEDULED 5 +#define NX_TOE_LRO_REQUEST_ADD_FLOW 6 +#define NX_TOE_LRO_REQUEST_ADD_FLOW_RESPONSE 7 +#define NX_TOE_LRO_REQUEST_DELETE_FLOW 8 +#define NX_TOE_LRO_REQUEST_DELETE_FLOW_RESPONSE 9 +#define NX_TOE_LRO_REQUEST_TIMER 10 +#define NX_NIC_LRO_REQUEST_LAST 11 + #define NX_FW_CAPABILITY_LINK_NOTIFICATION (1 << 5) #define NX_FW_CAPABILITY_SWITCHING (1 << 6) +#define NX_FW_CAPABILITY_PEXQ (1 << 7) +#define NX_FW_CAPABILITY_BDG (1 << 8) +#define NX_FW_CAPABILITY_FVLANTX (1 << 9) +#define NX_FW_CAPABILITY_HW_LRO (1 << 10) /* module types */ #define LINKEVENT_MODULE_NOT_PRESENT 1 @@ -1206,6 +1084,8 @@ typedef struct { #define NETXEN_NIC_MSI_ENABLED 0x02 #define NETXEN_NIC_MSIX_ENABLED 0x04 +#define NETXEN_NIC_LRO_ENABLED 0x08 +#define NETXEN_NIC_BRIDGE_ENABLED 0X10 #define NETXEN_IS_MSI_FAMILY(adapter) \ ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED)) @@ -1219,6 +1099,10 @@ typedef struct { #define NETXEN_ADAPTER_UP_MAGIC 777 #define NETXEN_NIC_PEG_TUNE 0 +#define __NX_FW_ATTACHED 0 +#define __NX_DEV_UP 1 +#define __NX_RESETTING 2 + struct netxen_dummy_dma { void *addr; dma_addr_t phys_addr; @@ -1255,7 +1139,10 @@ struct netxen_adapter { u8 max_mc_count; u8 rss_supported; u8 link_changed; - u32 resv3; + u8 fw_wait_cnt; + u8 fw_fail_cnt; + u8 tx_timeo_cnt; + u8 need_fw_reset; u8 has_link_events; u8 fw_type; @@ -1273,79 +1160,64 @@ struct netxen_adapter { u32 irq; u32 temp; - u32 msi_tgt_status; - u32 resv4; + u32 int_vec_bit; + u32 heartbit; struct netxen_adapter_stats stats; struct netxen_recv_context recv_ctx; struct nx_host_tx_ring *tx_ring; - int (*enable_phy_interrupts) (struct netxen_adapter *); - int (*disable_phy_interrupts) (struct netxen_adapter *); int (*macaddr_set) (struct netxen_adapter *, u8 *); int (*set_mtu) (struct netxen_adapter *, int); int (*set_promisc) (struct netxen_adapter *, u32); void (*set_multi) (struct net_device *); - int (*phy_read) (struct netxen_adapter *, long reg, u32 *); - int (*phy_write) (struct netxen_adapter *, long reg, u32 val); + int (*phy_read) (struct netxen_adapter *, u32 reg, u32 *); + int (*phy_write) (struct netxen_adapter *, u32 reg, u32 val); int (*init_port) (struct netxen_adapter *, int); int (*stop_port) (struct netxen_adapter *); - u32 (*hw_read_wx)(struct netxen_adapter *, ulong); - int (*hw_write_wx)(struct netxen_adapter *, ulong, u32); + u32 (*crb_read)(struct netxen_adapter *, ulong); + int (*crb_write)(struct netxen_adapter *, ulong, u32); + int (*pci_mem_read)(struct netxen_adapter *, u64, void *, int); int (*pci_mem_write)(struct netxen_adapter *, u64, void *, int); - int (*pci_write_immediate)(struct netxen_adapter *, u64, u32); - u32 (*pci_read_immediate)(struct netxen_adapter *, u64); + unsigned long (*pci_set_window)(struct netxen_adapter *, unsigned long long); - struct netxen_legacy_intr_set legacy_intr; + u32 (*io_read)(struct netxen_adapter *, void __iomem *); + void (*io_write)(struct netxen_adapter *, void __iomem *, u32); + + void __iomem *tgt_mask_reg; + void __iomem *pci_int_reg; + void __iomem *tgt_status_reg; + void __iomem *crb_int_state_reg; + void __iomem *isr_int_vec; struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER]; struct netxen_dummy_dma dummy_dma; - struct work_struct watchdog_task; - struct timer_list watchdog_timer; + struct delayed_work fw_work; + struct work_struct tx_timeout_task; struct net_device_stats net_stats; nx_nic_intr_coalesce_t coal; - u32 fw_major; + unsigned long state; + u32 resv5; u32 fw_version; const struct firmware *fw; }; -/* - * NetXen dma watchdog control structure - * - * Bit 0 : enabled => R/O: 1 watchdog active, 0 inactive - * Bit 1 : disable_request => 1 req disable dma watchdog - * Bit 2 : enable_request => 1 req enable dma watchdog - * Bit 3-31 : unused - */ +int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port); +int netxen_niu_disable_xg_port(struct netxen_adapter *adapter); -#define netxen_set_dma_watchdog_disable_req(config_word) \ - _netxen_set_bits(config_word, 1, 1, 1) -#define netxen_set_dma_watchdog_enable_req(config_word) \ - _netxen_set_bits(config_word, 2, 1, 1) -#define netxen_get_dma_watchdog_enabled(config_word) \ - ((config_word) & 0x1) -#define netxen_get_dma_watchdog_disabled(config_word) \ - (((config_word) >> 1) & 0x1) - -int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter); -int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter); -int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter); -int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter); -int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg, - __u32 * readval); -int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, - long reg, __u32 val); +int nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val); +int nx_fw_cmd_set_phy(struct netxen_adapter *adapter, u32 reg, u32 val); /* Functions available from netxen_nic_hw.c */ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu); @@ -1355,51 +1227,45 @@ int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr); int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr); #define NXRD32(adapter, off) \ - (adapter->hw_read_wx(adapter, off)) + (adapter->crb_read(adapter, off)) #define NXWR32(adapter, off, val) \ - (adapter->hw_write_wx(adapter, off, val)) + (adapter->crb_write(adapter, off, val)) +#define NXRDIO(adapter, addr) \ + (adapter->io_read(adapter, addr)) +#define NXWRIO(adapter, addr, val) \ + (adapter->io_write(adapter, addr, val)) + +int netxen_pcie_sem_lock(struct netxen_adapter *, int, u32); +void netxen_pcie_sem_unlock(struct netxen_adapter *, int); + +#define netxen_rom_lock(a) \ + netxen_pcie_sem_lock((a), 2, NETXEN_ROM_LOCK_ID) +#define netxen_rom_unlock(a) \ + netxen_pcie_sem_unlock((a), 2) +#define netxen_phy_lock(a) \ + netxen_pcie_sem_lock((a), 3, NETXEN_PHY_LOCK_ID) +#define netxen_phy_unlock(a) \ + netxen_pcie_sem_unlock((a), 3) +#define netxen_api_lock(a) \ + netxen_pcie_sem_lock((a), 5, 0) +#define netxen_api_unlock(a) \ + netxen_pcie_sem_unlock((a), 5) +#define netxen_sw_lock(a) \ + netxen_pcie_sem_lock((a), 6, 0) +#define netxen_sw_unlock(a) \ + netxen_pcie_sem_unlock((a), 6) +#define crb_win_lock(a) \ + netxen_pcie_sem_lock((a), 7, NETXEN_CRB_WIN_LOCK_ID) +#define crb_win_unlock(a) \ + netxen_pcie_sem_unlock((a), 7) int netxen_nic_get_board_info(struct netxen_adapter *adapter); -void netxen_nic_get_firmware_info(struct netxen_adapter *adapter); int netxen_nic_wol_supported(struct netxen_adapter *adapter); -u32 netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off); -int netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, - ulong off, u32 data); -int netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, - u64 off, void *data, int size); -int netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, - u64 off, void *data, int size); -int netxen_nic_pci_write_immediate_128M(struct netxen_adapter *adapter, - u64 off, u32 data); -u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off); -void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter, - u64 off, u32 data); -u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off); -unsigned long netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter, - unsigned long long addr); -void netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, - u32 wndw); - -u32 netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off); -int netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, - ulong off, u32 data); -int netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, - u64 off, void *data, int size); -int netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, - u64 off, void *data, int size); -int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter, - u64 off, u32 data); -u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off); -void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter, - u64 off, u32 data); -u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off); -unsigned long netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, - unsigned long long addr); - /* Functions from netxen_nic_init.c */ -void netxen_free_adapter_offload(struct netxen_adapter *adapter); -int netxen_initialize_adapter_offload(struct netxen_adapter *adapter); +int netxen_init_dummy_dma(struct netxen_adapter *adapter); +void netxen_free_dummy_dma(struct netxen_adapter *adapter); + int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); int netxen_load_firmware(struct netxen_adapter *adapter); int netxen_need_fw_reset(struct netxen_adapter *adapter); @@ -1423,13 +1289,15 @@ int netxen_rom_se(struct netxen_adapter *adapter, int addr); int netxen_alloc_sw_resources(struct netxen_adapter *adapter); void netxen_free_sw_resources(struct netxen_adapter *adapter); +void netxen_setup_hwops(struct netxen_adapter *adapter); +void __iomem *netxen_get_ioaddr(struct netxen_adapter *, u32); + int netxen_alloc_hw_resources(struct netxen_adapter *adapter); void netxen_free_hw_resources(struct netxen_adapter *adapter); void netxen_release_rx_buffers(struct netxen_adapter *adapter); void netxen_release_tx_buffers(struct netxen_adapter *adapter); -void netxen_initialize_adapter_ops(struct netxen_adapter *adapter); int netxen_init_firmware(struct netxen_adapter *adapter); void netxen_nic_clear_stats(struct netxen_adapter *adapter); void netxen_watchdog_task(struct work_struct *work); @@ -1440,14 +1308,19 @@ int netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max); void netxen_p2_nic_set_multi(struct net_device *netdev); void netxen_p3_nic_set_multi(struct net_device *netdev); void netxen_p3_free_mac_list(struct netxen_adapter *adapter); +int netxen_p2_nic_set_promisc(struct netxen_adapter *adapter, u32 mode); int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32); int netxen_config_intr_coalesce(struct netxen_adapter *adapter); int netxen_config_rss(struct netxen_adapter *adapter, int enable); +int netxen_config_ipaddr(struct netxen_adapter *adapter, u32 ip, int cmd); int netxen_linkevent_request(struct netxen_adapter *adapter, int enable); void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup); int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu); int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); +int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable); +int netxen_config_bridged_mode(struct netxen_adapter *adapter, int enable); +int netxen_send_lro_cleanup(struct netxen_adapter *adapter); int netxen_nic_set_mac(struct net_device *netdev, void *p); struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev); @@ -1455,6 +1328,9 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev); void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, struct nx_host_tx_ring *tx_ring); +/* Functions from netxen_nic_main.c */ +int netxen_nic_reset_context(struct netxen_adapter *); + /* * NetXen Board information */ @@ -1505,56 +1381,6 @@ static inline void get_brd_name_by_type(u32 type, char *name) name = "Unknown"; } -static inline int -dma_watchdog_shutdown_request(struct netxen_adapter *adapter) -{ - u32 ctrl; - - /* check if already inactive */ - ctrl = adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL)); - - if (netxen_get_dma_watchdog_enabled(ctrl) == 0) - return 1; - - /* Send the disable request */ - netxen_set_dma_watchdog_disable_req(ctrl); - NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); - - return 0; -} - -static inline int -dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter) -{ - u32 ctrl; - - ctrl = adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL)); - - return (netxen_get_dma_watchdog_enabled(ctrl) == 0); -} - -static inline int -dma_watchdog_wakeup(struct netxen_adapter *adapter) -{ - u32 ctrl; - - ctrl = adapter->hw_read_wx(adapter, - NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL)); - - if (netxen_get_dma_watchdog_enabled(ctrl)) - return 1; - - /* send the wakeup request */ - netxen_set_dma_watchdog_enable_req(ctrl); - - NXWR32(adapter, NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), ctrl); - - return 0; -} - - static inline u32 netxen_tx_avail(struct nx_host_tx_ring *tx_ring) { smp_mb(); @@ -1569,6 +1395,6 @@ extern void netxen_change_ringparam(struct netxen_adapter *adapter); extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); -extern struct ethtool_ops netxen_nic_ethtool_ops; +extern const struct ethtool_ops netxen_nic_ethtool_ops; #endif /* __NETXEN_NIC_H_ */ diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 9f8ae4719e2..9cb8f687804 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2003 - 2009 NetXen, Inc. + * Copyright (C) 2009 - QLogic Corporation. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -20,55 +21,13 @@ * The full GNU General Public License is included in this distribution * in the file called LICENSE. * - * Contact Information: - * info@netxen.com - * NetXen Inc, - * 18922 Forge Drive - * Cupertino, CA 95014-0701 - * */ #include "netxen_nic_hw.h" #include "netxen_nic.h" -#include "netxen_nic_phan_reg.h" #define NXHAL_VERSION 1 -static int -netxen_api_lock(struct netxen_adapter *adapter) -{ - u32 done = 0, timeout = 0; - - for (;;) { - /* Acquire PCIE HW semaphore5 */ - done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM5_LOCK)); - - if (done == 1) - break; - - if (++timeout >= NX_OS_CRB_RETRY_COUNT) { - printk(KERN_ERR "%s: lock timeout.\n", __func__); - return -1; - } - - msleep(1); - } - -#if 0 - NXWR32(adapter, - NETXEN_API_LOCK_ID, NX_OS_API_LOCK_DRIVER); -#endif - return 0; -} - -static int -netxen_api_unlock(struct netxen_adapter *adapter) -{ - /* Release PCIE HW semaphore5 */ - NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK)); - return 0; -} - static u32 netxen_poll_rsp(struct netxen_adapter *adapter) { @@ -265,7 +224,8 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) rds_ring = &recv_ctx->rds_rings[i]; reg = le32_to_cpu(prsp_rds[i].host_producer_crb); - rds_ring->crb_rcv_producer = NETXEN_NIC_REG(reg - 0x200); + rds_ring->crb_rcv_producer = netxen_get_ioaddr(adapter, + NETXEN_NIC_REG(reg - 0x200)); } prsp_sds = ((nx_cardrsp_sds_ring_t *) @@ -275,10 +235,12 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) sds_ring = &recv_ctx->sds_rings[i]; reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); - sds_ring->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200); + sds_ring->crb_sts_consumer = netxen_get_ioaddr(adapter, + NETXEN_NIC_REG(reg - 0x200)); reg = le32_to_cpu(prsp_sds[i].interrupt_crb); - sds_ring->crb_intr_mask = NETXEN_NIC_REG(reg - 0x200); + sds_ring->crb_intr_mask = netxen_get_ioaddr(adapter, + NETXEN_NIC_REG(reg - 0x200)); } recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); @@ -378,7 +340,8 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) if (err == NX_RCODE_SUCCESS) { temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); - tx_ring->crb_cmd_producer = NETXEN_NIC_REG(temp - 0x200); + tx_ring->crb_cmd_producer = netxen_get_ioaddr(adapter, + NETXEN_NIC_REG(temp - 0x200)); #if 0 adapter->tx_state = le32_to_cpu(prsp->host_ctx_state); @@ -416,6 +379,44 @@ nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter) } } +int +nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val) +{ + u32 rcode; + + rcode = netxen_issue_cmd(adapter, + adapter->ahw.pci_func, + NXHAL_VERSION, + reg, + 0, + 0, + NX_CDRP_CMD_READ_PHY); + + if (rcode != NX_RCODE_SUCCESS) + return -EIO; + + return NXRD32(adapter, NX_ARG1_CRB_OFFSET); +} + +int +nx_fw_cmd_set_phy(struct netxen_adapter *adapter, u32 reg, u32 val) +{ + u32 rcode; + + rcode = netxen_issue_cmd(adapter, + adapter->ahw.pci_func, + NXHAL_VERSION, + reg, + val, + 0, + NX_CDRP_CMD_WRITE_PHY); + + if (rcode != NX_RCODE_SUCCESS) + return -EIO; + + return 0; +} + static u64 ctx_addr_sig_regs[][3] = { {NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)}, {NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)}, @@ -647,9 +648,10 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) } rds_ring->desc_head = (struct rcv_desc *)addr; - if (adapter->fw_major < 4) + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) rds_ring->crb_rcv_producer = - recv_crb_registers[port].crb_rcv_producer[ring]; + netxen_get_ioaddr(adapter, + recv_crb_registers[port].crb_rcv_producer[ring]); } for (ring = 0; ring < adapter->max_sds_rings; ring++) { @@ -668,14 +670,19 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) sds_ring->desc_head = (struct status_desc *)addr; sds_ring->crb_sts_consumer = - recv_crb_registers[port].crb_sts_consumer[ring]; + netxen_get_ioaddr(adapter, + recv_crb_registers[port].crb_sts_consumer[ring]); sds_ring->crb_intr_mask = - recv_crb_registers[port].sw_int_mask[ring]; + netxen_get_ioaddr(adapter, + recv_crb_registers[port].sw_int_mask[ring]); } - if (adapter->fw_major >= 4) { + if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + if (test_and_set_bit(__NX_FW_ATTACHED, &adapter->state)) + goto done; + err = nx_fw_cmd_create_rx_ctx(adapter); if (err) goto err_out_free; @@ -688,6 +695,7 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) goto err_out_free; } +done: return 0; err_out_free: @@ -705,7 +713,10 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) int port = adapter->portnum; - if (adapter->fw_major >= 4) { + if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + if (!test_and_clear_bit(__NX_FW_ATTACHED, &adapter->state)) + goto done; + nx_fw_cmd_destroy_rx_ctx(adapter); nx_fw_cmd_destroy_tx_ctx(adapter); } else { @@ -718,6 +729,7 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) /* Allow dma queues to drain after context reset */ msleep(20); +done: recv_ctx = &adapter->recv_ctx; if (recv_ctx->hwctx != NULL) { diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index e16ea46c24b..714f38791a9 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2003 - 2009 NetXen, Inc. + * Copyright (C) 2009 - QLogic Corporation. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -20,12 +21,6 @@ * The full GNU General Public License is included in this distribution * in the file called LICENSE. * - * Contact Information: - * info@netxen.com - * NetXen Inc, - * 18922 Forge Drive - * Cupertino, CA 95014-0701 - * */ #include <linux/types.h> @@ -37,7 +32,6 @@ #include "netxen_nic.h" #include "netxen_nic_hw.h" -#include "netxen_nic_phan_reg.h" struct netxen_nic_stats { char stat_string[ETH_GSTRING_LEN]; @@ -57,7 +51,8 @@ static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = { {"rx_dropped", NETXEN_NIC_STAT(stats.rxdropped)}, {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)}, {"csummed", NETXEN_NIC_STAT(stats.csummed)}, - {"no_rcv", NETXEN_NIC_STAT(stats.no_rcv)}, + {"rx_pkts", NETXEN_NIC_STAT(stats.rx_pkts)}, + {"lro_pkts", NETXEN_NIC_STAT(stats.lro_pkts)}, {"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)}, {"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)}, }; @@ -84,18 +79,17 @@ static void netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) { struct netxen_adapter *adapter = netdev_priv(dev); - unsigned long flags; u32 fw_major = 0; u32 fw_minor = 0; u32 fw_build = 0; strncpy(drvinfo->driver, netxen_nic_driver_name, 32); strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32); - write_lock_irqsave(&adapter->adapter_lock, flags); + read_lock(&adapter->adapter_lock); fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); - write_unlock_irqrestore(&adapter->adapter_lock, flags); + read_unlock(&adapter->adapter_lock); sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build); strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); @@ -490,28 +484,86 @@ netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, } static void -netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) +netxen_nic_get_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) { struct netxen_adapter *adapter = netdev_priv(dev); - ring->rx_pending = 0; - ring->rx_jumbo_pending = 0; - ring->rx_pending += adapter->recv_ctx. - rds_rings[RCV_RING_NORMAL].num_desc; - ring->rx_jumbo_pending += adapter->recv_ctx. - rds_rings[RCV_RING_JUMBO].num_desc; + ring->rx_pending = adapter->num_rxd; + ring->rx_jumbo_pending = adapter->num_jumbo_rxd; + ring->rx_jumbo_pending += adapter->num_lro_rxd; ring->tx_pending = adapter->num_txd; - if (adapter->ahw.port_type == NETXEN_NIC_GBE) + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G; - else + ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_1G; + } else { ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G; - ring->tx_max_pending = MAX_CMD_DESCRIPTORS_HOST; - ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS; + ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_10G; + } + + ring->tx_max_pending = MAX_CMD_DESCRIPTORS; + ring->rx_mini_max_pending = 0; ring->rx_mini_pending = 0; } +static u32 +netxen_validate_ringparam(u32 val, u32 min, u32 max, char *r_name) +{ + u32 num_desc; + num_desc = max(val, min); + num_desc = min(num_desc, max); + num_desc = roundup_pow_of_two(num_desc); + + if (val != num_desc) { + printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n", + netxen_nic_driver_name, r_name, num_desc, val); + } + + return num_desc; +} + +static int +netxen_nic_set_ringparam(struct net_device *dev, + struct ethtool_ringparam *ring) +{ + struct netxen_adapter *adapter = netdev_priv(dev); + u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G; + u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G; + u16 num_rxd, num_jumbo_rxd, num_txd; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return -EOPNOTSUPP; + + if (ring->rx_mini_pending) + return -EOPNOTSUPP; + + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { + max_rcv_desc = MAX_RCV_DESCRIPTORS_1G; + max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G; + } + + num_rxd = netxen_validate_ringparam(ring->rx_pending, + MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx"); + + num_jumbo_rxd = netxen_validate_ringparam(ring->rx_jumbo_pending, + MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo"); + + num_txd = netxen_validate_ringparam(ring->tx_pending, + MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx"); + + if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd && + num_jumbo_rxd == adapter->num_jumbo_rxd) + return 0; + + adapter->num_rxd = num_rxd; + adapter->num_jumbo_rxd = num_jumbo_rxd; + adapter->num_txd = num_txd; + + return netxen_nic_reset_context(adapter); +} + static void netxen_nic_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *pause) @@ -883,7 +935,29 @@ static int netxen_get_intr_coalesce(struct net_device *netdev, return 0; } -struct ethtool_ops netxen_nic_ethtool_ops = { +static int netxen_nic_set_flags(struct net_device *netdev, u32 data) +{ + struct netxen_adapter *adapter = netdev_priv(netdev); + int hw_lro; + + if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO)) + return -EINVAL; + + ethtool_op_set_flags(netdev, data); + + hw_lro = (data & ETH_FLAG_LRO) ? NETXEN_NIC_LRO_ENABLED : 0; + + if (netxen_config_hw_lro(adapter, hw_lro)) + return -EIO; + + if ((hw_lro == 0) && netxen_send_lro_cleanup(adapter)) + return -EIO; + + + return 0; +} + +const struct ethtool_ops netxen_nic_ethtool_ops = { .get_settings = netxen_nic_get_settings, .set_settings = netxen_nic_set_settings, .get_drvinfo = netxen_nic_get_drvinfo, @@ -893,6 +967,7 @@ struct ethtool_ops netxen_nic_ethtool_ops = { .get_eeprom_len = netxen_nic_get_eeprom_len, .get_eeprom = netxen_nic_get_eeprom, .get_ringparam = netxen_nic_get_ringparam, + .set_ringparam = netxen_nic_set_ringparam, .get_pauseparam = netxen_nic_get_pauseparam, .set_pauseparam = netxen_nic_set_pauseparam, .set_tx_csum = ethtool_op_set_tx_csum, @@ -909,4 +984,6 @@ struct ethtool_ops netxen_nic_ethtool_ops = { .set_rx_csum = netxen_nic_set_rx_csum, .get_coalesce = netxen_get_intr_coalesce, .set_coalesce = netxen_set_intr_coalesce, + .get_flags = ethtool_op_get_flags, + .set_flags = netxen_nic_set_flags, }; diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 82410367564..7a7177421d7 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2003 - 2009 NetXen, Inc. + * Copyright (C) 2009 - QLogic Corporation. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -20,12 +21,6 @@ * The full GNU General Public License is included in this distribution * in the file called LICENSE. * - * Contact Information: - * info@netxen.com - * NetXen Inc, - * 18922 Forge Drive - * Cupertino, CA 95014-0701 - * */ #ifndef __NETXEN_NIC_HDR_H_ @@ -433,6 +428,7 @@ enum { #define NETXEN_CRB_PEG_NET_1 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN1) #define NETXEN_CRB_PEG_NET_2 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN2) #define NETXEN_CRB_PEG_NET_3 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN3) +#define NETXEN_CRB_PEG_NET_4 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SQS2) #define NETXEN_CRB_PEG_NET_D NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGND) #define NETXEN_CRB_PEG_NET_I NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGNI) #define NETXEN_CRB_DDR_NET NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_MN) @@ -723,9 +719,92 @@ enum { #define NETXEN_FW_VERSION_MINOR (NETXEN_CAM_RAM(0x154)) #define NETXEN_FW_VERSION_SUB (NETXEN_CAM_RAM(0x158)) #define NETXEN_ROM_LOCK_ID (NETXEN_CAM_RAM(0x100)) +#define NETXEN_PHY_LOCK_ID (NETXEN_CAM_RAM(0x120)) #define NETXEN_CRB_WIN_LOCK_ID (NETXEN_CAM_RAM(0x124)) -#define NETXEN_PHY_LOCK_ID (NETXEN_CAM_RAM(0x120)) +#define NIC_CRB_BASE (NETXEN_CAM_RAM(0x200)) +#define NIC_CRB_BASE_2 (NETXEN_CAM_RAM(0x700)) +#define NETXEN_NIC_REG(X) (NIC_CRB_BASE+(X)) +#define NETXEN_NIC_REG_2(X) (NIC_CRB_BASE_2+(X)) + +#define NX_CDRP_CRB_OFFSET (NETXEN_NIC_REG(0x18)) +#define NX_ARG1_CRB_OFFSET (NETXEN_NIC_REG(0x1c)) +#define NX_ARG2_CRB_OFFSET (NETXEN_NIC_REG(0x20)) +#define NX_ARG3_CRB_OFFSET (NETXEN_NIC_REG(0x24)) +#define NX_SIGN_CRB_OFFSET (NETXEN_NIC_REG(0x28)) + +#define CRB_HOST_DUMMY_BUF_ADDR_HI (NETXEN_NIC_REG(0x3c)) +#define CRB_HOST_DUMMY_BUF_ADDR_LO (NETXEN_NIC_REG(0x40)) + +#define CRB_CMDPEG_STATE (NETXEN_NIC_REG(0x50)) +#define CRB_RCVPEG_STATE (NETXEN_NIC_REG(0x13c)) + +#define CRB_XG_STATE (NETXEN_NIC_REG(0x94)) +#define CRB_XG_STATE_P3 (NETXEN_NIC_REG(0x98)) +#define CRB_PF_LINK_SPEED_1 (NETXEN_NIC_REG(0xe8)) +#define CRB_PF_LINK_SPEED_2 (NETXEN_NIC_REG(0xec)) + +#define CRB_MPORT_MODE (NETXEN_NIC_REG(0xc4)) +#define CRB_DMA_SHIFT (NETXEN_NIC_REG(0xcc)) +#define CRB_INT_VECTOR (NETXEN_NIC_REG(0xd4)) + +#define CRB_CMD_PRODUCER_OFFSET (NETXEN_NIC_REG(0x08)) +#define CRB_CMD_CONSUMER_OFFSET (NETXEN_NIC_REG(0x0c)) +#define CRB_CMD_PRODUCER_OFFSET_1 (NETXEN_NIC_REG(0x1ac)) +#define CRB_CMD_CONSUMER_OFFSET_1 (NETXEN_NIC_REG(0x1b0)) +#define CRB_CMD_PRODUCER_OFFSET_2 (NETXEN_NIC_REG(0x1b8)) +#define CRB_CMD_CONSUMER_OFFSET_2 (NETXEN_NIC_REG(0x1bc)) +#define CRB_CMD_PRODUCER_OFFSET_3 (NETXEN_NIC_REG(0x1d0)) +#define CRB_CMD_CONSUMER_OFFSET_3 (NETXEN_NIC_REG(0x1d4)) +#define CRB_TEMP_STATE (NETXEN_NIC_REG(0x1b4)) + +#define CRB_V2P_0 (NETXEN_NIC_REG(0x290)) +#define CRB_V2P(port) (CRB_V2P_0+((port)*4)) +#define CRB_DRIVER_VERSION (NETXEN_NIC_REG(0x2a0)) + +#define CRB_SW_INT_MASK_0 (NETXEN_NIC_REG(0x1d8)) +#define CRB_SW_INT_MASK_1 (NETXEN_NIC_REG(0x1e0)) +#define CRB_SW_INT_MASK_2 (NETXEN_NIC_REG(0x1e4)) +#define CRB_SW_INT_MASK_3 (NETXEN_NIC_REG(0x1e8)) + +#define CRB_FW_CAPABILITIES_1 (NETXEN_CAM_RAM(0x128)) +#define CRB_MAC_BLOCK_START (NETXEN_CAM_RAM(0x1c0)) + +/* + * capabilities register, can be used to selectively enable/disable features + * for backward compability + */ +#define CRB_NIC_CAPABILITIES_HOST NETXEN_NIC_REG(0x1a8) +#define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc) +#define CRB_NIC_MSI_MODE_HOST NETXEN_NIC_REG(0x270) +#define CRB_NIC_MSI_MODE_FW NETXEN_NIC_REG(0x274) + +#define INTR_SCHEME_PERPORT 0x1 +#define MSI_MODE_MULTIFUNC 0x1 + +/* used for ethtool tests */ +#define CRB_SCRATCHPAD_TEST NETXEN_NIC_REG(0x280) + +/* + * CrbPortPhanCntrHi/Lo is used to pass the address of HostPhantomIndex address + * which can be read by the Phantom host to get producer/consumer indexes from + * Phantom/Casper. If it is not HOST_SHARED_MEMORY, then the following + * registers will be used for the addresses of the ring's shared memory + * on the Phantom. + */ + +#define nx_get_temp_val(x) ((x) >> 16) +#define nx_get_temp_state(x) ((x) & 0xffff) +#define nx_encode_temp(val, state) (((val) << 16) | (state)) + +/* + * Temperature control. + */ +enum { + NX_TEMP_NORMAL = 0x1, /* Normal operating range */ + NX_TEMP_WARN, /* Sound alert, temperature getting high */ + NX_TEMP_PANIC /* Fatal error, hardware has shut down. */ +}; /* Lock IDs for PHY lock */ #define PHY_LOCK_DRIVER 0x44524956 @@ -816,16 +895,24 @@ enum { #define PCIE_DCR 0x00d8 +#define PCIE_SEM0_LOCK (0x1c000) +#define PCIE_SEM0_UNLOCK (0x1c004) +#define PCIE_SEM1_LOCK (0x1c008) +#define PCIE_SEM1_UNLOCK (0x1c00c) #define PCIE_SEM2_LOCK (0x1c010) /* Flash lock */ #define PCIE_SEM2_UNLOCK (0x1c014) /* Flash unlock */ #define PCIE_SEM3_LOCK (0x1c018) /* Phy lock */ #define PCIE_SEM3_UNLOCK (0x1c01c) /* Phy unlock */ +#define PCIE_SEM4_LOCK (0x1c020) +#define PCIE_SEM4_UNLOCK (0x1c024) #define PCIE_SEM5_LOCK (0x1c028) /* API lock */ #define PCIE_SEM5_UNLOCK (0x1c02c) /* API unlock */ #define PCIE_SEM6_LOCK (0x1c030) /* sw lock */ #define PCIE_SEM6_UNLOCK (0x1c034) /* sw unlock */ #define PCIE_SEM7_LOCK (0x1c038) /* crb win lock */ #define PCIE_SEM7_UNLOCK (0x1c03c) /* crbwin unlock*/ +#define PCIE_SEM_LOCK(N) (PCIE_SEM0_LOCK + 8*(N)) +#define PCIE_SEM_UNLOCK(N) (PCIE_SEM0_UNLOCK + 8*(N)) #define PCIE_SETUP_FUNCTION (0x12040) #define PCIE_SETUP_FUNCTION2 (0x12048) @@ -852,8 +939,30 @@ enum { #define NX_PEG_TUNE_MN_PRESENT 0x1 #define NX_PEG_TUNE_CAPABILITY (NETXEN_CAM_RAM(0x02c)) -#define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14) +#define NETXEN_DMA_WATCHDOG_CTRL (NETXEN_CAM_RAM(0x14)) #define NETXEN_PEG_ALIVE_COUNTER (NETXEN_CAM_RAM(0xb0)) +#define NETXEN_PEG_HALT_STATUS1 (NETXEN_CAM_RAM(0xa8)) +#define NETXEN_PEG_HALT_STATUS2 (NETXEN_CAM_RAM(0xac)) +#define NX_CRB_DEV_REF_COUNT (NETXEN_CAM_RAM(0x138)) +#define NX_CRB_DEV_STATE (NETXEN_CAM_RAM(0x140)) + +/* Device State */ +#define NX_DEV_COLD 1 +#define NX_DEV_INITALIZING 2 +#define NX_DEV_READY 3 +#define NX_DEV_NEED_RESET 4 +#define NX_DEV_NEED_QUISCENT 5 +#define NX_DEV_FAILED 6 + +#define NX_RCODE_DRIVER_INFO 0x20000000 +#define NX_RCODE_DRIVER_CAN_RELOAD 0x40000000 +#define NX_RCODE_FATAL_ERROR 0x80000000 +#define NX_FWERROR_PEGNUM(code) ((code) & 0xff) +#define NX_FWERROR_CODE(code) ((code >> 8) & 0xfffff) + +#define FW_POLL_DELAY (2 * HZ) +#define FW_FAIL_THRESH 3 +#define FW_POLL_THRESH 10 #define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC))) #define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index b9123d445c9..32314000dfc 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2003 - 2009 NetXen, Inc. + * Copyright (C) 2009 - QLogic Corporation. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -20,17 +21,10 @@ * The full GNU General Public License is included in this distribution * in the file called LICENSE. * - * Contact Information: - * info@netxen.com - * NetXen Inc, - * 18922 Forge Drive - * Cupertino, CA 95014-0701 - * */ #include "netxen_nic.h" #include "netxen_nic_hw.h" -#include "netxen_nic_phan_reg.h" #include <net/ip.h> @@ -87,7 +81,6 @@ static void __iomem *pci_base_offset(struct netxen_adapter *adapter, return NULL; } -#define CRB_WIN_LOCK_TIMEOUT 100000000 static crb_128M_2M_block_map_t crb_128M_2M_map[64] __cacheline_aligned_in_smp = { {{{0, 0, 0, 0} } }, /* 0: PCI */ @@ -321,6 +314,64 @@ static unsigned crb_hub_agt[64] = #define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */ +#define NETXEN_PCIE_SEM_TIMEOUT 10000 + +int +netxen_pcie_sem_lock(struct netxen_adapter *adapter, int sem, u32 id_reg) +{ + int done = 0, timeout = 0; + + while (!done) { + done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM_LOCK(sem))); + if (done == 1) + break; + if (++timeout >= NETXEN_PCIE_SEM_TIMEOUT) + return -1; + msleep(1); + } + + if (id_reg) + NXWR32(adapter, id_reg, adapter->portnum); + + return 0; +} + +void +netxen_pcie_sem_unlock(struct netxen_adapter *adapter, int sem) +{ + int val; + val = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM_UNLOCK(sem))); +} + +int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port) +{ + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447); + NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5); + } + + return 0; +} + +/* Disable an XG interface */ +int netxen_niu_disable_xg_port(struct netxen_adapter *adapter) +{ + __u32 mac_cfg; + u32 port = adapter->physical_port; + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + return 0; + + if (port > NETXEN_NIU_MAX_XG_PORTS) + return -EINVAL; + + mac_cfg = 0; + if (NXWR32(adapter, + NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg)) + return -EIO; + return 0; +} + #define NETXEN_UNICAST_ADDR(port, index) \ (NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8)) #define NETXEN_MCAST_ADDR(port, index) \ @@ -330,6 +381,56 @@ static unsigned crb_hub_agt[64] = #define MAC_LO(addr) \ ((addr[5] << 16) | (addr[4] << 8) | (addr[3])) +int netxen_p2_nic_set_promisc(struct netxen_adapter *adapter, u32 mode) +{ + __u32 reg; + u32 port = adapter->physical_port; + + if (port > NETXEN_NIU_MAX_XG_PORTS) + return -EINVAL; + + reg = NXRD32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port)); + if (mode == NETXEN_NIU_PROMISC_MODE) + reg = (reg | 0x2000UL); + else + reg = (reg & ~0x2000UL); + + if (mode == NETXEN_NIU_ALLMULTI_MODE) + reg = (reg | 0x1000UL); + else + reg = (reg & ~0x1000UL); + + NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg); + + return 0; +} + +int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr) +{ + u32 mac_hi, mac_lo; + u32 reg_hi, reg_lo; + + u8 phy = adapter->physical_port; + + if (phy >= NETXEN_NIU_MAX_XG_PORTS) + return -EINVAL; + + mac_lo = ((u32)addr[0] << 16) | ((u32)addr[1] << 24); + mac_hi = addr[2] | ((u32)addr[3] << 8) | + ((u32)addr[4] << 16) | ((u32)addr[5] << 24); + + reg_lo = NETXEN_NIU_XGE_STATION_ADDR_0_1 + (0x10000 * phy); + reg_hi = NETXEN_NIU_XGE_STATION_ADDR_0_HI + (0x10000 * phy); + + /* write twice to flush */ + if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi)) + return -EIO; + if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi)) + return -EIO; + + return 0; +} + static int netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter) { @@ -460,6 +561,9 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, i = 0; + if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) + return -EIO; + tx_ring = adapter->tx_ring; __netif_tx_lock_bh(tx_ring->txq); @@ -643,7 +747,7 @@ int netxen_config_intr_coalesce(struct netxen_adapter *adapter) memset(&req, 0, sizeof(nx_nic_req_t)); - req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23); + req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); word = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16); req.req_hdr = cpu_to_le64(word); @@ -659,6 +763,66 @@ int netxen_config_intr_coalesce(struct netxen_adapter *adapter) return rv; } +int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable) +{ + nx_nic_req_t req; + u64 word; + int rv = 0; + + if ((adapter->flags & NETXEN_NIC_LRO_ENABLED) == enable) + return 0; + + memset(&req, 0, sizeof(nx_nic_req_t)); + + req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); + + word = NX_NIC_H2C_OPCODE_CONFIG_HW_LRO | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + req.words[0] = cpu_to_le64(enable); + + rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) { + printk(KERN_ERR "ERROR. Could not send " + "configure hw lro request\n"); + } + + adapter->flags ^= NETXEN_NIC_LRO_ENABLED; + + return rv; +} + +int netxen_config_bridged_mode(struct netxen_adapter *adapter, int enable) +{ + nx_nic_req_t req; + u64 word; + int rv = 0; + + if (!!(adapter->flags & NETXEN_NIC_BRIDGE_ENABLED) == enable) + return rv; + + memset(&req, 0, sizeof(nx_nic_req_t)); + + req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); + + word = NX_NIC_H2C_OPCODE_CONFIG_BRIDGING | + ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + req.words[0] = cpu_to_le64(enable); + + rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) { + printk(KERN_ERR "ERROR. Could not send " + "configure bridge mode request\n"); + } + + adapter->flags ^= NETXEN_NIC_BRIDGE_ENABLED; + + return rv; +} + + #define RSS_HASHTYPE_IP_TCP 0x3 int netxen_config_rss(struct netxen_adapter *adapter, int enable) @@ -706,6 +870,30 @@ int netxen_config_rss(struct netxen_adapter *adapter, int enable) return rv; } +int netxen_config_ipaddr(struct netxen_adapter *adapter, u32 ip, int cmd) +{ + nx_nic_req_t req; + u64 word; + int rv; + + memset(&req, 0, sizeof(nx_nic_req_t)); + req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); + + word = NX_NIC_H2C_OPCODE_CONFIG_IPADDR | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + req.words[0] = cpu_to_le64(cmd); + req.words[1] = cpu_to_le64(ip); + + rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) { + printk(KERN_ERR "%s: could not notify %s IP 0x%x reuqest\n", + adapter->netdev->name, + (cmd == NX_IP_UP) ? "Add" : "Remove", ip); + } + return rv; +} + int netxen_linkevent_request(struct netxen_adapter *adapter, int enable) { nx_nic_req_t req; @@ -728,6 +916,29 @@ int netxen_linkevent_request(struct netxen_adapter *adapter, int enable) return rv; } +int netxen_send_lro_cleanup(struct netxen_adapter *adapter) +{ + nx_nic_req_t req; + u64 word; + int rv; + + memset(&req, 0, sizeof(nx_nic_req_t)); + req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); + + word = NX_NIC_H2C_OPCODE_LRO_REQUEST | + ((u64)adapter->portnum << 16) | + ((u64)NX_NIC_LRO_REQUEST_CLEANUP << 56) ; + + req.req_hdr = cpu_to_le64(word); + + rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) { + printk(KERN_ERR "%s: could not cleanup lro flows\n", + adapter->netdev->name); + } + return rv; +} + /* * netxen_nic_change_mtu - Change the Maximum Transfer Unit * @returns 0 on success, negative on failure @@ -792,18 +1003,15 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac) __le32 *pmac = (__le32 *) mac; u32 offset; - offset = NETXEN_USER_START + - offsetof(struct netxen_new_user_info, mac_addr) + - adapter->portnum * sizeof(u64); + offset = NX_FW_MAC_ADDR_OFFSET + (adapter->portnum * sizeof(u64)); if (netxen_get_flash_block(adapter, offset, sizeof(u64), pmac) == -1) return -1; if (*mac == cpu_to_le64(~0ULL)) { - offset = NETXEN_USER_START_OLD + - offsetof(struct netxen_user_old_info, mac_addr) + - adapter->portnum * sizeof(u64); + offset = NX_OLD_MAC_ADDR_OFFSET + + (adapter->portnum * sizeof(u64)); if (netxen_get_flash_block(adapter, offset, sizeof(u64), pmac) == -1) @@ -834,37 +1042,10 @@ int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac) return 0; } -#define CRB_WIN_LOCK_TIMEOUT 100000000 - -static int crb_win_lock(struct netxen_adapter *adapter) -{ - int done = 0, timeout = 0; - - while (!done) { - /* acquire semaphore3 from PCI HW block */ - done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM7_LOCK)); - if (done == 1) - break; - if (timeout >= CRB_WIN_LOCK_TIMEOUT) - return -1; - timeout++; - udelay(1); - } - NXWR32(adapter, NETXEN_CRB_WIN_LOCK_ID, adapter->portnum); - return 0; -} - -static void crb_win_unlock(struct netxen_adapter *adapter) -{ - int val; - - val = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK)); -} - /* * Changes the CRB window to the specified window. */ -void +static void netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw) { void __iomem *offset; @@ -977,61 +1158,68 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off) (ulong)adapter->ahw.pci_base0; } -int +static int netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data) { + unsigned long flags; void __iomem *addr; - if (ADDR_IN_WINDOW1(off)) { + if (ADDR_IN_WINDOW1(off)) addr = NETXEN_CRB_NORMALIZE(adapter, off); + else + addr = pci_base_offset(adapter, off); + + BUG_ON(!addr); + + if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ + read_lock(&adapter->adapter_lock); + writel(data, addr); + read_unlock(&adapter->adapter_lock); } else { /* Window 0 */ + write_lock_irqsave(&adapter->adapter_lock, flags); addr = pci_base_offset(adapter, off); netxen_nic_pci_change_crbwindow_128M(adapter, 0); - } - - if (!addr) { + writel(data, addr); netxen_nic_pci_change_crbwindow_128M(adapter, 1); - return 1; + write_unlock_irqrestore(&adapter->adapter_lock, flags); } - writel(data, addr); - - if (!ADDR_IN_WINDOW1(off)) - netxen_nic_pci_change_crbwindow_128M(adapter, 1); - return 0; } -u32 +static u32 netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off) { + unsigned long flags; void __iomem *addr; u32 data; - if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ + if (ADDR_IN_WINDOW1(off)) addr = NETXEN_CRB_NORMALIZE(adapter, off); - } else { /* Window 0 */ + else addr = pci_base_offset(adapter, off); - netxen_nic_pci_change_crbwindow_128M(adapter, 0); - } - - if (!addr) { - netxen_nic_pci_change_crbwindow_128M(adapter, 1); - return 1; - } - data = readl(addr); + BUG_ON(!addr); - if (!ADDR_IN_WINDOW1(off)) + if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ + read_lock(&adapter->adapter_lock); + data = readl(addr); + read_unlock(&adapter->adapter_lock); + } else { /* Window 0 */ + write_lock_irqsave(&adapter->adapter_lock, flags); + netxen_nic_pci_change_crbwindow_128M(adapter, 0); + data = readl(addr); netxen_nic_pci_change_crbwindow_128M(adapter, 1); + write_unlock_irqrestore(&adapter->adapter_lock, flags); + } return data; } -int +static int netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data) { - unsigned long flags = 0; + unsigned long flags; int rv; rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off); @@ -1057,10 +1245,10 @@ netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data) return 0; } -u32 +static u32 netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off) { - unsigned long flags = 0; + unsigned long flags; int rv; u32 data; @@ -1086,28 +1274,9 @@ netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off) return data; } -/* - * check memory access boundary. - * used by test agent. support ddr access only for now - */ -static unsigned long -netxen_nic_pci_mem_bound_check(struct netxen_adapter *adapter, - unsigned long long addr, int size) -{ - if (!ADDR_IN_RANGE(addr, - NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX) || - !ADDR_IN_RANGE(addr+size-1, - NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX) || - ((size != 1) && (size != 2) && (size != 4) && (size != 8))) { - return 0; - } - - return 1; -} - static int netxen_pci_set_window_warning_count; -unsigned long +static unsigned long netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter, unsigned long long addr) { @@ -1171,22 +1340,56 @@ netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter, return addr; } -/* - * Note : only 32-bit writes! - */ -int netxen_nic_pci_write_immediate_128M(struct netxen_adapter *adapter, - u64 off, u32 data) +/* window 1 registers only */ +static void netxen_nic_io_write_128M(struct netxen_adapter *adapter, + void __iomem *addr, u32 data) { - writel(data, (void __iomem *)(PCI_OFFSET_SECOND_RANGE(adapter, off))); - return 0; + read_lock(&adapter->adapter_lock); + writel(data, addr); + read_unlock(&adapter->adapter_lock); } -u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off) +static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, + void __iomem *addr) { - return readl((void __iomem *)(pci_base_offset(adapter, off))); + u32 val; + + read_lock(&adapter->adapter_lock); + val = readl(addr); + read_unlock(&adapter->adapter_lock); + + return val; } -unsigned long +static void netxen_nic_io_write_2M(struct netxen_adapter *adapter, + void __iomem *addr, u32 data) +{ + writel(data, addr); +} + +static u32 netxen_nic_io_read_2M(struct netxen_adapter *adapter, + void __iomem *addr) +{ + return readl(addr); +} + +void __iomem * +netxen_get_ioaddr(struct netxen_adapter *adapter, u32 offset) +{ + ulong off = offset; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + if (offset < NETXEN_CRB_PCIX_HOST2 && + offset > NETXEN_CRB_PCIX_HOST) + return PCI_OFFSET_SECOND_RANGE(adapter, offset); + return NETXEN_CRB_NORMALIZE(adapter, offset); + } + + BUG_ON(netxen_nic_pci_get_crb_addr_2M(adapter, &off)); + return (void __iomem *)off; +} + +static unsigned long netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, unsigned long long addr) { @@ -1197,10 +1400,8 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, /* DDR network side */ window = MN_WIN(addr); adapter->ahw.ddr_mn_window = window; - NXWR32(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, - window); - win_read = NXRD32(adapter, - adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE); + NXWR32(adapter, adapter->ahw.mn_win_crb, window); + win_read = NXRD32(adapter, adapter->ahw.mn_win_crb); if ((win_read << 17) != window) { printk(KERN_INFO "Written MNwin (0x%x) != " "Read MNwin (0x%x)\n", window, win_read); @@ -1215,10 +1416,8 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, window = OCM_WIN(addr); adapter->ahw.ddr_mn_window = window; - NXWR32(adapter, adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE, - window); - win_read = NXRD32(adapter, - adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE); + NXWR32(adapter, adapter->ahw.mn_win_crb, window); + win_read = NXRD32(adapter, adapter->ahw.mn_win_crb); if ((win_read >> 7) != window) { printk(KERN_INFO "%s: Written OCMwin (0x%x) != " "Read OCMwin (0x%x)\n", @@ -1231,10 +1430,8 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, /* QDR network side */ window = MS_WIN(addr); adapter->ahw.qdr_sn_window = window; - NXWR32(adapter, adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE, - window); - win_read = NXRD32(adapter, - adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE); + NXWR32(adapter, adapter->ahw.ms_win_crb, window); + win_read = NXRD32(adapter, adapter->ahw.ms_win_crb); if (win_read != window) { printk(KERN_INFO "%s: Written MSwin (0x%x) != " "Read MSwin (0x%x)\n", @@ -1257,180 +1454,9 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, return addr; } -static int netxen_nic_pci_is_same_window(struct netxen_adapter *adapter, - unsigned long long addr) -{ - int window; - unsigned long long qdr_max; - - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) - qdr_max = NETXEN_ADDR_QDR_NET_MAX_P2; - else - qdr_max = NETXEN_ADDR_QDR_NET_MAX_P3; - - if (ADDR_IN_RANGE(addr, - NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { - /* DDR network side */ - BUG(); /* MN access can not come here */ - } else if (ADDR_IN_RANGE(addr, - NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { - return 1; - } else if (ADDR_IN_RANGE(addr, - NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { - return 1; - } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) { - /* QDR network side */ - window = ((addr - NETXEN_ADDR_QDR_NET) >> 22) & 0x3f; - if (adapter->ahw.qdr_sn_window == window) - return 1; - } - - return 0; -} - -static int netxen_nic_pci_mem_read_direct(struct netxen_adapter *adapter, - u64 off, void *data, int size) -{ - unsigned long flags; - void __iomem *addr, *mem_ptr = NULL; - int ret = 0; - u64 start; - unsigned long mem_base; - unsigned long mem_page; - - write_lock_irqsave(&adapter->adapter_lock, flags); - - /* - * If attempting to access unknown address or straddle hw windows, - * do not access. - */ - start = adapter->pci_set_window(adapter, off); - if ((start == -1UL) || - (netxen_nic_pci_is_same_window(adapter, off+size-1) == 0)) { - write_unlock_irqrestore(&adapter->adapter_lock, flags); - printk(KERN_ERR "%s out of bound pci memory access. " - "offset is 0x%llx\n", netxen_nic_driver_name, - (unsigned long long)off); - return -1; - } - - addr = pci_base_offset(adapter, start); - if (!addr) { - write_unlock_irqrestore(&adapter->adapter_lock, flags); - mem_base = pci_resource_start(adapter->pdev, 0); - mem_page = start & PAGE_MASK; - /* Map two pages whenever user tries to access addresses in two - consecutive pages. - */ - if (mem_page != ((start + size - 1) & PAGE_MASK)) - mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2); - else - mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); - if (mem_ptr == NULL) { - *(uint8_t *)data = 0; - return -1; - } - addr = mem_ptr; - addr += start & (PAGE_SIZE - 1); - write_lock_irqsave(&adapter->adapter_lock, flags); - } - - switch (size) { - case 1: - *(uint8_t *)data = readb(addr); - break; - case 2: - *(uint16_t *)data = readw(addr); - break; - case 4: - *(uint32_t *)data = readl(addr); - break; - case 8: - *(uint64_t *)data = readq(addr); - break; - default: - ret = -1; - break; - } - write_unlock_irqrestore(&adapter->adapter_lock, flags); - - if (mem_ptr) - iounmap(mem_ptr); - return ret; -} - -static int -netxen_nic_pci_mem_write_direct(struct netxen_adapter *adapter, u64 off, - void *data, int size) -{ - unsigned long flags; - void __iomem *addr, *mem_ptr = NULL; - int ret = 0; - u64 start; - unsigned long mem_base; - unsigned long mem_page; - - write_lock_irqsave(&adapter->adapter_lock, flags); - - /* - * If attempting to access unknown address or straddle hw windows, - * do not access. - */ - start = adapter->pci_set_window(adapter, off); - if ((start == -1UL) || - (netxen_nic_pci_is_same_window(adapter, off+size-1) == 0)) { - write_unlock_irqrestore(&adapter->adapter_lock, flags); - printk(KERN_ERR "%s out of bound pci memory access. " - "offset is 0x%llx\n", netxen_nic_driver_name, - (unsigned long long)off); - return -1; - } - - addr = pci_base_offset(adapter, start); - if (!addr) { - write_unlock_irqrestore(&adapter->adapter_lock, flags); - mem_base = pci_resource_start(adapter->pdev, 0); - mem_page = start & PAGE_MASK; - /* Map two pages whenever user tries to access addresses in two - * consecutive pages. - */ - if (mem_page != ((start + size - 1) & PAGE_MASK)) - mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2); - else - mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE); - if (mem_ptr == NULL) - return -1; - addr = mem_ptr; - addr += start & (PAGE_SIZE - 1); - write_lock_irqsave(&adapter->adapter_lock, flags); - } - - switch (size) { - case 1: - writeb(*(uint8_t *)data, addr); - break; - case 2: - writew(*(uint16_t *)data, addr); - break; - case 4: - writel(*(uint32_t *)data, addr); - break; - case 8: - writeq(*(uint64_t *)data, addr); - break; - default: - ret = -1; - break; - } - write_unlock_irqrestore(&adapter->adapter_lock, flags); - if (mem_ptr) - iounmap(mem_ptr); - return ret; -} - #define MAX_CTL_CHECK 1000 -int +static int netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, u64 off, void *data, int size) { @@ -1440,19 +1466,28 @@ netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, uint64_t off8, tmpw, word[2] = {0, 0}; void __iomem *mem_crb; - /* - * If not MN, go check for MS or invalid. - */ - if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0) - return netxen_nic_pci_mem_write_direct(adapter, - off, data, size); + if (size != 8) + return -EIO; + if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, + NETXEN_ADDR_QDR_NET_MAX_P2)) { + mem_crb = pci_base_offset(adapter, NETXEN_CRB_QDR_NET); + goto correct; + } + + if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { + mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET); + goto correct; + } + + return -EIO; + +correct: off8 = off & 0xfffffff8; off0 = off & 0x7; sz[0] = (size < (8 - off0)) ? size : (8 - off0); sz[1] = size - sz[0]; loop = ((off0 + size - 1) >> 3) + 1; - mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET); if ((size != 8) || (off0 != 0)) { for (i = 0; i < loop; i++) { @@ -1523,7 +1558,7 @@ netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, return ret; } -int +static int netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, u64 off, void *data, int size) { @@ -1533,20 +1568,29 @@ netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, uint64_t off8, val, word[2] = {0, 0}; void __iomem *mem_crb; + if (size != 8) + return -EIO; - /* - * If not MN, go check for MS or invalid. - */ - if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0) - return netxen_nic_pci_mem_read_direct(adapter, off, data, size); + if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, + NETXEN_ADDR_QDR_NET_MAX_P2)) { + mem_crb = pci_base_offset(adapter, NETXEN_CRB_QDR_NET); + goto correct; + } + + if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { + mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET); + goto correct; + } + + return -EIO; +correct: off8 = off & 0xfffffff8; off0[0] = off & 0x7; off0[1] = 0; sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]); sz[1] = size - sz[0]; loop = ((off0[0] + size - 1) >> 3) + 1; - mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET); write_lock_irqsave(&adapter->adapter_lock, flags); netxen_nic_pci_change_crbwindow_128M(adapter, 0); @@ -1614,26 +1658,32 @@ netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, return 0; } -int +static int netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, u64 off, void *data, int size) { int i, j, ret = 0, loop, sz[2], off0; uint32_t temp; - uint64_t off8, mem_crb, tmpw, word[2] = {0, 0}; + uint64_t off8, tmpw, word[2] = {0, 0}; + void __iomem *mem_crb; - /* - * If not MN, go check for MS or invalid. - */ - if (off >= NETXEN_ADDR_QDR_NET && off <= NETXEN_ADDR_QDR_NET_MAX_P3) - mem_crb = NETXEN_CRB_QDR_NET; - else { - mem_crb = NETXEN_CRB_DDR_NET; - if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0) - return netxen_nic_pci_mem_write_direct(adapter, - off, data, size); + if (size != 8) + return -EIO; + + if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, + NETXEN_ADDR_QDR_NET_MAX_P3)) { + mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_QDR_NET); + goto correct; } + if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { + mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_DDR_NET); + goto correct; + } + + return -EIO; + +correct: off8 = off & 0xfffffff8; off0 = off & 0x7; sz[0] = (size < (8 - off0)) ? size : (8 - off0); @@ -1642,8 +1692,8 @@ netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, if ((size != 8) || (off0 != 0)) { for (i = 0; i < loop; i++) { - if (adapter->pci_mem_read(adapter, off8 + (i << 3), - &word[i], 8)) + if (adapter->pci_mem_read(adapter, + off8 + (i << 3), &word[i], 8)) return -1; } } @@ -1679,21 +1729,18 @@ netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, */ for (i = 0; i < loop; i++) { - temp = off8 + (i << 3); - NXWR32(adapter, mem_crb+MIU_TEST_AGT_ADDR_LO, temp); - temp = 0; - NXWR32(adapter, mem_crb+MIU_TEST_AGT_ADDR_HI, temp); - temp = word[i] & 0xffffffff; - NXWR32(adapter, mem_crb+MIU_TEST_AGT_WRDATA_LO, temp); - temp = (word[i] >> 32) & 0xffffffff; - NXWR32(adapter, mem_crb+MIU_TEST_AGT_WRDATA_HI, temp); - temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; - NXWR32(adapter, mem_crb+MIU_TEST_AGT_CTRL, temp); - temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE; - NXWR32(adapter, mem_crb+MIU_TEST_AGT_CTRL, temp); + writel(off8 + (i << 3), mem_crb+MIU_TEST_AGT_ADDR_LO); + writel(0, mem_crb+MIU_TEST_AGT_ADDR_HI); + writel(word[i] & 0xffffffff, mem_crb+MIU_TEST_AGT_WRDATA_LO); + writel((word[i] >> 32) & 0xffffffff, + mem_crb+MIU_TEST_AGT_WRDATA_HI); + writel((MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE), + mem_crb+MIU_TEST_AGT_CTRL); + writel(MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE, + mem_crb+MIU_TEST_AGT_CTRL); for (j = 0; j < MAX_CTL_CHECK; j++) { - temp = NXRD32(adapter, mem_crb + MIU_TEST_AGT_CTRL); + temp = readl(mem_crb + MIU_TEST_AGT_CTRL); if ((temp & MIU_TA_CTL_BUSY) == 0) break; } @@ -1714,27 +1761,32 @@ netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, return ret; } -int +static int netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, u64 off, void *data, int size) { int i, j = 0, k, start, end, loop, sz[2], off0[2]; uint32_t temp; - uint64_t off8, val, mem_crb, word[2] = {0, 0}; + uint64_t off8, val, word[2] = {0, 0}; + void __iomem *mem_crb; - /* - * If not MN, go check for MS or invalid. - */ + if (size != 8) + return -EIO; - if (off >= NETXEN_ADDR_QDR_NET && off <= NETXEN_ADDR_QDR_NET_MAX_P3) - mem_crb = NETXEN_CRB_QDR_NET; - else { - mem_crb = NETXEN_CRB_DDR_NET; - if (netxen_nic_pci_mem_bound_check(adapter, off, size) == 0) - return netxen_nic_pci_mem_read_direct(adapter, - off, data, size); + if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, + NETXEN_ADDR_QDR_NET_MAX_P3)) { + mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_QDR_NET); + goto correct; } + if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { + mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_DDR_NET); + goto correct; + } + + return -EIO; + +correct: off8 = off & 0xfffffff8; off0[0] = off & 0x7; off0[1] = 0; @@ -1749,17 +1801,14 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, */ for (i = 0; i < loop; i++) { - temp = off8 + (i << 3); - NXWR32(adapter, mem_crb + MIU_TEST_AGT_ADDR_LO, temp); - temp = 0; - NXWR32(adapter, mem_crb + MIU_TEST_AGT_ADDR_HI, temp); - temp = MIU_TA_CTL_ENABLE; - NXWR32(adapter, mem_crb + MIU_TEST_AGT_CTRL, temp); - temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; - NXWR32(adapter, mem_crb + MIU_TEST_AGT_CTRL, temp); + writel(off8 + (i << 3), mem_crb + MIU_TEST_AGT_ADDR_LO); + writel(0, mem_crb + MIU_TEST_AGT_ADDR_HI); + writel(MIU_TA_CTL_ENABLE, mem_crb + MIU_TEST_AGT_CTRL); + writel(MIU_TA_CTL_START | MIU_TA_CTL_ENABLE, + mem_crb + MIU_TEST_AGT_CTRL); for (j = 0; j < MAX_CTL_CHECK; j++) { - temp = NXRD32(adapter, mem_crb + MIU_TEST_AGT_CTRL); + temp = readl(mem_crb + MIU_TEST_AGT_CTRL); if ((temp & MIU_TA_CTL_BUSY) == 0) break; } @@ -1774,8 +1823,7 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, start = off0[i] >> 2; end = (off0[i] + sz[i] - 1) >> 2; for (k = start; k <= end; k++) { - temp = NXRD32(adapter, - mem_crb + MIU_TEST_AGT_RDDATA(k)); + temp = readl(mem_crb + MIU_TEST_AGT_RDDATA(k)); word[i] |= ((uint64_t)temp << (32 * k)); } } @@ -1812,20 +1860,43 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, return 0; } -/* - * Note : only 32-bit writes! - */ -int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter, - u64 off, u32 data) +void +netxen_setup_hwops(struct netxen_adapter *adapter) { - NXWR32(adapter, off, data); + adapter->init_port = netxen_niu_xg_init_port; + adapter->stop_port = netxen_niu_disable_xg_port; - return 0; -} + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + adapter->crb_read = netxen_nic_hw_read_wx_128M, + adapter->crb_write = netxen_nic_hw_write_wx_128M, + adapter->pci_set_window = netxen_nic_pci_set_window_128M, + adapter->pci_mem_read = netxen_nic_pci_mem_read_128M, + adapter->pci_mem_write = netxen_nic_pci_mem_write_128M, + adapter->io_read = netxen_nic_io_read_128M, + adapter->io_write = netxen_nic_io_write_128M, + + adapter->macaddr_set = netxen_p2_nic_set_mac_addr; + adapter->set_multi = netxen_p2_nic_set_multi; + adapter->set_mtu = netxen_nic_set_mtu_xgb; + adapter->set_promisc = netxen_p2_nic_set_promisc; -u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off) -{ - return NXRD32(adapter, off); + } else { + adapter->crb_read = netxen_nic_hw_read_wx_2M, + adapter->crb_write = netxen_nic_hw_write_wx_2M, + adapter->pci_set_window = netxen_nic_pci_set_window_2M, + adapter->pci_mem_read = netxen_nic_pci_mem_read_2M, + adapter->pci_mem_write = netxen_nic_pci_mem_write_2M, + adapter->io_read = netxen_nic_io_read_2M, + adapter->io_write = netxen_nic_io_write_2M, + + adapter->set_mtu = nx_fw_cmd_set_mtu; + adapter->set_promisc = netxen_p3_nic_set_promisc; + adapter->macaddr_set = netxen_p3_nic_set_mac_addr; + adapter->set_multi = netxen_p3_nic_set_multi; + + adapter->phy_read = nx_fw_cmd_query_phy; + adapter->phy_write = nx_fw_cmd_set_phy; + } } int netxen_nic_get_board_info(struct netxen_adapter *adapter) @@ -1833,13 +1904,11 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) int offset, board_type, magic, header_version; struct pci_dev *pdev = adapter->pdev; - offset = NETXEN_BRDCFG_START + - offsetof(struct netxen_board_info, magic); + offset = NX_FW_MAGIC_OFFSET; if (netxen_rom_fast_read(adapter, offset, &magic)) return -EIO; - offset = NETXEN_BRDCFG_START + - offsetof(struct netxen_board_info, header_version); + offset = NX_HDR_VERSION_OFFSET; if (netxen_rom_fast_read(adapter, offset, &header_version)) return -EIO; @@ -1851,8 +1920,7 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) return -EIO; } - offset = NETXEN_BRDCFG_START + - offsetof(struct netxen_board_info, board_type); + offset = NX_BRDTYPE_OFFSET; if (netxen_rom_fast_read(adapter, offset, &board_type)) return -EIO; @@ -1993,62 +2061,6 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) } } -void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) -{ - u32 fw_major, fw_minor, fw_build; - char brd_name[NETXEN_MAX_SHORT_NAME]; - char serial_num[32]; - int i, addr, val; - int *ptr32; - struct pci_dev *pdev = adapter->pdev; - - adapter->driver_mismatch = 0; - - ptr32 = (int *)&serial_num; - addr = NETXEN_USER_START + - offsetof(struct netxen_new_user_info, serial_num); - for (i = 0; i < 8; i++) { - if (netxen_rom_fast_read(adapter, addr, &val) == -1) { - dev_err(&pdev->dev, "error reading board info\n"); - adapter->driver_mismatch = 1; - return; - } - ptr32[i] = cpu_to_le32(val); - addr += sizeof(u32); - } - - fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); - fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); - fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); - - adapter->fw_major = fw_major; - adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build); - - if (adapter->portnum == 0) { - get_brd_name_by_type(adapter->ahw.board_type, brd_name); - - printk(KERN_INFO "NetXen %s Board S/N %s Chip rev 0x%x\n", - brd_name, serial_num, adapter->ahw.revision_id); - } - - if (adapter->fw_version < NETXEN_VERSION_CODE(3, 4, 216)) { - adapter->driver_mismatch = 1; - dev_warn(&pdev->dev, "firmware version %d.%d.%d unsupported\n", - fw_major, fw_minor, fw_build); - return; - } - - dev_info(&pdev->dev, "firmware version %d.%d.%d\n", - fw_major, fw_minor, fw_build); - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - i = NXRD32(adapter, NETXEN_SRE_MISC); - adapter->ahw.cut_through = (i & 0x8000) ? 1 : 0; - dev_info(&pdev->dev, "firmware running in %s mode\n", - adapter->ahw.cut_through ? "cut-through" : "legacy"); - } -} - int netxen_nic_wol_supported(struct netxen_adapter *adapter) { diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h index d4e83333978..3fd1dcb3583 100644 --- a/drivers/net/netxen/netxen_nic_hw.h +++ b/drivers/net/netxen/netxen_nic_hw.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2003 - 2009 NetXen, Inc. + * Copyright (C) 2009 - QLogic Corporation. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -20,19 +21,11 @@ * The full GNU General Public License is included in this distribution * in the file called LICENSE. * - * Contact Information: - * info@netxen.com - * NetXen Inc, - * 18922 Forge Drive - * Cupertino, CA 95014-0701 - * */ #ifndef __NETXEN_NIC_HW_H_ #define __NETXEN_NIC_HW_H_ -#include "netxen_nic_hdr.h" - /* Hardware memory size of 128 meg */ #define NETXEN_MEMADDR_MAX (128 * 1024 * 1024) @@ -63,10 +56,6 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter); * Bit 31: soft_reset => 1:reset the MAC and the SERDES, 0:no-op */ -#define netxen_gb_enable_tx(config_word) \ - ((config_word) |= 1 << 0) -#define netxen_gb_enable_rx(config_word) \ - ((config_word) |= 1 << 2) #define netxen_gb_tx_flowctl(config_word) \ ((config_word) |= 1 << 4) #define netxen_gb_rx_flowctl(config_word) \ @@ -79,8 +68,6 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter); ((config_word) |= 1 << 18) #define netxen_gb_rx_reset_mac(config_word) \ ((config_word) |= 1 << 19) -#define netxen_gb_soft_reset(config_word) \ - ((config_word) |= 1 << 31) #define netxen_gb_unset_tx_flowctl(config_word) \ ((config_word) &= ~(1 << 4)) @@ -242,7 +229,6 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter); * Bits 14-15 : speed => 0:10Mb/s, 1:100Mb/s, 2:1000Mb/s, 3:rsvd */ -#define netxen_get_phy_cablelen(config_word) (((config_word) >> 7) & 0x07) #define netxen_get_phy_speed(config_word) (((config_word) >> 14) & 0x03) #define netxen_set_phy_speed(config_word, val) \ @@ -252,85 +238,12 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter); #define netxen_clear_phy_duplex(config_word) \ ((config_word) &= ~(1 << 13)) -#define netxen_get_phy_jabber(config_word) \ - _netxen_crb_get_bit(config_word, 0) -#define netxen_get_phy_polarity(config_word) \ - _netxen_crb_get_bit(config_word, 1) -#define netxen_get_phy_recvpause(config_word) \ - _netxen_crb_get_bit(config_word, 2) -#define netxen_get_phy_xmitpause(config_word) \ - _netxen_crb_get_bit(config_word, 3) -#define netxen_get_phy_energydetect(config_word) \ - _netxen_crb_get_bit(config_word, 4) -#define netxen_get_phy_downshift(config_word) \ - _netxen_crb_get_bit(config_word, 5) -#define netxen_get_phy_crossover(config_word) \ - _netxen_crb_get_bit(config_word, 6) #define netxen_get_phy_link(config_word) \ _netxen_crb_get_bit(config_word, 10) -#define netxen_get_phy_resolved(config_word) \ - _netxen_crb_get_bit(config_word, 11) -#define netxen_get_phy_pagercvd(config_word) \ - _netxen_crb_get_bit(config_word, 12) #define netxen_get_phy_duplex(config_word) \ _netxen_crb_get_bit(config_word, 13) /* - * Interrupt Register definition - * This definition applies to registers 18 and 19 (int enable and int status). - * Bit 0 : jabber - * Bit 1 : polarity_changed - * Bit 4 : energy_detect - * Bit 5 : downshift - * Bit 6 : mdi_xover_changed - * Bit 7 : fifo_over_underflow - * Bit 8 : false_carrier - * Bit 9 : symbol_error - * Bit 10: link_status_changed - * Bit 11: autoneg_completed - * Bit 12: page_received - * Bit 13: duplex_changed - * Bit 14: speed_changed - * Bit 15: autoneg_error - */ - -#define netxen_get_phy_int_jabber(config_word) \ - _netxen_crb_get_bit(config_word, 0) -#define netxen_get_phy_int_polarity_changed(config_word) \ - _netxen_crb_get_bit(config_word, 1) -#define netxen_get_phy_int_energy_detect(config_word) \ - _netxen_crb_get_bit(config_word, 4) -#define netxen_get_phy_int_downshift(config_word) \ - _netxen_crb_get_bit(config_word, 5) -#define netxen_get_phy_int_mdi_xover_changed(config_word) \ - _netxen_crb_get_bit(config_word, 6) -#define netxen_get_phy_int_fifo_over_underflow(config_word) \ - _netxen_crb_get_bit(config_word, 7) -#define netxen_get_phy_int_false_carrier(config_word) \ - _netxen_crb_get_bit(config_word, 8) -#define netxen_get_phy_int_symbol_error(config_word) \ - _netxen_crb_get_bit(config_word, 9) -#define netxen_get_phy_int_link_status_changed(config_word) \ - _netxen_crb_get_bit(config_word, 10) -#define netxen_get_phy_int_autoneg_completed(config_word) \ - _netxen_crb_get_bit(config_word, 11) -#define netxen_get_phy_int_page_received(config_word) \ - _netxen_crb_get_bit(config_word, 12) -#define netxen_get_phy_int_duplex_changed(config_word) \ - _netxen_crb_get_bit(config_word, 13) -#define netxen_get_phy_int_speed_changed(config_word) \ - _netxen_crb_get_bit(config_word, 14) -#define netxen_get_phy_int_autoneg_error(config_word) \ - _netxen_crb_get_bit(config_word, 15) - -#define netxen_set_phy_int_link_status_changed(config_word) \ - ((config_word) |= 1 << 10) -#define netxen_set_phy_int_autoneg_completed(config_word) \ - ((config_word) |= 1 << 11) -#define netxen_set_phy_int_speed_changed(config_word) \ - ((config_word) |= 1 << 14) - -/* * NIU Mode Register. * Bit 0 : enable FibreChannel * Bit 1 : enable 10/100/1000 Ethernet @@ -345,33 +258,6 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter); #define NETXEN_NIU_ALLMULTI_MODE 2 /* - * NIU GB Drop CRC Register - * - * Bit 0 : drop_gb0 => 1:drop pkts with bad CRCs, 0:pass them on - * Bit 1 : drop_gb1 => 1:drop pkts with bad CRCs, 0:pass them on - * Bit 2 : drop_gb2 => 1:drop pkts with bad CRCs, 0:pass them on - * Bit 3 : drop_gb3 => 1:drop pkts with bad CRCs, 0:pass them on - */ - -#define netxen_set_gb_drop_gb0(config_word) \ - ((config_word) |= 1 << 0) -#define netxen_set_gb_drop_gb1(config_word) \ - ((config_word) |= 1 << 1) -#define netxen_set_gb_drop_gb2(config_word) \ - ((config_word) |= 1 << 2) -#define netxen_set_gb_drop_gb3(config_word) \ - ((config_word) |= 1 << 3) - -#define netxen_clear_gb_drop_gb0(config_word) \ - ((config_word) &= ~(1 << 0)) -#define netxen_clear_gb_drop_gb1(config_word) \ - ((config_word) &= ~(1 << 1)) -#define netxen_clear_gb_drop_gb2(config_word) \ - ((config_word) &= ~(1 << 2)) -#define netxen_clear_gb_drop_gb3(config_word) \ - ((config_word) &= ~(1 << 3)) - -/* * NIU XG MAC Config Register * * Bit 0 : tx_enable => 1:enable frame xmit, 0:disable @@ -387,22 +273,6 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter); #define netxen_xg_soft_reset(config_word) \ ((config_word) |= 1 << 4) -/* Set promiscuous mode for a GbE interface */ -int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, - u32 mode); -int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, - u32 mode); - -/* Generic enable for GbE ports. Will detect the speed of the link. */ -int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port); - -int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port); - -/* Disable a GbE interface */ -int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter); - -int netxen_niu_disable_xg_port(struct netxen_adapter *adapter); - typedef struct { unsigned valid; unsigned start_128M; diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 5d3343ef3d8..91c2bc61c8e 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2003 - 2009 NetXen, Inc. + * Copyright (C) 2009 - QLogic Corporation. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -20,19 +21,12 @@ * The full GNU General Public License is included in this distribution * in the file called LICENSE. * - * Contact Information: - * info@netxen.com - * NetXen Inc, - * 18922 Forge Drive - * Cupertino, CA 95014-0701 - * */ #include <linux/netdevice.h> #include <linux/delay.h> #include "netxen_nic.h" #include "netxen_nic_hw.h" -#include "netxen_nic_phan_reg.h" struct crb_addr_pair { u32 addr; @@ -247,9 +241,14 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) rds_ring->skb_size = NX_CT_DEFAULT_RX_BUF_LEN; } else { - rds_ring->dma_size = RX_DMA_MAP_LEN; + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + rds_ring->dma_size = + NX_P3_RX_BUF_MAX_LEN; + else + rds_ring->dma_size = + NX_P2_RX_BUF_MAX_LEN; rds_ring->skb_size = - MAX_RX_BUFFER_LENGTH; + rds_ring->dma_size + NET_IP_ALIGN; } break; @@ -261,14 +260,18 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) else rds_ring->dma_size = NX_P2_RX_JUMBO_BUF_MAX_LEN; + + if (adapter->capabilities & NX_CAP0_HW_LRO) + rds_ring->dma_size += NX_LRO_BUFFER_EXTRA; + rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN; break; case RCV_RING_LRO: rds_ring->num_desc = adapter->num_lro_rxd; - rds_ring->dma_size = RX_LRO_DMA_MAP_LEN; - rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH; + rds_ring->dma_size = NX_RX_LRO_BUFFER_LENGTH; + rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN; break; } @@ -315,48 +318,6 @@ err_out: return -ENOMEM; } -void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) -{ - adapter->macaddr_set = netxen_p2_nic_set_mac_addr; - adapter->set_multi = netxen_p2_nic_set_multi; - - switch (adapter->ahw.port_type) { - case NETXEN_NIC_GBE: - adapter->enable_phy_interrupts = - netxen_niu_gbe_enable_phy_interrupts; - adapter->disable_phy_interrupts = - netxen_niu_gbe_disable_phy_interrupts; - adapter->set_mtu = netxen_nic_set_mtu_gb; - adapter->set_promisc = netxen_niu_set_promiscuous_mode; - adapter->phy_read = netxen_niu_gbe_phy_read; - adapter->phy_write = netxen_niu_gbe_phy_write; - adapter->init_port = netxen_niu_gbe_init_port; - adapter->stop_port = netxen_niu_disable_gbe_port; - break; - - case NETXEN_NIC_XGBE: - adapter->enable_phy_interrupts = - netxen_niu_xgbe_enable_phy_interrupts; - adapter->disable_phy_interrupts = - netxen_niu_xgbe_disable_phy_interrupts; - adapter->set_mtu = netxen_nic_set_mtu_xgb; - adapter->init_port = netxen_niu_xg_init_port; - adapter->set_promisc = netxen_niu_xg_set_promiscuous_mode; - adapter->stop_port = netxen_niu_disable_xg_port; - break; - - default: - break; - } - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - adapter->set_mtu = nx_fw_cmd_set_mtu; - adapter->set_promisc = netxen_p3_nic_set_promisc; - adapter->macaddr_set = netxen_p3_nic_set_mac_addr; - adapter->set_multi = netxen_p3_nic_set_multi; - } -} - /* * netxen_decode_crb_addr(0 - utility to translate from internal Phantom CRB * address to external PCI CRB address. @@ -384,37 +345,7 @@ static u32 netxen_decode_crb_addr(u32 addr) return (pci_base + offset); } -static long rom_max_timeout = 100; -static long rom_lock_timeout = 10000; - -static int rom_lock(struct netxen_adapter *adapter) -{ - int iter; - u32 done = 0; - int timeout = 0; - - while (!done) { - /* acquire semaphore2 from PCI HW block */ - done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK)); - if (done == 1) - break; - if (timeout >= rom_lock_timeout) - return -EIO; - - timeout++; - /* - * Yield CPU - */ - if (!in_atomic()) - schedule(); - else { - for (iter = 0; iter < 20; iter++) - cpu_relax(); /*This a nop instr on i386 */ - } - } - NXWR32(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER); - return 0; -} +#define NETXEN_MAX_ROM_WAIT_USEC 100 static int netxen_wait_rom_done(struct netxen_adapter *adapter) { @@ -426,22 +357,16 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter) while (done == 0) { done = NXRD32(adapter, NETXEN_ROMUSB_GLB_STATUS); done &= 2; - timeout++; - if (timeout >= rom_max_timeout) { - printk("Timeout reached waiting for rom done"); + if (++timeout >= NETXEN_MAX_ROM_WAIT_USEC) { + dev_err(&adapter->pdev->dev, + "Timeout reached waiting for rom done"); return -EIO; } + udelay(1); } return 0; } -static void netxen_rom_unlock(struct netxen_adapter *adapter) -{ - /* release semaphore2 */ - NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK)); - -} - static int do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { @@ -486,7 +411,7 @@ netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr, { int ret; - ret = rom_lock(adapter); + ret = netxen_rom_lock(adapter); if (ret < 0) return ret; @@ -500,7 +425,7 @@ int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { int ret; - if (rom_lock(adapter) != 0) + if (netxen_rom_lock(adapter) != 0) return -EIO; ret = do_rom_fast_read(adapter, addr, valp); @@ -521,7 +446,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) u32 off; /* resetall */ - rom_lock(adapter); + netxen_rom_lock(adapter); NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff); netxen_rom_unlock(adapter); @@ -797,21 +722,28 @@ netxen_load_firmware(struct netxen_adapter *adapter) flashaddr += 8; } } else { - u32 data; + u64 data; + u32 hi, lo; - size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4; + size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8; flashaddr = NETXEN_BOOTLD_START; for (i = 0; i < size; i++) { if (netxen_rom_fast_read(adapter, - flashaddr, (int *)&data) != 0) + flashaddr, &lo) != 0) + return -EIO; + if (netxen_rom_fast_read(adapter, + flashaddr + 4, &hi) != 0) return -EIO; + /* hi, lo are already in host endian byteorder */ + data = (((u64)hi << 32) | lo); + if (adapter->pci_mem_write(adapter, - flashaddr, &data, 4)) + flashaddr, &data, 8)) return -EIO; - flashaddr += 4; + flashaddr += 8; } } msleep(1); @@ -880,22 +812,10 @@ netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) return 0; } -void netxen_request_firmware(struct netxen_adapter *adapter) +static int +netxen_p3_has_mn(struct netxen_adapter *adapter) { u32 capability, flashed_ver; - u8 fw_type; - struct pci_dev *pdev = adapter->pdev; - int rc = 0; - - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - fw_type = NX_P2_MN_ROMIMAGE; - goto request_fw; - } else { - fw_type = NX_P3_CT_ROMIMAGE; - goto request_fw; - } - -request_mn: capability = 0; netxen_rom_fast_read(adapter, @@ -903,23 +823,35 @@ request_mn: flashed_ver = NETXEN_DECODE_VERSION(flashed_ver); if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { + capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY); - if (capability & NX_PEG_TUNE_MN_PRESENT) { - fw_type = NX_P3_MN_ROMIMAGE; - goto request_fw; - } + if (capability & NX_PEG_TUNE_MN_PRESENT) + return 1; } + return 0; +} - fw_type = NX_FLASH_ROMIMAGE; - adapter->fw = NULL; - goto done; +void netxen_request_firmware(struct netxen_adapter *adapter) +{ + u8 fw_type; + struct pci_dev *pdev = adapter->pdev; + int rc = 0; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + fw_type = NX_P2_MN_ROMIMAGE; + goto request_fw; + } + + fw_type = netxen_p3_has_mn(adapter) ? + NX_P3_MN_ROMIMAGE : NX_P3_CT_ROMIMAGE; request_fw: rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev); if (rc != 0) { - if (fw_type == NX_P3_CT_ROMIMAGE) { + if (fw_type == NX_P3_MN_ROMIMAGE) { msleep(1); - goto request_mn; + fw_type = NX_P3_CT_ROMIMAGE; + goto request_fw; } fw_type = NX_FLASH_ROMIMAGE; @@ -931,9 +863,10 @@ request_fw: if (rc != 0) { release_firmware(adapter->fw); - if (fw_type == NX_P3_CT_ROMIMAGE) { + if (fw_type == NX_P3_MN_ROMIMAGE) { msleep(1); - goto request_mn; + fw_type = NX_P3_CT_ROMIMAGE; + goto request_fw; } fw_type = NX_FLASH_ROMIMAGE; @@ -951,21 +884,23 @@ netxen_release_firmware(struct netxen_adapter *adapter) { if (adapter->fw) release_firmware(adapter->fw); + adapter->fw = NULL; } -int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) +int netxen_init_dummy_dma(struct netxen_adapter *adapter) { - uint64_t addr; - uint32_t hi; - uint32_t lo; + u64 addr; + u32 hi, lo; + + if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return 0; - adapter->dummy_dma.addr = - pci_alloc_consistent(adapter->pdev, + adapter->dummy_dma.addr = pci_alloc_consistent(adapter->pdev, NETXEN_HOST_DUMMY_DMA_SIZE, &adapter->dummy_dma.phys_addr); if (adapter->dummy_dma.addr == NULL) { - printk("%s: ERROR: Could not allocate dummy DMA memory\n", - __func__); + dev_err(&adapter->pdev->dev, + "ERROR: Could not allocate dummy DMA memory\n"); return -ENOMEM; } @@ -976,29 +911,41 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi); NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo); - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - uint32_t temp = 0; - NXWR32(adapter, CRB_HOST_DUMMY_BUF, temp); - } - return 0; } -void netxen_free_adapter_offload(struct netxen_adapter *adapter) +/* + * NetXen DMA watchdog control: + * + * Bit 0 : enabled => R/O: 1 watchdog active, 0 inactive + * Bit 1 : disable_request => 1 req disable dma watchdog + * Bit 2 : enable_request => 1 req enable dma watchdog + * Bit 3-31 : unused + */ +void netxen_free_dummy_dma(struct netxen_adapter *adapter) { int i = 100; + u32 ctrl; + + if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return; if (!adapter->dummy_dma.addr) return; - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - do { - if (dma_watchdog_shutdown_request(adapter) == 1) - break; + ctrl = NXRD32(adapter, NETXEN_DMA_WATCHDOG_CTRL); + if ((ctrl & 0x1) != 0) { + NXWR32(adapter, NETXEN_DMA_WATCHDOG_CTRL, (ctrl | 0x2)); + + while ((ctrl & 0x1) != 0) { + msleep(50); - if (dma_watchdog_shutdown_poll_result(adapter) == 1) + + ctrl = NXRD32(adapter, NETXEN_DMA_WATCHDOG_CTRL); + + if (--i == 0) break; - } while (--i); + }; } if (i) { @@ -1007,10 +954,8 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter) adapter->dummy_dma.addr, adapter->dummy_dma.phys_addr); adapter->dummy_dma.addr = NULL; - } else { - printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n", - adapter->netdev->name); - } + } else + dev_err(&adapter->pdev->dev, "dma_watchdog_shutdown failed\n"); } int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) @@ -1083,10 +1028,6 @@ int netxen_init_firmware(struct netxen_adapter *adapter) NXWR32(adapter, CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE); NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); - if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) { - adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1); - } - return err; } @@ -1222,20 +1163,31 @@ no_skb: static struct netxen_rx_buffer * netxen_process_rcv(struct netxen_adapter *adapter, - int ring, int index, int length, int cksum, int pkt_offset, - struct nx_host_sds_ring *sds_ring) + struct nx_host_sds_ring *sds_ring, + int ring, u64 sts_data0) { struct net_device *netdev = adapter->netdev; struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; struct netxen_rx_buffer *buffer; struct sk_buff *skb; - struct nx_host_rds_ring *rds_ring = &recv_ctx->rds_rings[ring]; + struct nx_host_rds_ring *rds_ring; + int index, length, cksum, pkt_offset; - if (unlikely(index > rds_ring->num_desc)) + if (unlikely(ring >= adapter->max_rds_rings)) + return NULL; + + rds_ring = &recv_ctx->rds_rings[ring]; + + index = netxen_get_sts_refhandle(sts_data0); + if (unlikely(index >= rds_ring->num_desc)) return NULL; buffer = &rds_ring->rx_buf_arr[index]; + length = netxen_get_sts_totallength(sts_data0); + cksum = netxen_get_sts_status(sts_data0); + pkt_offset = netxen_get_sts_pkt_offset(sts_data0); + skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum); if (!skb) return buffer; @@ -1249,11 +1201,88 @@ netxen_process_rcv(struct netxen_adapter *adapter, if (pkt_offset) skb_pull(skb, pkt_offset); + skb->truesize = skb->len + sizeof(struct sk_buff); skb->protocol = eth_type_trans(skb, netdev); napi_gro_receive(&sds_ring->napi, skb); - adapter->stats.no_rcv++; + adapter->stats.rx_pkts++; + adapter->stats.rxbytes += length; + + return buffer; +} + +#define TCP_HDR_SIZE 20 +#define TCP_TS_OPTION_SIZE 12 +#define TCP_TS_HDR_SIZE (TCP_HDR_SIZE + TCP_TS_OPTION_SIZE) + +static struct netxen_rx_buffer * +netxen_process_lro(struct netxen_adapter *adapter, + struct nx_host_sds_ring *sds_ring, + int ring, u64 sts_data0, u64 sts_data1) +{ + struct net_device *netdev = adapter->netdev; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + struct netxen_rx_buffer *buffer; + struct sk_buff *skb; + struct nx_host_rds_ring *rds_ring; + struct iphdr *iph; + struct tcphdr *th; + bool push, timestamp; + int l2_hdr_offset, l4_hdr_offset; + int index; + u16 lro_length, length, data_offset; + u32 seq_number; + + if (unlikely(ring > adapter->max_rds_rings)) + return NULL; + + rds_ring = &recv_ctx->rds_rings[ring]; + + index = netxen_get_lro_sts_refhandle(sts_data0); + if (unlikely(index > rds_ring->num_desc)) + return NULL; + + buffer = &rds_ring->rx_buf_arr[index]; + + timestamp = netxen_get_lro_sts_timestamp(sts_data0); + lro_length = netxen_get_lro_sts_length(sts_data0); + l2_hdr_offset = netxen_get_lro_sts_l2_hdr_offset(sts_data0); + l4_hdr_offset = netxen_get_lro_sts_l4_hdr_offset(sts_data0); + push = netxen_get_lro_sts_push_flag(sts_data0); + seq_number = netxen_get_lro_sts_seq_number(sts_data1); + + skb = netxen_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK); + if (!skb) + return buffer; + + if (timestamp) + data_offset = l4_hdr_offset + TCP_TS_HDR_SIZE; + else + data_offset = l4_hdr_offset + TCP_HDR_SIZE; + + skb_put(skb, lro_length + data_offset); + + skb->truesize = skb->len + sizeof(struct sk_buff) + skb_headroom(skb); + + skb_pull(skb, l2_hdr_offset); + skb->protocol = eth_type_trans(skb, netdev); + + iph = (struct iphdr *)skb->data; + th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); + + length = (iph->ihl << 2) + (th->doff << 2) + lro_length; + iph->tot_len = htons(length); + iph->check = 0; + iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); + th->psh = push; + th->seq = htonl(seq_number); + + length = skb->len; + + netif_receive_skb(skb); + + adapter->stats.lro_pkts++; adapter->stats.rxbytes += length; return buffer; @@ -1275,27 +1304,33 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) u32 consumer = sds_ring->consumer; int count = 0; - u64 sts_data; - int opcode, ring, index, length, cksum, pkt_offset, desc_cnt; + u64 sts_data0, sts_data1; + int opcode, ring = 0, desc_cnt; while (count < max) { desc = &sds_ring->desc_head[consumer]; - sts_data = le64_to_cpu(desc->status_desc_data[0]); + sts_data0 = le64_to_cpu(desc->status_desc_data[0]); - if (!(sts_data & STATUS_OWNER_HOST)) + if (!(sts_data0 & STATUS_OWNER_HOST)) break; - desc_cnt = netxen_get_sts_desc_cnt(sts_data); - ring = netxen_get_sts_type(sts_data); - - if (ring > RCV_RING_JUMBO) - goto skip; + desc_cnt = netxen_get_sts_desc_cnt(sts_data0); - opcode = netxen_get_sts_opcode(sts_data); + opcode = netxen_get_sts_opcode(sts_data0); switch (opcode) { case NETXEN_NIC_RXPKT_DESC: case NETXEN_OLD_RXPKT_DESC: + case NETXEN_NIC_SYN_OFFLOAD: + ring = netxen_get_sts_type(sts_data0); + rxbuf = netxen_process_rcv(adapter, sds_ring, + ring, sts_data0); + break; + case NETXEN_NIC_LRO_DESC: + ring = netxen_get_lro_sts_type(sts_data0); + sts_data1 = le64_to_cpu(desc->status_desc_data[1]); + rxbuf = netxen_process_lro(adapter, sds_ring, + ring, sts_data0, sts_data1); break; case NETXEN_NIC_RESPONSE_DESC: netxen_handle_fw_message(desc_cnt, consumer, sds_ring); @@ -1305,14 +1340,6 @@ netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) WARN_ON(desc_cnt > 1); - index = netxen_get_sts_refhandle(sts_data); - length = netxen_get_sts_totallength(sts_data); - cksum = netxen_get_sts_status(sts_data); - pkt_offset = netxen_get_sts_pkt_offset(sts_data); - - rxbuf = netxen_process_rcv(adapter, ring, index, - length, cksum, pkt_offset, sds_ring); - if (rxbuf) list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); @@ -1347,7 +1374,7 @@ skip: if (count) { sds_ring->consumer = consumer; - NXWR32(adapter, sds_ring->crb_sts_consumer, consumer); + NXWRIO(adapter, sds_ring->crb_sts_consumer, consumer); } return count; @@ -1402,8 +1429,10 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { __netif_tx_lock(tx_ring->txq, smp_processor_id()); - if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) + if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) { netif_wake_queue(netdev); + adapter->tx_timeo_cnt = 0; + } __netif_tx_unlock(tx_ring->txq); } } @@ -1465,10 +1494,10 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, if (count) { rds_ring->producer = producer; - NXWR32(adapter, rds_ring->crb_rcv_producer, + NXWRIO(adapter, rds_ring->crb_rcv_producer, (producer-1) & (rds_ring->num_desc-1)); - if (adapter->fw_major < 4) { + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { /* * Write a doorbell msg to tell phanmon of change in * receive ring producer @@ -1481,9 +1510,10 @@ netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, (rds_ring->num_desc - 1))); netxen_set_msg_ctxid(msg, adapter->portnum); netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid)); - writel(msg, - DB_NORMALIZE(adapter, + read_lock(&adapter->adapter_lock); + writel(msg, DB_NORMALIZE(adapter, NETXEN_RCV_PRODUCER_OFFSET)); + read_unlock(&adapter->adapter_lock); } } } @@ -1525,7 +1555,7 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, if (count) { rds_ring->producer = producer; - NXWR32(adapter, rds_ring->crb_rcv_producer, + NXWRIO(adapter, rds_ring->crb_rcv_producer, (producer - 1) & (rds_ring->num_desc - 1)); } spin_unlock(&rds_ring->lock); diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 28f270f5ac7..f7bdde111df 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2003 - 2009 NetXen, Inc. + * Copyright (C) 2009 - QLogic Corporation. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -20,12 +21,6 @@ * The full GNU General Public License is included in this distribution * in the file called LICENSE. * - * Contact Information: - * info@netxen.com - * NetXen Inc, - * 18922 Forge Drive - * Cupertino, CA 95014-0701 - * */ #include <linux/vmalloc.h> @@ -33,12 +28,12 @@ #include "netxen_nic_hw.h" #include "netxen_nic.h" -#include "netxen_nic_phan_reg.h" #include <linux/dma-mapping.h> #include <linux/if_vlan.h> #include <net/ip.h> #include <linux/ipv6.h> +#include <linux/inetdevice.h> MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); MODULE_LICENSE("GPL"); @@ -63,18 +58,31 @@ static int __devinit netxen_nic_probe(struct pci_dev *pdev, static void __devexit netxen_nic_remove(struct pci_dev *pdev); static int netxen_nic_open(struct net_device *netdev); static int netxen_nic_close(struct net_device *netdev); -static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *); +static netdev_tx_t netxen_nic_xmit_frame(struct sk_buff *, + struct net_device *); static void netxen_tx_timeout(struct net_device *netdev); static void netxen_tx_timeout_task(struct work_struct *work); -static void netxen_watchdog(unsigned long); +static void netxen_fw_poll_work(struct work_struct *work); +static void netxen_schedule_work(struct netxen_adapter *adapter, + work_func_t func, int delay); +static void netxen_cancel_fw_work(struct netxen_adapter *adapter); static int netxen_nic_poll(struct napi_struct *napi, int budget); #ifdef CONFIG_NET_POLL_CONTROLLER static void netxen_nic_poll_controller(struct net_device *netdev); #endif + +static void netxen_create_sysfs_entries(struct netxen_adapter *adapter); +static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter); + +static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter); +static int netxen_can_start_firmware(struct netxen_adapter *adapter); + static irqreturn_t netxen_intr(int irq, void *data); static irqreturn_t netxen_msi_intr(int irq, void *data); static irqreturn_t netxen_msix_intr(int irq, void *data); +static void netxen_config_indev_addr(struct net_device *dev, unsigned long); + /* PCI Device ID Table */ #define ENTRY(device) \ {PCI_DEVICE(PCI_VENDOR_ID_NETXEN, (device)), \ @@ -94,8 +102,6 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, netxen_pci_tbl); -static void netxen_watchdog(unsigned long); - static uint32_t crb_cmd_producer[4] = { CRB_CMD_PRODUCER_OFFSET, CRB_CMD_PRODUCER_OFFSET_1, CRB_CMD_PRODUCER_OFFSET_2, CRB_CMD_PRODUCER_OFFSET_3 @@ -105,7 +111,7 @@ void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, struct nx_host_tx_ring *tx_ring) { - NXWR32(adapter, tx_ring->crb_cmd_producer, tx_ring->producer); + NXWRIO(adapter, tx_ring->crb_cmd_producer, tx_ring->producer); if (netxen_tx_avail(tx_ring) <= TX_STOP_THRESH) { netif_stop_queue(adapter->netdev); @@ -122,7 +128,7 @@ static inline void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter, struct nx_host_tx_ring *tx_ring) { - NXWR32(adapter, tx_ring->crb_cmd_consumer, tx_ring->sw_consumer); + NXWRIO(adapter, tx_ring->crb_cmd_consumer, tx_ring->sw_consumer); } static uint32_t msi_tgt_status[8] = { @@ -138,18 +144,17 @@ static inline void netxen_nic_disable_int(struct nx_host_sds_ring *sds_ring) { struct netxen_adapter *adapter = sds_ring->adapter; - NXWR32(adapter, sds_ring->crb_intr_mask, 0); + NXWRIO(adapter, sds_ring->crb_intr_mask, 0); } static inline void netxen_nic_enable_int(struct nx_host_sds_ring *sds_ring) { struct netxen_adapter *adapter = sds_ring->adapter; - NXWR32(adapter, sds_ring->crb_intr_mask, 0x1); + NXWRIO(adapter, sds_ring->crb_intr_mask, 0x1); if (!NETXEN_IS_MSI_FAMILY(adapter)) - adapter->pci_write_immediate(adapter, - adapter->legacy_intr.tgt_mask_reg, 0xfbff); + NXWRIO(adapter, adapter->tgt_mask_reg, 0xfbff); } static int @@ -179,7 +184,7 @@ netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev) struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; if (netxen_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) - return 1; + return -ENOMEM; for (ring = 0; ring < adapter->max_sds_rings; ring++) { sds_ring = &recv_ctx->sds_rings[ring]; @@ -308,36 +313,6 @@ err_out: return err; } -static void netxen_check_options(struct netxen_adapter *adapter) -{ - if (adapter->ahw.port_type == NETXEN_NIC_XGBE) - adapter->num_rxd = MAX_RCV_DESCRIPTORS_10G; - else if (adapter->ahw.port_type == NETXEN_NIC_GBE) - adapter->num_rxd = MAX_RCV_DESCRIPTORS_1G; - - adapter->msix_supported = 0; - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { - adapter->msix_supported = !!use_msi_x; - adapter->rss_supported = !!use_msi_x; - } else if (adapter->fw_version >= NETXEN_VERSION_CODE(3, 4, 336)) { - switch (adapter->ahw.board_type) { - case NETXEN_BRDTYPE_P2_SB31_10G: - case NETXEN_BRDTYPE_P2_SB31_10G_CX4: - adapter->msix_supported = !!use_msi_x; - adapter->rss_supported = !!use_msi_x; - break; - default: - break; - } - } - - adapter->num_txd = MAX_CMD_DESCRIPTORS_HOST; - adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS; - adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS; - - return; -} - static int netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot) { @@ -537,10 +512,22 @@ netxen_setup_intr(struct netxen_adapter *adapter) legacy_intrp = &legacy_intr[adapter->ahw.pci_func]; else legacy_intrp = &legacy_intr[0]; - adapter->legacy_intr.int_vec_bit = legacy_intrp->int_vec_bit; - adapter->legacy_intr.tgt_status_reg = legacy_intrp->tgt_status_reg; - adapter->legacy_intr.tgt_mask_reg = legacy_intrp->tgt_mask_reg; - adapter->legacy_intr.pci_int_reg = legacy_intrp->pci_int_reg; + + adapter->int_vec_bit = legacy_intrp->int_vec_bit; + adapter->tgt_status_reg = netxen_get_ioaddr(adapter, + legacy_intrp->tgt_status_reg); + adapter->tgt_mask_reg = netxen_get_ioaddr(adapter, + legacy_intrp->tgt_mask_reg); + adapter->pci_int_reg = netxen_get_ioaddr(adapter, + legacy_intrp->pci_int_reg); + adapter->isr_int_vec = netxen_get_ioaddr(adapter, ISR_INT_VECTOR); + + if (adapter->ahw.revision_id >= NX_P3_B1) + adapter->crb_int_state_reg = netxen_get_ioaddr(adapter, + ISR_INT_STATE_REG); + else + adapter->crb_int_state_reg = netxen_get_ioaddr(adapter, + CRB_INT_VECTOR); netxen_set_msix_bit(pdev, 0); @@ -567,8 +554,8 @@ netxen_setup_intr(struct netxen_adapter *adapter) if (use_msi && !pci_enable_msi(pdev)) { adapter->flags |= NETXEN_NIC_MSI_ENABLED; - adapter->msi_tgt_status = - msi_tgt_status[adapter->ahw.pci_func]; + adapter->tgt_status_reg = netxen_get_ioaddr(adapter, + msi_tgt_status[adapter->ahw.pci_func]); dev_info(&pdev->dev, "using msi interrupts\n"); adapter->msix_entries[0].vector = pdev->irq; return; @@ -628,14 +615,6 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) mem_len = pci_resource_len(pdev, 0); pci_len0 = 0; - adapter->hw_write_wx = netxen_nic_hw_write_wx_128M; - adapter->hw_read_wx = netxen_nic_hw_read_wx_128M; - adapter->pci_read_immediate = netxen_nic_pci_read_immediate_128M; - adapter->pci_write_immediate = netxen_nic_pci_write_immediate_128M; - adapter->pci_set_window = netxen_nic_pci_set_window_128M; - adapter->pci_mem_read = netxen_nic_pci_mem_read_128M; - adapter->pci_mem_write = netxen_nic_pci_mem_write_128M; - /* 128 Meg of memory */ if (mem_len == NETXEN_PCI_128MB_SIZE) { mem_ptr0 = ioremap(mem_base, FIRST_PAGE_GROUP_SIZE); @@ -648,14 +627,6 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) mem_ptr2 = ioremap(mem_base + THIRD_PAGE_GROUP_START - SECOND_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE); } else if (mem_len == NETXEN_PCI_2MB_SIZE) { - adapter->hw_write_wx = netxen_nic_hw_write_wx_2M; - adapter->hw_read_wx = netxen_nic_hw_read_wx_2M; - adapter->pci_read_immediate = netxen_nic_pci_read_immediate_2M; - adapter->pci_write_immediate = - netxen_nic_pci_write_immediate_2M; - adapter->pci_set_window = netxen_nic_pci_set_window_2M; - adapter->pci_mem_read = netxen_nic_pci_mem_read_2M; - adapter->pci_mem_write = netxen_nic_pci_mem_write_2M; mem_ptr0 = pci_ioremap_bar(pdev, 0); if (mem_ptr0 == NULL) { @@ -667,9 +638,10 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) adapter->ahw.ddr_mn_window = 0; adapter->ahw.qdr_sn_window = 0; - adapter->ahw.mn_win_crb = 0x100000 + PCIX_MN_WINDOW + - (pci_func * 0x20); - adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW; + adapter->ahw.mn_win_crb = NETXEN_PCI_CRBSPACE + + 0x100000 + PCIX_MN_WINDOW + (pci_func * 0x20); + adapter->ahw.ms_win_crb = NETXEN_PCI_CRBSPACE + + 0x100000 + PCIX_SN_WINDOW; if (pci_func < 4) adapter->ahw.ms_win_crb += (pci_func * 0x20); else @@ -679,6 +651,8 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) return -EIO; } + netxen_setup_hwops(adapter); + dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20)); adapter->ahw.pci_base0 = mem_ptr0; @@ -717,20 +691,111 @@ err_out: return err; } +static void +netxen_check_options(struct netxen_adapter *adapter) +{ + u32 fw_major, fw_minor, fw_build; + char brd_name[NETXEN_MAX_SHORT_NAME]; + char serial_num[32]; + int i, offset, val; + int *ptr32; + struct pci_dev *pdev = adapter->pdev; + + adapter->driver_mismatch = 0; + + ptr32 = (int *)&serial_num; + offset = NX_FW_SERIAL_NUM_OFFSET; + for (i = 0; i < 8; i++) { + if (netxen_rom_fast_read(adapter, offset, &val) == -1) { + dev_err(&pdev->dev, "error reading board info\n"); + adapter->driver_mismatch = 1; + return; + } + ptr32[i] = cpu_to_le32(val); + offset += sizeof(u32); + } + + fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); + fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); + fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); + + adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build); + + if (adapter->portnum == 0) { + get_brd_name_by_type(adapter->ahw.board_type, brd_name); + + printk(KERN_INFO "NetXen %s Board S/N %s Chip rev 0x%x\n", + brd_name, serial_num, adapter->ahw.revision_id); + } + + if (adapter->fw_version < NETXEN_VERSION_CODE(3, 4, 216)) { + adapter->driver_mismatch = 1; + dev_warn(&pdev->dev, "firmware version %d.%d.%d unsupported\n", + fw_major, fw_minor, fw_build); + return; + } + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + i = NXRD32(adapter, NETXEN_SRE_MISC); + adapter->ahw.cut_through = (i & 0x8000) ? 1 : 0; + } + + dev_info(&pdev->dev, "firmware v%d.%d.%d [%s]\n", + fw_major, fw_minor, fw_build, + adapter->ahw.cut_through ? "cut-through" : "legacy"); + + if (adapter->fw_version >= NETXEN_VERSION_CODE(4, 0, 222)) + adapter->capabilities = NXRD32(adapter, CRB_FW_CAPABILITIES_1); + + adapter->flags &= ~NETXEN_NIC_LRO_ENABLED; + + if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { + adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G; + adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G; + } else if (adapter->ahw.port_type == NETXEN_NIC_GBE) { + adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G; + adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G; + } + + adapter->msix_supported = 0; + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + adapter->msix_supported = !!use_msi_x; + adapter->rss_supported = !!use_msi_x; + } else if (adapter->fw_version >= NETXEN_VERSION_CODE(3, 4, 336)) { + switch (adapter->ahw.board_type) { + case NETXEN_BRDTYPE_P2_SB31_10G: + case NETXEN_BRDTYPE_P2_SB31_10G_CX4: + adapter->msix_supported = !!use_msi_x; + adapter->rss_supported = !!use_msi_x; + break; + default: + break; + } + } + + adapter->num_txd = MAX_CMD_DESCRIPTORS; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS; + adapter->max_rds_rings = 3; + } else { + adapter->num_lro_rxd = 0; + adapter->max_rds_rings = 2; + } +} + static int -netxen_start_firmware(struct netxen_adapter *adapter, int request_fw) +netxen_start_firmware(struct netxen_adapter *adapter) { int val, err, first_boot; struct pci_dev *pdev = adapter->pdev; - int first_driver = 0; - - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) - first_driver = (adapter->portnum == 0); - else - first_driver = (adapter->ahw.pci_func == 0); + /* required for NX2031 dummy dma */ + err = nx_set_dma_mask(adapter); + if (err) + return err; - if (!first_driver) + if (!netxen_can_start_firmware(adapter)) goto wait_init; first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc)); @@ -741,12 +806,13 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw) return err; } - if (request_fw) - netxen_request_firmware(adapter); + netxen_request_firmware(adapter); err = netxen_need_fw_reset(adapter); - if (err <= 0) - return err; + if (err < 0) + goto err_out; + if (err == 0) + goto ready; if (first_boot != 0x55555555) { NXWR32(adapter, CRB_CMDPEG_STATE, 0); @@ -755,10 +821,17 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw) } NXWR32(adapter, CRB_DMA_SHIFT, 0x55555555); + NXWR32(adapter, NETXEN_PEG_HALT_STATUS1, 0); + NXWR32(adapter, NETXEN_PEG_HALT_STATUS2, 0); + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) netxen_set_port_mode(adapter); - netxen_load_firmware(adapter); + err = netxen_load_firmware(adapter); + if (err) + goto err_out; + + netxen_release_firmware(adapter); if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { @@ -770,9 +843,9 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw) } - err = netxen_initialize_adapter_offload(adapter); + err = netxen_init_dummy_dma(adapter); if (err) - return err; + goto err_out; /* * Tell the hardware our version number. @@ -782,15 +855,28 @@ netxen_start_firmware(struct netxen_adapter *adapter, int request_fw) | (_NETXEN_NIC_LINUX_SUBVERSION); NXWR32(adapter, CRB_DRIVER_VERSION, val); +ready: + NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_READY); + wait_init: /* Handshake with the card before we register the devices. */ err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); if (err) { - netxen_free_adapter_offload(adapter); - return err; + netxen_free_dummy_dma(adapter); + goto err_out; } - return 0; + nx_update_dma_mask(adapter); + + netxen_check_options(adapter); + + adapter->need_fw_reset = 0; + + /* fall through and release firmware */ + +err_out: + netxen_release_firmware(adapter); + return err; } static int @@ -840,11 +926,28 @@ netxen_nic_free_irq(struct netxen_adapter *adapter) } } +static void +netxen_nic_init_coalesce_defaults(struct netxen_adapter *adapter) +{ + adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT; + adapter->coal.normal.data.rx_time_us = + NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US; + adapter->coal.normal.data.rx_packets = + NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS; + adapter->coal.normal.data.tx_time_us = + NETXEN_DEFAULT_INTR_COALESCE_TX_TIME_US; + adapter->coal.normal.data.tx_packets = + NETXEN_DEFAULT_INTR_COALESCE_TX_PACKETS; +} + static int netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) { int err; + if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) + return -EIO; + err = adapter->init_port(adapter, adapter->physical_port); if (err) { printk(KERN_ERR "%s: Failed to initialize port %d\n", @@ -862,6 +965,12 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) if (adapter->max_sds_rings > 1) netxen_config_rss(adapter, 1); + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + netxen_config_intr_coalesce(adapter); + + if (adapter->capabilities & NX_FW_CAPABILITY_HW_LRO) + netxen_config_hw_lro(adapter, NETXEN_NIC_LRO_ENABLED); + netxen_napi_enable(adapter); if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION) @@ -869,14 +978,18 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) else netxen_nic_set_link_parameters(adapter); - mod_timer(&adapter->watchdog_timer, jiffies); - + set_bit(__NX_DEV_UP, &adapter->state); return 0; } static void netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) { + if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) + return; + + clear_bit(__NX_DEV_UP, &adapter->state); + spin_lock(&adapter->tx_clean_lock); netif_carrier_off(netdev); netif_tx_disable(netdev); @@ -887,12 +1000,12 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) netxen_p3_free_mac_list(adapter); + adapter->set_promisc(adapter, NETXEN_NIU_NON_PROMISC_MODE); + netxen_napi_disable(adapter); netxen_release_tx_buffers(adapter); spin_unlock(&adapter->tx_clean_lock); - - del_timer_sync(&adapter->watchdog_timer); } @@ -905,6 +1018,9 @@ netxen_nic_attach(struct netxen_adapter *adapter) struct nx_host_rds_ring *rds_ring; struct nx_host_tx_ring *tx_ring; + if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) + return 0; + err = netxen_init_firmware(adapter); if (err) return err; @@ -913,11 +1029,6 @@ netxen_nic_attach(struct netxen_adapter *adapter) if (err) return err; - if (adapter->fw_major < 4) - adapter->max_rds_rings = 3; - else - adapter->max_rds_rings = 2; - err = netxen_alloc_sw_resources(adapter); if (err) { printk(KERN_ERR "%s: Error in setting sw resources\n", @@ -925,8 +1036,6 @@ netxen_nic_attach(struct netxen_adapter *adapter) return err; } - netxen_nic_clear_stats(adapter); - err = netxen_alloc_hw_resources(adapter); if (err) { printk(KERN_ERR "%s: Error in setting hw resources\n", @@ -934,10 +1043,12 @@ netxen_nic_attach(struct netxen_adapter *adapter) goto err_out_free_sw; } - if (adapter->fw_major < 4) { + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { tx_ring = adapter->tx_ring; - tx_ring->crb_cmd_producer = crb_cmd_producer[adapter->portnum]; - tx_ring->crb_cmd_consumer = crb_cmd_consumer[adapter->portnum]; + tx_ring->crb_cmd_producer = netxen_get_ioaddr(adapter, + crb_cmd_producer[adapter->portnum]); + tx_ring->crb_cmd_consumer = netxen_get_ioaddr(adapter, + crb_cmd_consumer[adapter->portnum]); tx_ring->producer = 0; tx_ring->sw_consumer = 0; @@ -958,6 +1069,11 @@ netxen_nic_attach(struct netxen_adapter *adapter) goto err_out_free_rxbuf; } + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + netxen_nic_init_coalesce_defaults(adapter); + + netxen_create_sysfs_entries(adapter); + adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; return 0; @@ -972,6 +1088,11 @@ err_out_free_sw: static void netxen_nic_detach(struct netxen_adapter *adapter) { + if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) + return; + + netxen_remove_sysfs_entries(adapter); + netxen_free_hw_resources(adapter); netxen_release_rx_buffers(adapter); netxen_nic_free_irq(adapter); @@ -981,6 +1102,101 @@ netxen_nic_detach(struct netxen_adapter *adapter) adapter->is_up = 0; } +int +netxen_nic_reset_context(struct netxen_adapter *adapter) +{ + int err = 0; + struct net_device *netdev = adapter->netdev; + + if (test_and_set_bit(__NX_RESETTING, &adapter->state)) + return -EBUSY; + + if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { + + netif_device_detach(netdev); + + if (netif_running(netdev)) + netxen_nic_down(adapter, netdev); + + netxen_nic_detach(adapter); + + if (netif_running(netdev)) { + err = netxen_nic_attach(adapter); + if (!err) + err = netxen_nic_up(adapter, netdev); + + if (err) + goto done; + } + + netif_device_attach(netdev); + } + +done: + clear_bit(__NX_RESETTING, &adapter->state); + return err; +} + +static int +netxen_setup_netdev(struct netxen_adapter *adapter, + struct net_device *netdev) +{ + int err = 0; + struct pci_dev *pdev = adapter->pdev; + + adapter->rx_csum = 1; + adapter->mc_enabled = 0; + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + adapter->max_mc_count = 38; + else + adapter->max_mc_count = 16; + + netdev->netdev_ops = &netxen_netdev_ops; + netdev->watchdog_timeo = 2*HZ; + + netxen_nic_change_mtu(netdev, netdev->mtu); + + SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops); + + netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + netdev->features |= (NETIF_F_GRO); + netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); + netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); + } + + if (adapter->pci_using_dac) { + netdev->features |= NETIF_F_HIGHDMA; + netdev->vlan_features |= NETIF_F_HIGHDMA; + } + + if (adapter->capabilities & NX_FW_CAPABILITY_FVLANTX) + netdev->features |= (NETIF_F_HW_VLAN_TX); + + if (adapter->capabilities & NX_FW_CAPABILITY_HW_LRO) + netdev->features |= NETIF_F_LRO; + + netdev->irq = adapter->msix_entries[0].vector; + + INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task); + + if (netxen_read_mac_addr(adapter)) + dev_warn(&pdev->dev, "failed to read mac addr\n"); + + netif_carrier_off(netdev); + netif_stop_queue(netdev); + + err = register_netdev(netdev); + if (err) { + dev_err(&pdev->dev, "failed to register net device\n"); + return err; + } + + return 0; +} + static int __devinit netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -1018,9 +1234,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev = alloc_etherdev(sizeof(struct netxen_adapter)); if(!netdev) { - printk(KERN_ERR"%s: Failed to allocate memory for the " - "device block.Check system memory resource" - " usage.\n", netxen_nic_driver_name); + dev_err(&pdev->dev, "failed to allocate net_device\n"); + err = -ENOMEM; goto err_out_free_res; } @@ -1034,10 +1249,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) revision_id = pdev->revision; adapter->ahw.revision_id = revision_id; - err = nx_set_dma_mask(adapter); - if (err) - goto err_out_free_netdev; - rwlock_init(&adapter->adapter_lock); spin_lock_init(&adapter->tx_clean_lock); INIT_LIST_HEAD(&adapter->mac_list); @@ -1048,43 +1259,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* This will be reset for mezz cards */ adapter->portnum = pci_func_id; - adapter->rx_csum = 1; - adapter->mc_enabled = 0; - if (NX_IS_REVISION_P3(revision_id)) - adapter->max_mc_count = 38; - else - adapter->max_mc_count = 16; - - netdev->netdev_ops = &netxen_netdev_ops; - netdev->watchdog_timeo = 2*HZ; - - netxen_nic_change_mtu(netdev, netdev->mtu); - SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops); - - netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); - netdev->features |= (NETIF_F_GRO); - netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO); - - if (NX_IS_REVISION_P3(revision_id)) { - netdev->features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); - netdev->vlan_features |= (NETIF_F_IPV6_CSUM | NETIF_F_TSO6); - } - - if (adapter->pci_using_dac) { - netdev->features |= NETIF_F_HIGHDMA; - netdev->vlan_features |= NETIF_F_HIGHDMA; - } - - if (netxen_nic_get_board_info(adapter) != 0) { - printk("%s: Error getting board config info.\n", - netxen_nic_driver_name); - err = -EIO; + err = netxen_nic_get_board_info(adapter); + if (err) { + dev_err(&pdev->dev, "Error getting board config info.\n"); goto err_out_iounmap; } - netxen_initialize_adapter_ops(adapter); - /* Mezz cards have PCI function 0,2,3 enabled */ switch (adapter->ahw.board_type) { case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ: @@ -1096,53 +1277,32 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) break; } - err = netxen_start_firmware(adapter, 1); + err = netxen_start_firmware(adapter); if (err) goto err_out_iounmap; - nx_update_dma_mask(adapter); - - netxen_nic_get_firmware_info(adapter); - /* * See if the firmware gave us a virtual-physical port mapping. */ adapter->physical_port = adapter->portnum; - if (adapter->fw_major < 4) { + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { i = NXRD32(adapter, CRB_V2P(adapter->portnum)); if (i != 0x55555555) adapter->physical_port = i; } - netxen_check_options(adapter); + netxen_nic_clear_stats(adapter); netxen_setup_intr(adapter); - netdev->irq = adapter->msix_entries[0].vector; - - init_timer(&adapter->watchdog_timer); - adapter->watchdog_timer.function = &netxen_watchdog; - adapter->watchdog_timer.data = (unsigned long)adapter; - INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task); - INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task); - - err = netxen_read_mac_addr(adapter); + err = netxen_setup_netdev(adapter, netdev); if (err) - dev_warn(&pdev->dev, "failed to read mac addr\n"); - - netif_carrier_off(netdev); - netif_stop_queue(netdev); - - if ((err = register_netdev(netdev))) { - printk(KERN_ERR "%s: register_netdev failed port #%d" - " aborting\n", netxen_nic_driver_name, - adapter->portnum); - err = -EIO; goto err_out_disable_msi; - } pci_set_drvdata(pdev, adapter); + netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY); + switch (adapter->ahw.port_type) { case NETXEN_NIC_GBE: dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n", @@ -1159,7 +1319,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err_out_disable_msi: netxen_teardown_intr(adapter); - netxen_free_adapter_offload(adapter); + netxen_free_dummy_dma(adapter); + + nx_decr_dev_ref_cnt(adapter); err_out_iounmap: netxen_cleanup_pci_map(adapter); @@ -1187,17 +1349,20 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netdev = adapter->netdev; + netxen_cancel_fw_work(adapter); + unregister_netdev(netdev); - cancel_work_sync(&adapter->watchdog_task); cancel_work_sync(&adapter->tx_timeout_task); - if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { - netxen_nic_detach(adapter); - } + netxen_nic_detach(adapter); + + nx_decr_dev_ref_cnt(adapter); if (adapter->portnum == 0) - netxen_free_adapter_offload(adapter); + netxen_free_dummy_dma(adapter); + + clear_bit(__NX_RESETTING, &adapter->state); netxen_teardown_intr(adapter); @@ -1211,27 +1376,33 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) free_netdev(netdev); } - -#ifdef CONFIG_PM -static int -netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) +static int __netxen_nic_shutdown(struct pci_dev *pdev) { - struct netxen_adapter *adapter = pci_get_drvdata(pdev); struct net_device *netdev = adapter->netdev; + int retval; netif_device_detach(netdev); + netxen_cancel_fw_work(adapter); + if (netif_running(netdev)) netxen_nic_down(adapter, netdev); - cancel_work_sync(&adapter->watchdog_task); cancel_work_sync(&adapter->tx_timeout_task); - if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) - netxen_nic_detach(adapter); + netxen_nic_detach(adapter); + + if (adapter->portnum == 0) + netxen_free_dummy_dma(adapter); + + nx_decr_dev_ref_cnt(adapter); - pci_save_state(pdev); + clear_bit(__NX_RESETTING, &adapter->state); + + retval = pci_save_state(pdev); + if (retval) + return retval; if (netxen_nic_wol_supported(adapter)) { pci_enable_wake(pdev, PCI_D3cold, 1); @@ -1239,10 +1410,27 @@ netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) } pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } +static void netxen_nic_shutdown(struct pci_dev *pdev) +{ + if (__netxen_nic_shutdown(pdev)) + return; +} +#ifdef CONFIG_PM +static int +netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) +{ + int retval; + + retval = __netxen_nic_shutdown(pdev); + if (retval) + return retval; + + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; +} static int netxen_nic_resume(struct pci_dev *pdev) @@ -1260,7 +1448,7 @@ netxen_nic_resume(struct pci_dev *pdev) adapter->curr_window = 255; - err = netxen_start_firmware(adapter, 0); + err = netxen_start_firmware(adapter); if (err) { dev_err(&pdev->dev, "failed to start firmware\n"); return err; @@ -1269,16 +1457,24 @@ netxen_nic_resume(struct pci_dev *pdev) if (netif_running(netdev)) { err = netxen_nic_attach(adapter); if (err) - return err; + goto err_out; err = netxen_nic_up(adapter, netdev); if (err) - return err; + goto err_out_detach; netif_device_attach(netdev); + + netxen_config_indev_addr(netdev, NETDEV_UP); } - return 0; + netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY); + +err_out_detach: + netxen_nic_detach(adapter); +err_out: + nx_decr_dev_ref_cnt(adapter); + return err; } #endif @@ -1290,11 +1486,9 @@ static int netxen_nic_open(struct net_device *netdev) if (adapter->driver_mismatch) return -EIO; - if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) { - err = netxen_nic_attach(adapter); - if (err) - return err; - } + err = netxen_nic_attach(adapter); + if (err) + return err; err = netxen_nic_up(adapter, netdev); if (err) @@ -1320,30 +1514,52 @@ static int netxen_nic_close(struct net_device *netdev) return 0; } -static bool netxen_tso_check(struct net_device *netdev, - struct cmd_desc_type0 *desc, struct sk_buff *skb) +static void +netxen_tso_check(struct net_device *netdev, + struct nx_host_tx_ring *tx_ring, + struct cmd_desc_type0 *first_desc, + struct sk_buff *skb) { - bool tso = false; u8 opcode = TX_ETHER_PKT; __be16 protocol = skb->protocol; - u16 flags = 0; + u16 flags = 0, vid = 0; + u32 producer; + int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0; + struct cmd_desc_type0 *hwdesc; + struct vlan_ethhdr *vh; if (protocol == cpu_to_be16(ETH_P_8021Q)) { - struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data; + + vh = (struct vlan_ethhdr *)skb->data; protocol = vh->h_vlan_encapsulated_proto; flags = FLAGS_VLAN_TAGGED; + + } else if (vlan_tx_tag_present(skb)) { + + flags = FLAGS_VLAN_OOB; + vid = vlan_tx_tag_get(skb); + netxen_set_tx_vlan_tci(first_desc, vid); + vlan_oob = 1; } if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) && skb_shinfo(skb)->gso_size > 0) { - desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); - desc->total_hdr_length = - skb_transport_offset(skb) + tcp_hdrlen(skb); + hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); + + first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size); + first_desc->total_hdr_length = hdr_len; + if (vlan_oob) { + first_desc->total_hdr_length += VLAN_HLEN; + first_desc->tcp_hdr_offset = VLAN_HLEN; + first_desc->ip_hdr_offset = VLAN_HLEN; + /* Only in case of TSO on vlan device */ + flags |= FLAGS_VLAN_TAGGED; + } opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ? TX_TCP_LSO6 : TX_TCP_LSO; - tso = true; + tso = 1; } else if (skb->ip_summed == CHECKSUM_PARTIAL) { u8 l4proto; @@ -1364,55 +1580,133 @@ static bool netxen_tso_check(struct net_device *netdev, opcode = TX_UDPV6_PKT; } } - desc->tcp_hdr_offset = skb_transport_offset(skb); - desc->ip_hdr_offset = skb_network_offset(skb); - netxen_set_tx_flags_opcode(desc, flags, opcode); - return tso; + + first_desc->tcp_hdr_offset += skb_transport_offset(skb); + first_desc->ip_hdr_offset += skb_network_offset(skb); + netxen_set_tx_flags_opcode(first_desc, flags, opcode); + + if (!tso) + return; + + /* For LSO, we need to copy the MAC/IP/TCP headers into + * the descriptor ring + */ + producer = tx_ring->producer; + copied = 0; + offset = 2; + + if (vlan_oob) { + /* Create a TSO vlan header template for firmware */ + + hwdesc = &tx_ring->desc_head[producer]; + tx_ring->cmd_buf_arr[producer].skb = NULL; + + copy_len = min((int)sizeof(struct cmd_desc_type0) - offset, + hdr_len + VLAN_HLEN); + + vh = (struct vlan_ethhdr *)((char *)hwdesc + 2); + skb_copy_from_linear_data(skb, vh, 12); + vh->h_vlan_proto = htons(ETH_P_8021Q); + vh->h_vlan_TCI = htons(vid); + skb_copy_from_linear_data_offset(skb, 12, + (char *)vh + 16, copy_len - 16); + + copied = copy_len - VLAN_HLEN; + offset = 0; + + producer = get_next_index(producer, tx_ring->num_desc); + } + + while (copied < hdr_len) { + + copy_len = min((int)sizeof(struct cmd_desc_type0) - offset, + (hdr_len - copied)); + + hwdesc = &tx_ring->desc_head[producer]; + tx_ring->cmd_buf_arr[producer].skb = NULL; + + skb_copy_from_linear_data_offset(skb, copied, + (char *)hwdesc + offset, copy_len); + + copied += copy_len; + offset = 0; + + producer = get_next_index(producer, tx_ring->num_desc); + } + + tx_ring->producer = producer; + barrier(); } -static void -netxen_clean_tx_dma_mapping(struct pci_dev *pdev, - struct netxen_cmd_buffer *pbuf, int last) +static int +netxen_map_tx_skb(struct pci_dev *pdev, + struct sk_buff *skb, struct netxen_cmd_buffer *pbuf) { - int k; - struct netxen_skb_frag *buffrag; + struct netxen_skb_frag *nf; + struct skb_frag_struct *frag; + int i, nr_frags; + dma_addr_t map; + + nr_frags = skb_shinfo(skb)->nr_frags; + nf = &pbuf->frag_array[0]; - buffrag = &pbuf->frag_array[0]; - pci_unmap_single(pdev, buffrag->dma, - buffrag->length, PCI_DMA_TODEVICE); + map = pci_map_single(pdev, skb->data, + skb_headlen(skb), PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, map)) + goto out_err; - for (k = 1; k < last; k++) { - buffrag = &pbuf->frag_array[k]; - pci_unmap_page(pdev, buffrag->dma, - buffrag->length, PCI_DMA_TODEVICE); + nf->dma = map; + nf->length = skb_headlen(skb); + + for (i = 0; i < nr_frags; i++) { + frag = &skb_shinfo(skb)->frags[i]; + nf = &pbuf->frag_array[i+1]; + + map = pci_map_page(pdev, frag->page, frag->page_offset, + frag->size, PCI_DMA_TODEVICE); + if (pci_dma_mapping_error(pdev, map)) + goto unwind; + + nf->dma = map; + nf->length = frag->size; } + + return 0; + +unwind: + while (--i >= 0) { + nf = &pbuf->frag_array[i+1]; + pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); + } + + nf = &pbuf->frag_array[0]; + pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); + +out_err: + return -ENOMEM; } static inline void netxen_clear_cmddesc(u64 *desc) { - int i; - for (i = 0; i < 8; i++) - desc[i] = 0ULL; + desc[0] = 0ULL; + desc[2] = 0ULL; } -static int +static netdev_tx_t netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); struct nx_host_tx_ring *tx_ring = adapter->tx_ring; - unsigned int first_seg_len = skb->len - skb->data_len; struct netxen_cmd_buffer *pbuf; struct netxen_skb_frag *buffrag; - struct cmd_desc_type0 *hwdesc; - struct pci_dev *pdev = adapter->pdev; - dma_addr_t temp_dma; + struct cmd_desc_type0 *hwdesc, *first_desc; + struct pci_dev *pdev; int i, k; u32 producer; int frag_count, no_of_desc; u32 num_txd = tx_ring->num_desc; - bool is_tso = false; frag_count = skb_shinfo(skb)->nr_frags + 1; @@ -1425,121 +1719,60 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } producer = tx_ring->producer; - - hwdesc = &tx_ring->desc_head[producer]; - netxen_clear_cmddesc((u64 *)hwdesc); pbuf = &tx_ring->cmd_buf_arr[producer]; - is_tso = netxen_tso_check(netdev, hwdesc, skb); + pdev = adapter->pdev; + + if (netxen_map_tx_skb(pdev, skb, pbuf)) + goto drop_packet; pbuf->skb = skb; pbuf->frag_count = frag_count; - buffrag = &pbuf->frag_array[0]; - temp_dma = pci_map_single(pdev, skb->data, first_seg_len, - PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(pdev, temp_dma)) - goto drop_packet; - buffrag->dma = temp_dma; - buffrag->length = first_seg_len; - netxen_set_tx_frags_len(hwdesc, frag_count, skb->len); - netxen_set_tx_port(hwdesc, adapter->portnum); + first_desc = hwdesc = &tx_ring->desc_head[producer]; + netxen_clear_cmddesc((u64 *)hwdesc); + + netxen_set_tx_frags_len(first_desc, frag_count, skb->len); + netxen_set_tx_port(first_desc, adapter->portnum); - hwdesc->buffer_length[0] = cpu_to_le16(first_seg_len); - hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); + for (i = 0; i < frag_count; i++) { - for (i = 1, k = 1; i < frag_count; i++, k++) { - struct skb_frag_struct *frag; - int len, temp_len; - unsigned long offset; + k = i % 4; - /* move to next desc. if there is a need */ - if ((i & 0x3) == 0) { - k = 0; + if ((k == 0) && (i > 0)) { + /* move to next desc.*/ producer = get_next_index(producer, num_txd); hwdesc = &tx_ring->desc_head[producer]; netxen_clear_cmddesc((u64 *)hwdesc); - pbuf = &tx_ring->cmd_buf_arr[producer]; - pbuf->skb = NULL; - } - frag = &skb_shinfo(skb)->frags[i - 1]; - len = frag->size; - offset = frag->page_offset; - - temp_len = len; - temp_dma = pci_map_page(pdev, frag->page, offset, - len, PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(pdev, temp_dma)) { - netxen_clean_tx_dma_mapping(pdev, pbuf, i); - goto drop_packet; + tx_ring->cmd_buf_arr[producer].skb = NULL; } - buffrag++; - buffrag->dma = temp_dma; - buffrag->length = temp_len; + buffrag = &pbuf->frag_array[i]; - hwdesc->buffer_length[k] = cpu_to_le16(temp_len); + hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length); switch (k) { case 0: - hwdesc->addr_buffer1 = cpu_to_le64(temp_dma); + hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); break; case 1: - hwdesc->addr_buffer2 = cpu_to_le64(temp_dma); + hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma); break; case 2: - hwdesc->addr_buffer3 = cpu_to_le64(temp_dma); + hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma); break; case 3: - hwdesc->addr_buffer4 = cpu_to_le64(temp_dma); + hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma); break; } - frag++; } - producer = get_next_index(producer, num_txd); - /* For LSO, we need to copy the MAC/IP/TCP headers into - * the descriptor ring - */ - if (is_tso) { - int hdr_len, first_hdr_len, more_hdr; - hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - if (hdr_len > (sizeof(struct cmd_desc_type0) - 2)) { - first_hdr_len = sizeof(struct cmd_desc_type0) - 2; - more_hdr = 1; - } else { - first_hdr_len = hdr_len; - more_hdr = 0; - } - /* copy the MAC/IP/TCP headers to the cmd descriptor list */ - hwdesc = &tx_ring->desc_head[producer]; - pbuf = &tx_ring->cmd_buf_arr[producer]; - pbuf->skb = NULL; - - /* copy the first 64 bytes */ - memcpy(((void *)hwdesc) + 2, - (void *)(skb->data), first_hdr_len); - producer = get_next_index(producer, num_txd); - - if (more_hdr) { - hwdesc = &tx_ring->desc_head[producer]; - pbuf = &tx_ring->cmd_buf_arr[producer]; - pbuf->skb = NULL; - /* copy the next 64 bytes - should be enough except - * for pathological case - */ - skb_copy_from_linear_data_offset(skb, first_hdr_len, - hwdesc, - (hdr_len - - first_hdr_len)); - producer = get_next_index(producer, num_txd); - } - } + tx_ring->producer = get_next_index(producer, num_txd); - tx_ring->producer = producer; - adapter->stats.txbytes += skb->len; + netxen_tso_check(netdev, tx_ring, first_desc, skb); netxen_nic_update_cmd_producer(adapter, tx_ring); + adapter->stats.txbytes += skb->len; adapter->stats.xmitcalled++; return NETDEV_TX_OK; @@ -1635,58 +1868,14 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) netxen_advert_link_change(adapter, linkup); } -static void netxen_nic_thermal_shutdown(struct netxen_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - netif_device_detach(netdev); - netxen_nic_down(adapter, netdev); - netxen_nic_detach(adapter); -} - -static void netxen_watchdog(unsigned long v) -{ - struct netxen_adapter *adapter = (struct netxen_adapter *)v; - - if (netxen_nic_check_temp(adapter)) - goto do_sched; - - if (!adapter->has_link_events) { - netxen_nic_handle_phy_intr(adapter); - - if (adapter->link_changed) - goto do_sched; - } - - if (netif_running(adapter->netdev)) - mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); - - return; - -do_sched: - schedule_work(&adapter->watchdog_task); -} - -void netxen_watchdog_task(struct work_struct *work) +static void netxen_tx_timeout(struct net_device *netdev) { - struct netxen_adapter *adapter = - container_of(work, struct netxen_adapter, watchdog_task); + struct netxen_adapter *adapter = netdev_priv(netdev); - if (adapter->temp == NX_TEMP_PANIC) { - netxen_nic_thermal_shutdown(adapter); + if (test_bit(__NX_RESETTING, &adapter->state)) return; - } - - if (adapter->link_changed) - netxen_nic_set_link_parameters(adapter); - - if (netif_running(adapter->netdev)) - mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); -} -static void netxen_tx_timeout(struct net_device *netdev) -{ - struct netxen_adapter *adapter = netdev_priv(netdev); + dev_err(&netdev->dev, "transmit timeout, resetting.\n"); schedule_work(&adapter->tx_timeout_task); } @@ -1698,15 +1887,37 @@ static void netxen_tx_timeout_task(struct work_struct *work) if (!netif_running(adapter->netdev)) return; - printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", - netxen_nic_driver_name, adapter->netdev->name); + if (test_and_set_bit(__NX_RESETTING, &adapter->state)) + return; - netxen_napi_disable(adapter); + if (++adapter->tx_timeo_cnt >= NX_MAX_TX_TIMEOUTS) + goto request_reset; - adapter->netdev->trans_start = jiffies; + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + /* try to scrub interrupt */ + netxen_napi_disable(adapter); - netxen_napi_enable(adapter); - netif_wake_queue(adapter->netdev); + adapter->netdev->trans_start = jiffies; + + netxen_napi_enable(adapter); + + netif_wake_queue(adapter->netdev); + + goto done; + + } else { + if (!netxen_nic_reset_context(adapter)) { + adapter->netdev->trans_start = jiffies; + goto done; + } + + /* context reset failed, fall through for fw reset */ + } + +request_reset: + adapter->need_fw_reset = 1; +done: + clear_bit(__NX_RESETTING, &adapter->state); } struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) @@ -1716,7 +1927,7 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) memset(stats, 0, sizeof(*stats)); - stats->rx_packets = adapter->stats.no_rcv; + stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts; stats->tx_packets = adapter->stats.xmitfinished; stats->rx_bytes = adapter->stats.rxbytes; stats->tx_bytes = adapter->stats.txbytes; @@ -1732,41 +1943,37 @@ static irqreturn_t netxen_intr(int irq, void *data) struct netxen_adapter *adapter = sds_ring->adapter; u32 status = 0; - status = adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); + status = readl(adapter->isr_int_vec); - if (!(status & adapter->legacy_intr.int_vec_bit)) + if (!(status & adapter->int_vec_bit)) return IRQ_NONE; - if (adapter->ahw.revision_id >= NX_P3_B1) { + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { /* check interrupt state machine, to be sure */ - status = adapter->pci_read_immediate(adapter, - ISR_INT_STATE_REG); + status = readl(adapter->crb_int_state_reg); if (!ISR_LEGACY_INT_TRIGGERED(status)) return IRQ_NONE; } else { unsigned long our_int = 0; - our_int = NXRD32(adapter, CRB_INT_VECTOR); + our_int = readl(adapter->crb_int_state_reg); /* not our interrupt */ if (!test_and_clear_bit((7 + adapter->portnum), &our_int)) return IRQ_NONE; /* claim interrupt */ - NXWR32(adapter, CRB_INT_VECTOR, (our_int & 0xffffffff)); - } + writel((our_int & 0xffffffff), adapter->crb_int_state_reg); - /* clear interrupt */ - if (adapter->fw_major < 4) + /* clear interrupt */ netxen_nic_disable_int(sds_ring); + } - adapter->pci_write_immediate(adapter, - adapter->legacy_intr.tgt_status_reg, - 0xffffffff); + writel(0xffffffff, adapter->tgt_status_reg); /* read twice to ensure write is flushed */ - adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); - adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); + readl(adapter->isr_int_vec); + readl(adapter->isr_int_vec); napi_schedule(&sds_ring->napi); @@ -1779,8 +1986,7 @@ static irqreturn_t netxen_msi_intr(int irq, void *data) struct netxen_adapter *adapter = sds_ring->adapter; /* clear interrupt */ - adapter->pci_write_immediate(adapter, - adapter->msi_tgt_status, 0xffffffff); + writel(0xffffffff, adapter->tgt_status_reg); napi_schedule(&sds_ring->napi); return IRQ_HANDLED; @@ -1827,6 +2033,473 @@ static void netxen_nic_poll_controller(struct net_device *netdev) } #endif +static int +nx_incr_dev_ref_cnt(struct netxen_adapter *adapter) +{ + int count; + if (netxen_api_lock(adapter)) + return -EIO; + + count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); + + NXWR32(adapter, NX_CRB_DEV_REF_COUNT, ++count); + + netxen_api_unlock(adapter); + return count; +} + +static int +nx_decr_dev_ref_cnt(struct netxen_adapter *adapter) +{ + int count; + if (netxen_api_lock(adapter)) + return -EIO; + + count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); + WARN_ON(count == 0); + + NXWR32(adapter, NX_CRB_DEV_REF_COUNT, --count); + + if (count == 0) + NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_COLD); + + netxen_api_unlock(adapter); + return count; +} + +static void +nx_dev_request_reset(struct netxen_adapter *adapter) +{ + u32 state; + + if (netxen_api_lock(adapter)) + return; + + state = NXRD32(adapter, NX_CRB_DEV_STATE); + + if (state != NX_DEV_INITALIZING) + NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET); + + netxen_api_unlock(adapter); +} + +static int +netxen_can_start_firmware(struct netxen_adapter *adapter) +{ + int count; + int can_start = 0; + + if (netxen_api_lock(adapter)) + return 0; + + count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); + + if ((count < 0) || (count >= NX_MAX_PCI_FUNC)) + count = 0; + + if (count == 0) { + can_start = 1; + NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_INITALIZING); + } + + NXWR32(adapter, NX_CRB_DEV_REF_COUNT, ++count); + + netxen_api_unlock(adapter); + + return can_start; +} + +static void +netxen_schedule_work(struct netxen_adapter *adapter, + work_func_t func, int delay) +{ + INIT_DELAYED_WORK(&adapter->fw_work, func); + schedule_delayed_work(&adapter->fw_work, delay); +} + +static void +netxen_cancel_fw_work(struct netxen_adapter *adapter) +{ + while (test_and_set_bit(__NX_RESETTING, &adapter->state)) + msleep(10); + + cancel_delayed_work_sync(&adapter->fw_work); +} + +static void +netxen_attach_work(struct work_struct *work) +{ + struct netxen_adapter *adapter = container_of(work, + struct netxen_adapter, fw_work.work); + struct net_device *netdev = adapter->netdev; + int err = 0; + + if (netif_running(netdev)) { + err = netxen_nic_attach(adapter); + if (err) + goto done; + + err = netxen_nic_up(adapter, netdev); + if (err) { + netxen_nic_detach(adapter); + goto done; + } + + netxen_config_indev_addr(netdev, NETDEV_UP); + } + + netif_device_attach(netdev); + +done: + adapter->fw_fail_cnt = 0; + clear_bit(__NX_RESETTING, &adapter->state); + netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY); +} + +static void +netxen_fwinit_work(struct work_struct *work) +{ + struct netxen_adapter *adapter = container_of(work, + struct netxen_adapter, fw_work.work); + int dev_state; + + dev_state = NXRD32(adapter, NX_CRB_DEV_STATE); + + switch (dev_state) { + case NX_DEV_COLD: + case NX_DEV_READY: + if (!netxen_start_firmware(adapter)) { + netxen_schedule_work(adapter, netxen_attach_work, 0); + return; + } + break; + + case NX_DEV_INITALIZING: + if (++adapter->fw_wait_cnt < FW_POLL_THRESH) { + netxen_schedule_work(adapter, + netxen_fwinit_work, 2 * FW_POLL_DELAY); + return; + } + break; + + case NX_DEV_FAILED: + default: + break; + } + + nx_incr_dev_ref_cnt(adapter); + clear_bit(__NX_RESETTING, &adapter->state); +} + +static void +netxen_detach_work(struct work_struct *work) +{ + struct netxen_adapter *adapter = container_of(work, + struct netxen_adapter, fw_work.work); + struct net_device *netdev = adapter->netdev; + int ref_cnt, delay; + u32 status; + + netif_device_detach(netdev); + + if (netif_running(netdev)) + netxen_nic_down(adapter, netdev); + + netxen_nic_detach(adapter); + + status = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1); + + ref_cnt = nx_decr_dev_ref_cnt(adapter); + + if (status & NX_RCODE_FATAL_ERROR) + return; + + if (adapter->temp == NX_TEMP_PANIC) + return; + + delay = (ref_cnt == 0) ? 0 : (2 * FW_POLL_DELAY); + + adapter->fw_wait_cnt = 0; + netxen_schedule_work(adapter, netxen_fwinit_work, delay); +} + +static int +netxen_check_health(struct netxen_adapter *adapter) +{ + u32 state, heartbit; + struct net_device *netdev = adapter->netdev; + + if (netxen_nic_check_temp(adapter)) + goto detach; + + if (adapter->need_fw_reset) { + nx_dev_request_reset(adapter); + goto detach; + } + + state = NXRD32(adapter, NX_CRB_DEV_STATE); + if (state == NX_DEV_NEED_RESET) + goto detach; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return 0; + + heartbit = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER); + if (heartbit != adapter->heartbit) { + adapter->heartbit = heartbit; + adapter->fw_fail_cnt = 0; + return 0; + } + + if (++adapter->fw_fail_cnt < FW_FAIL_THRESH) + return 0; + + clear_bit(__NX_FW_ATTACHED, &adapter->state); + + dev_info(&netdev->dev, "firmware hang detected\n"); + +detach: + if (!test_and_set_bit(__NX_RESETTING, &adapter->state)) + netxen_schedule_work(adapter, netxen_detach_work, 0); + return 1; +} + +static void +netxen_fw_poll_work(struct work_struct *work) +{ + struct netxen_adapter *adapter = container_of(work, + struct netxen_adapter, fw_work.work); + + if (test_bit(__NX_RESETTING, &adapter->state)) + goto reschedule; + + if (test_bit(__NX_DEV_UP, &adapter->state)) { + if (!adapter->has_link_events) { + + netxen_nic_handle_phy_intr(adapter); + + if (adapter->link_changed) + netxen_nic_set_link_parameters(adapter); + } + } + + if (netxen_check_health(adapter)) + return; + +reschedule: + netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY); +} + +static ssize_t +netxen_store_bridged_mode(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) +{ + struct net_device *net = to_net_dev(dev); + struct netxen_adapter *adapter = netdev_priv(net); + unsigned long new; + int ret = -EINVAL; + + if (!(adapter->capabilities & NX_FW_CAPABILITY_BDG)) + goto err_out; + + if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) + goto err_out; + + if (strict_strtoul(buf, 2, &new)) + goto err_out; + + if (!netxen_config_bridged_mode(adapter, !!new)) + ret = len; + +err_out: + return ret; +} + +static ssize_t +netxen_show_bridged_mode(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct net_device *net = to_net_dev(dev); + struct netxen_adapter *adapter; + int bridged_mode = 0; + + adapter = netdev_priv(net); + + if (adapter->capabilities & NX_FW_CAPABILITY_BDG) + bridged_mode = !!(adapter->flags & NETXEN_NIC_BRIDGE_ENABLED); + + return sprintf(buf, "%d\n", bridged_mode); +} + +static struct device_attribute dev_attr_bridged_mode = { + .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)}, + .show = netxen_show_bridged_mode, + .store = netxen_store_bridged_mode, +}; + +static void +netxen_create_sysfs_entries(struct netxen_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct device *dev = &netdev->dev; + + if (adapter->capabilities & NX_FW_CAPABILITY_BDG) { + /* bridged_mode control */ + if (device_create_file(dev, &dev_attr_bridged_mode)) { + dev_warn(&netdev->dev, + "failed to create bridged_mode sysfs entry\n"); + } + } +} + +static void +netxen_remove_sysfs_entries(struct netxen_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct device *dev = &netdev->dev; + + if (adapter->capabilities & NX_FW_CAPABILITY_BDG) + device_remove_file(dev, &dev_attr_bridged_mode); +} + +#ifdef CONFIG_INET + +#define is_netxen_netdev(dev) (dev->netdev_ops == &netxen_netdev_ops) + +static int +netxen_destip_supported(struct netxen_adapter *adapter) +{ + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return 0; + + if (adapter->ahw.cut_through) + return 0; + + return 1; +} + +static void +netxen_config_indev_addr(struct net_device *dev, unsigned long event) +{ + struct in_device *indev; + struct netxen_adapter *adapter = netdev_priv(dev); + + if (!netxen_destip_supported(adapter)) + return; + + indev = in_dev_get(dev); + if (!indev) + return; + + for_ifa(indev) { + switch (event) { + case NETDEV_UP: + netxen_config_ipaddr(adapter, + ifa->ifa_address, NX_IP_UP); + break; + case NETDEV_DOWN: + netxen_config_ipaddr(adapter, + ifa->ifa_address, NX_IP_DOWN); + break; + default: + break; + } + } endfor_ifa(indev); + + in_dev_put(indev); + return; +} + +static int netxen_netdev_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct netxen_adapter *adapter; + struct net_device *dev = (struct net_device *)ptr; + +recheck: + if (dev == NULL) + goto done; + + if (dev->priv_flags & IFF_802_1Q_VLAN) { + dev = vlan_dev_real_dev(dev); + goto recheck; + } + + if (!is_netxen_netdev(dev)) + goto done; + + adapter = netdev_priv(dev); + + if (!adapter) + goto done; + + if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) + goto done; + + netxen_config_indev_addr(dev, event); +done: + return NOTIFY_DONE; +} + +static int +netxen_inetaddr_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct netxen_adapter *adapter; + struct net_device *dev; + + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; + + dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL; + +recheck: + if (dev == NULL || !netif_running(dev)) + goto done; + + if (dev->priv_flags & IFF_802_1Q_VLAN) { + dev = vlan_dev_real_dev(dev); + goto recheck; + } + + if (!is_netxen_netdev(dev)) + goto done; + + adapter = netdev_priv(dev); + + if (!adapter || !netxen_destip_supported(adapter)) + goto done; + + if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) + goto done; + + switch (event) { + case NETDEV_UP: + netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP); + break; + case NETDEV_DOWN: + netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_DOWN); + break; + default: + break; + } + +done: + return NOTIFY_DONE; +} + +static struct notifier_block netxen_netdev_cb = { + .notifier_call = netxen_netdev_event, +}; + +static struct notifier_block netxen_inetaddr_cb = { + .notifier_call = netxen_inetaddr_event, +}; +#else +static void +netxen_config_indev_addr(struct net_device *dev, unsigned long event) +{ } +#endif + static struct pci_driver netxen_driver = { .name = netxen_nic_driver_name, .id_table = netxen_pci_tbl, @@ -1834,16 +2507,20 @@ static struct pci_driver netxen_driver = { .remove = __devexit_p(netxen_nic_remove), #ifdef CONFIG_PM .suspend = netxen_nic_suspend, - .resume = netxen_nic_resume + .resume = netxen_nic_resume, #endif + .shutdown = netxen_nic_shutdown }; -/* Driver Registration on NetXen card */ - static int __init netxen_init_module(void) { printk(KERN_INFO "%s\n", netxen_nic_driver_string); +#ifdef CONFIG_INET + register_netdevice_notifier(&netxen_netdev_cb); + register_inetaddr_notifier(&netxen_inetaddr_cb); +#endif + return pci_register_driver(&netxen_driver); } @@ -1852,6 +2529,11 @@ module_init(netxen_init_module); static void __exit netxen_exit_module(void) { pci_unregister_driver(&netxen_driver); + +#ifdef CONFIG_INET + unregister_inetaddr_notifier(&netxen_inetaddr_cb); + unregister_netdevice_notifier(&netxen_netdev_cb); +#endif } module_exit(netxen_exit_module); diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c deleted file mode 100644 index 5941c79be72..00000000000 --- a/drivers/net/netxen/netxen_nic_niu.c +++ /dev/null @@ -1,550 +0,0 @@ -/* - * Copyright (C) 2003 - 2009 NetXen, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE. - * - * Contact Information: - * info@netxen.com - * NetXen Inc, - * 18922 Forge Drive - * Cupertino, CA 95014-0701 - * - */ - -#include "netxen_nic.h" - -#define NETXEN_GB_MAC_SOFT_RESET 0x80000000 -#define NETXEN_GB_MAC_RESET_PROT_BLK 0x000F0000 -#define NETXEN_GB_MAC_ENABLE_TX_RX 0x00000005 -#define NETXEN_GB_MAC_PAUSED_FRMS 0x00000020 - -static long phy_lock_timeout = 100000000; - -static int phy_lock(struct netxen_adapter *adapter) -{ - int i; - int done = 0, timeout = 0; - - while (!done) { - done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK)); - if (done == 1) - break; - if (timeout >= phy_lock_timeout) { - return -1; - } - timeout++; - if (!in_atomic()) - schedule(); - else { - for (i = 0; i < 20; i++) - cpu_relax(); - } - } - - NXWR32(adapter, NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER); - return 0; -} - -static int phy_unlock(struct netxen_adapter *adapter) -{ - adapter->pci_read_immediate(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK)); - - return 0; -} - -/* - * netxen_niu_gbe_phy_read - read a register from the GbE PHY via - * mii management interface. - * - * Note: The MII management interface goes through port 0. - * Individual phys are addressed as follows: - * @param phy [15:8] phy id - * @param reg [7:0] register number - * - * @returns 0 on success - * -1 on error - * - */ -int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg, - __u32 * readval) -{ - long timeout = 0; - long result = 0; - long restore = 0; - long phy = adapter->physical_port; - __u32 address; - __u32 command; - __u32 status; - __u32 mac_cfg0; - - if (phy_lock(adapter) != 0) { - return -1; - } - - /* - * MII mgmt all goes through port 0 MAC interface, - * so it cannot be in reset - */ - - mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0)); - if (netxen_gb_get_soft_reset(mac_cfg0)) { - __u32 temp; - temp = 0; - netxen_gb_tx_reset_pb(temp); - netxen_gb_rx_reset_pb(temp); - netxen_gb_tx_reset_mac(temp); - netxen_gb_rx_reset_mac(temp); - if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp)) - return -EIO; - restore = 1; - } - - address = 0; - netxen_gb_mii_mgmt_reg_addr(address, reg); - netxen_gb_mii_mgmt_phy_addr(address, phy); - if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address)) - return -EIO; - command = 0; /* turn off any prior activity */ - if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) - return -EIO; - /* send read command */ - netxen_gb_mii_mgmt_set_read_cycle(command); - if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) - return -EIO; - - status = 0; - do { - status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0)); - timeout++; - } while ((netxen_get_gb_mii_mgmt_busy(status) - || netxen_get_gb_mii_mgmt_notvalid(status)) - && (timeout++ < NETXEN_NIU_PHY_WAITMAX)); - - if (timeout < NETXEN_NIU_PHY_WAITMAX) { - *readval = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_STATUS(0)); - result = 0; - } else - result = -1; - - if (restore) - if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0)) - return -EIO; - phy_unlock(adapter); - return result; -} - -/* - * netxen_niu_gbe_phy_write - write a register to the GbE PHY via - * mii management interface. - * - * Note: The MII management interface goes through port 0. - * Individual phys are addressed as follows: - * @param phy [15:8] phy id - * @param reg [7:0] register number - * - * @returns 0 on success - * -1 on error - * - */ -int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg, - __u32 val) -{ - long timeout = 0; - long result = 0; - long restore = 0; - long phy = adapter->physical_port; - __u32 address; - __u32 command; - __u32 status; - __u32 mac_cfg0; - - /* - * MII mgmt all goes through port 0 MAC interface, so it - * cannot be in reset - */ - - mac_cfg0 = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0)); - if (netxen_gb_get_soft_reset(mac_cfg0)) { - __u32 temp; - temp = 0; - netxen_gb_tx_reset_pb(temp); - netxen_gb_rx_reset_pb(temp); - netxen_gb_tx_reset_mac(temp); - netxen_gb_rx_reset_mac(temp); - - if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), temp)) - return -EIO; - restore = 1; - } - - command = 0; /* turn off any prior activity */ - if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), command)) - return -EIO; - - address = 0; - netxen_gb_mii_mgmt_reg_addr(address, reg); - netxen_gb_mii_mgmt_phy_addr(address, phy); - if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), address)) - return -EIO; - - if (NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0), val)) - return -EIO; - - status = 0; - do { - status = NXRD32(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(0)); - timeout++; - } while ((netxen_get_gb_mii_mgmt_busy(status)) - && (timeout++ < NETXEN_NIU_PHY_WAITMAX)); - - if (timeout < NETXEN_NIU_PHY_WAITMAX) - result = 0; - else - result = -EIO; - - /* restore the state of port 0 MAC in case we tampered with it */ - if (restore) - if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), mac_cfg0)) - return -EIO; - - return result; -} - -int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter) -{ - NXWR32(adapter, NETXEN_NIU_INT_MASK, 0x3f); - return 0; -} - -int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter) -{ - int result = 0; - __u32 enable = 0; - netxen_set_phy_int_link_status_changed(enable); - netxen_set_phy_int_autoneg_completed(enable); - netxen_set_phy_int_speed_changed(enable); - - if (0 != - netxen_niu_gbe_phy_write(adapter, - NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE, - enable)) - result = -EIO; - - return result; -} - -int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter) -{ - NXWR32(adapter, NETXEN_NIU_INT_MASK, 0x7f); - return 0; -} - -int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter) -{ - int result = 0; - if (0 != - netxen_niu_gbe_phy_write(adapter, - NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE, 0)) - result = -EIO; - - return result; -} - -static int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter) -{ - int result = 0; - if (0 != - netxen_niu_gbe_phy_write(adapter, - NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS, - -EIO)) - result = -EIO; - - return result; -} - -/* - * netxen_niu_gbe_set_mii_mode- Set 10/100 Mbit Mode for GbE MAC - * - */ -static void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter, - int port, long enable) -{ - NXWR32(adapter, NETXEN_NIU_MODE, 0x2); - NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x80000000); - NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025); - NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), 0xf1ff); - NXWR32(adapter, NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0); - NXWR32(adapter, NETXEN_NIU_GB0_MII_MODE + (port << 3), 1); - NXWR32(adapter, (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); - NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); - - if (enable) { - /* - * Do NOT enable flow control until a suitable solution for - * shutting down pause frames is found. - */ - NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x5); - } - - if (netxen_niu_gbe_enable_phy_interrupts(adapter)) - printk(KERN_ERR "ERROR enabling PHY interrupts\n"); - if (netxen_niu_gbe_clear_phy_interrupts(adapter)) - printk(KERN_ERR "ERROR clearing PHY interrupts\n"); -} - -/* - * netxen_niu_gbe_set_gmii_mode- Set GbE Mode for GbE MAC - */ -static void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter, - int port, long enable) -{ - NXWR32(adapter, NETXEN_NIU_MODE, 0x2); - NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x80000000); - NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x0000f0025); - NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), 0xf2ff); - NXWR32(adapter, NETXEN_NIU_GB0_MII_MODE + (port << 3), 0); - NXWR32(adapter, NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1); - NXWR32(adapter, (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); - NXWR32(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); - - if (enable) { - /* - * Do NOT enable flow control until a suitable solution for - * shutting down pause frames is found. - */ - NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), 0x5); - } - - if (netxen_niu_gbe_enable_phy_interrupts(adapter)) - printk(KERN_ERR "ERROR enabling PHY interrupts\n"); - if (netxen_niu_gbe_clear_phy_interrupts(adapter)) - printk(KERN_ERR "ERROR clearing PHY interrupts\n"); -} - -int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) -{ - int result = 0; - __u32 status; - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - return 0; - - if (adapter->disable_phy_interrupts) - adapter->disable_phy_interrupts(adapter); - mdelay(2); - - if (0 == netxen_niu_gbe_phy_read(adapter, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, &status)) { - if (netxen_get_phy_link(status)) { - if (netxen_get_phy_speed(status) == 2) { - netxen_niu_gbe_set_gmii_mode(adapter, port, 1); - } else if ((netxen_get_phy_speed(status) == 1) - || (netxen_get_phy_speed(status) == 0)) { - netxen_niu_gbe_set_mii_mode(adapter, port, 1); - } else { - result = -1; - } - - } else { - /* - * We don't have link. Cable must be unconnected. - * Enable phy interrupts so we take action when - * plugged in. - */ - - NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - NETXEN_GB_MAC_SOFT_RESET); - NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - NETXEN_GB_MAC_RESET_PROT_BLK | - NETXEN_GB_MAC_ENABLE_TX_RX | - NETXEN_GB_MAC_PAUSED_FRMS); - if (netxen_niu_gbe_clear_phy_interrupts(adapter)) - printk(KERN_ERR - "ERROR clearing PHY interrupts\n"); - if (netxen_niu_gbe_enable_phy_interrupts(adapter)) - printk(KERN_ERR - "ERROR enabling PHY interrupts\n"); - if (netxen_niu_gbe_clear_phy_interrupts(adapter)) - printk(KERN_ERR - "ERROR clearing PHY interrupts\n"); - result = -1; - } - } else { - result = -EIO; - } - return result; -} - -int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port) -{ - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447); - NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5); - } - - return 0; -} - -/* Disable a GbE interface */ -int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter) -{ - __u32 mac_cfg0; - u32 port = adapter->physical_port; - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - return 0; - - if (port > NETXEN_NIU_MAX_GBE_PORTS) - return -EINVAL; - mac_cfg0 = 0; - netxen_gb_soft_reset(mac_cfg0); - if (NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), mac_cfg0)) - return -EIO; - return 0; -} - -/* Disable an XG interface */ -int netxen_niu_disable_xg_port(struct netxen_adapter *adapter) -{ - __u32 mac_cfg; - u32 port = adapter->physical_port; - - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) - return 0; - - if (port > NETXEN_NIU_MAX_XG_PORTS) - return -EINVAL; - - mac_cfg = 0; - if (NXWR32(adapter, - NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg)) - return -EIO; - return 0; -} - -/* Set promiscuous mode for a GbE interface */ -int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, - u32 mode) -{ - __u32 reg; - u32 port = adapter->physical_port; - - if (port > NETXEN_NIU_MAX_GBE_PORTS) - return -EINVAL; - - /* save previous contents */ - reg = NXRD32(adapter, NETXEN_NIU_GB_DROP_WRONGADDR); - if (mode == NETXEN_NIU_PROMISC_MODE) { - switch (port) { - case 0: - netxen_clear_gb_drop_gb0(reg); - break; - case 1: - netxen_clear_gb_drop_gb1(reg); - break; - case 2: - netxen_clear_gb_drop_gb2(reg); - break; - case 3: - netxen_clear_gb_drop_gb3(reg); - break; - default: - return -EIO; - } - } else { - switch (port) { - case 0: - netxen_set_gb_drop_gb0(reg); - break; - case 1: - netxen_set_gb_drop_gb1(reg); - break; - case 2: - netxen_set_gb_drop_gb2(reg); - break; - case 3: - netxen_set_gb_drop_gb3(reg); - break; - default: - return -EIO; - } - } - if (NXWR32(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, reg)) - return -EIO; - return 0; -} - -int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, - u32 mode) -{ - __u32 reg; - u32 port = adapter->physical_port; - - if (port > NETXEN_NIU_MAX_XG_PORTS) - return -EINVAL; - - reg = NXRD32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port)); - if (mode == NETXEN_NIU_PROMISC_MODE) - reg = (reg | 0x2000UL); - else - reg = (reg & ~0x2000UL); - - if (mode == NETXEN_NIU_ALLMULTI_MODE) - reg = (reg | 0x1000UL); - else - reg = (reg & ~0x1000UL); - - NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg); - - return 0; -} - -int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr) -{ - u32 mac_hi, mac_lo; - u32 reg_hi, reg_lo; - - u8 phy = adapter->physical_port; - u8 phy_count = (adapter->ahw.port_type == NETXEN_NIC_XGBE) ? - NETXEN_NIU_MAX_XG_PORTS : NETXEN_NIU_MAX_GBE_PORTS; - - if (phy >= phy_count) - return -EINVAL; - - mac_lo = ((u32)addr[0] << 16) | ((u32)addr[1] << 24); - mac_hi = addr[2] | ((u32)addr[3] << 8) | - ((u32)addr[4] << 16) | ((u32)addr[5] << 24); - - if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { - reg_lo = NETXEN_NIU_XGE_STATION_ADDR_0_1 + (0x10000 * phy); - reg_hi = NETXEN_NIU_XGE_STATION_ADDR_0_HI + (0x10000 * phy); - } else { - reg_lo = NETXEN_NIU_GB_STATION_ADDR_1(phy); - reg_hi = NETXEN_NIU_GB_STATION_ADDR_0(phy); - } - - /* write twice to flush */ - if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi)) - return -EIO; - if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi)) - return -EIO; - - return 0; -} diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h deleted file mode 100644 index b73a62ca74f..00000000000 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2003 - 2009 NetXen, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, - * MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE. - * - * Contact Information: - * info@netxen.com - * NetXen Inc, - * 18922 Forge Drive - * Cupertino, CA 95014-0701 - * - */ - -#ifndef __NIC_PHAN_REG_H_ -#define __NIC_PHAN_REG_H_ - -/* - * CRB Registers or queue message done only at initialization time. - */ -#define NIC_CRB_BASE NETXEN_CAM_RAM(0x200) -#define NETXEN_NIC_REG(X) (NIC_CRB_BASE+(X)) -#define NIC_CRB_BASE_2 NETXEN_CAM_RAM(0x700) -#define NETXEN_NIC_REG_2(X) (NIC_CRB_BASE_2+(X)) - -#define CRB_PHAN_CNTRL_LO_OFFSET NETXEN_NIC_REG(0x00) -#define CRB_PHAN_CNTRL_HI_OFFSET NETXEN_NIC_REG(0x04) -#define CRB_CMD_PRODUCER_OFFSET NETXEN_NIC_REG(0x08) -#define CRB_CMD_CONSUMER_OFFSET NETXEN_NIC_REG(0x0c) -#define CRB_PAUSE_ADDR_LO NETXEN_NIC_REG(0x10) -#define CRB_PAUSE_ADDR_HI NETXEN_NIC_REG(0x14) -#define NX_CDRP_CRB_OFFSET NETXEN_NIC_REG(0x18) -#define NX_ARG1_CRB_OFFSET NETXEN_NIC_REG(0x1c) -#define NX_ARG2_CRB_OFFSET NETXEN_NIC_REG(0x20) -#define NX_ARG3_CRB_OFFSET NETXEN_NIC_REG(0x24) -#define NX_SIGN_CRB_OFFSET NETXEN_NIC_REG(0x28) -#define CRB_CMD_INTR_LOOP NETXEN_NIC_REG(0x20) -#define CRB_CMD_DMA_LOOP NETXEN_NIC_REG(0x24) -#define CRB_RCV_INTR_LOOP NETXEN_NIC_REG(0x28) -#define CRB_RCV_DMA_LOOP NETXEN_NIC_REG(0x2c) -#define CRB_ENABLE_TX_INTR NETXEN_NIC_REG(0x30) -#define CRB_MMAP_ADDR_3 NETXEN_NIC_REG(0x34) -#define CRB_CMDPEG_CMDRING NETXEN_NIC_REG(0x38) -#define CRB_HOST_DUMMY_BUF_ADDR_HI NETXEN_NIC_REG(0x3c) -#define CRB_HOST_DUMMY_BUF_ADDR_LO NETXEN_NIC_REG(0x40) -#define CRB_MMAP_ADDR_0 NETXEN_NIC_REG(0x44) -#define CRB_MMAP_ADDR_1 NETXEN_NIC_REG(0x48) -#define CRB_MMAP_ADDR_2 NETXEN_NIC_REG(0x4c) -#define CRB_CMDPEG_STATE NETXEN_NIC_REG(0x50) -#define CRB_MMAP_SIZE_0 NETXEN_NIC_REG(0x54) -#define CRB_MMAP_SIZE_1 NETXEN_NIC_REG(0x58) -#define CRB_MMAP_SIZE_2 NETXEN_NIC_REG(0x5c) -#define CRB_MMAP_SIZE_3 NETXEN_NIC_REG(0x60) -#define CRB_GLOBAL_INT_COAL NETXEN_NIC_REG(0x64) -#define CRB_INT_COAL_MODE NETXEN_NIC_REG(0x68) -#define CRB_MAX_RCV_BUFS NETXEN_NIC_REG(0x6c) -#define CRB_TX_INT_THRESHOLD NETXEN_NIC_REG(0x70) -#define CRB_RX_PKT_TIMER NETXEN_NIC_REG(0x74) -#define CRB_TX_PKT_TIMER NETXEN_NIC_REG(0x78) -#define CRB_RX_PKT_CNT NETXEN_NIC_REG(0x7c) -#define CRB_RX_TMR_CNT NETXEN_NIC_REG(0x80) -#define CRB_RX_LRO_TIMER NETXEN_NIC_REG(0x84) -#define CRB_RX_LRO_MID_TIMER NETXEN_NIC_REG(0x88) -#define CRB_DMA_MAX_RCV_BUFS NETXEN_NIC_REG(0x8c) -#define CRB_MAX_DMA_ENTRIES NETXEN_NIC_REG(0x90) -#define CRB_XG_STATE NETXEN_NIC_REG(0x94) /* XG Link status */ -#define CRB_XG_STATE_P3 NETXEN_NIC_REG(0x98) /* XG PF Link status */ -#define CRB_AGENT_TX_SIZE NETXEN_NIC_REG(0x9c) -#define CRB_AGENT_TX_TYPE NETXEN_NIC_REG(0xa0) -#define CRB_AGENT_TX_ADDR NETXEN_NIC_REG(0xa4) -#define CRB_AGENT_TX_MSS NETXEN_NIC_REG(0xa8) -#define CRB_TX_STATE NETXEN_NIC_REG(0xac) -#define CRB_TX_COUNT NETXEN_NIC_REG(0xb0) -#define CRB_RX_STATE NETXEN_NIC_REG(0xb4) -#define CRB_RX_PERF_DEBUG_1 NETXEN_NIC_REG(0xb8) -#define CRB_RX_LRO_CONTROL NETXEN_NIC_REG(0xbc) -#define CRB_RX_LRO_START_NUM NETXEN_NIC_REG(0xc0) -#define CRB_MPORT_MODE NETXEN_NIC_REG(0xc4) -#define CRB_CMD_RING_SIZE NETXEN_NIC_REG(0xc8) -#define CRB_DMA_SHIFT NETXEN_NIC_REG(0xcc) -#define CRB_INT_VECTOR NETXEN_NIC_REG(0xd4) -#define CRB_CTX_RESET NETXEN_NIC_REG(0xd8) -#define CRB_HOST_STS_PROD NETXEN_NIC_REG(0xdc) -#define CRB_HOST_STS_CONS NETXEN_NIC_REG(0xe0) -#define CRB_PEG_CMD_PROD NETXEN_NIC_REG(0xe4) -#define CRB_PF_LINK_SPEED_1 NETXEN_NIC_REG(0xe8) -#define CRB_PF_LINK_SPEED_2 NETXEN_NIC_REG(0xec) -#define CRB_HOST_BUFFER_CONS NETXEN_NIC_REG(0xf0) -#define CRB_JUMBO_BUFFER_PROD NETXEN_NIC_REG(0xf4) -#define CRB_JUMBO_BUFFER_CONS NETXEN_NIC_REG(0xf8) -#define CRB_HOST_DUMMY_BUF NETXEN_NIC_REG(0xfc) - -#define CRB_RCVPEG_STATE NETXEN_NIC_REG(0x13c) -#define CRB_CMD_PRODUCER_OFFSET_1 NETXEN_NIC_REG(0x1ac) -#define CRB_CMD_CONSUMER_OFFSET_1 NETXEN_NIC_REG(0x1b0) -#define CRB_CMD_PRODUCER_OFFSET_2 NETXEN_NIC_REG(0x1b8) -#define CRB_CMD_CONSUMER_OFFSET_2 NETXEN_NIC_REG(0x1bc) -#define CRB_CMD_PRODUCER_OFFSET_3 NETXEN_NIC_REG(0x1d0) -#define CRB_CMD_CONSUMER_OFFSET_3 NETXEN_NIC_REG(0x1d4) -#define CRB_TEMP_STATE NETXEN_NIC_REG(0x1b4) - -#define CRB_V2P_0 NETXEN_NIC_REG(0x290) -#define CRB_V2P_1 NETXEN_NIC_REG(0x294) -#define CRB_V2P_2 NETXEN_NIC_REG(0x298) -#define CRB_V2P_3 NETXEN_NIC_REG(0x29c) -#define CRB_V2P(port) (CRB_V2P_0+((port)*4)) -#define CRB_DRIVER_VERSION NETXEN_NIC_REG(0x2a0) -#define CRB_SW_INT_MASK_0 NETXEN_NIC_REG(0x1d8) -#define CRB_SW_INT_MASK_1 NETXEN_NIC_REG(0x1e0) -#define CRB_SW_INT_MASK_2 NETXEN_NIC_REG(0x1e4) -#define CRB_SW_INT_MASK_3 NETXEN_NIC_REG(0x1e8) - -#define CRB_FW_CAPABILITIES_1 NETXEN_CAM_RAM(0x128) -#define CRB_MAC_BLOCK_START NETXEN_CAM_RAM(0x1c0) - -/* - * capabilities register, can be used to selectively enable/disable features - * for backward compability - */ -#define CRB_NIC_CAPABILITIES_HOST NETXEN_NIC_REG(0x1a8) -#define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc) -#define CRB_NIC_MSI_MODE_HOST NETXEN_NIC_REG(0x270) -#define CRB_NIC_MSI_MODE_FW NETXEN_NIC_REG(0x274) - -#define INTR_SCHEME_PERPORT 0x1 -#define MSI_MODE_MULTIFUNC 0x1 - -/* used for ethtool tests */ -#define CRB_SCRATCHPAD_TEST NETXEN_NIC_REG(0x280) - -/* - * CrbPortPhanCntrHi/Lo is used to pass the address of HostPhantomIndex address - * which can be read by the Phantom host to get producer/consumer indexes from - * Phantom/Casper. If it is not HOST_SHARED_MEMORY, then the following - * registers will be used for the addresses of the ring's shared memory - * on the Phantom. - */ - -#define nx_get_temp_val(x) ((x) >> 16) -#define nx_get_temp_state(x) ((x) & 0xffff) -#define nx_encode_temp(val, state) (((val) << 16) | (state)) - -/* - * CRB registers used by the receive peg logic. - */ - -struct netxen_recv_crb { - u32 crb_rcv_producer[NUM_RCV_DESC_RINGS]; - u32 crb_sts_consumer[NUM_STS_DESC_RINGS]; - u32 sw_int_mask[NUM_STS_DESC_RINGS]; -}; - -/* - * Temperature control. - */ -enum { - NX_TEMP_NORMAL = 0x1, /* Normal operating range */ - NX_TEMP_WARN, /* Sound alert, temperature getting high */ - NX_TEMP_PANIC /* Fatal error, hardware has shut down. */ -}; - -#endif /* __NIC_PHAN_REG_H_ */ |