summaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2008-07-25 10:40:14 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2008-07-25 10:40:14 -0400
commitff877ea80efa2015b6263766f78ee42c2a1b32f9 (patch)
tree85205005c611ab774702148558321c6fb92f1ccd /drivers/net/netxen
parent30821fee4f0cb3e6d241d9f7ddc37742212e3eb7 (diff)
parentd37e6bf68fc1eb34a4ad21d9ae8890ed37ea80e7 (diff)
Merge branch 'linux-next' of git://git.infradead.org/~dedekind/ubi-2.6
Diffstat (limited to 'drivers/net/netxen')
-rw-r--r--drivers/net/netxen/Makefile2
-rw-r--r--drivers/net/netxen/netxen_nic.h575
-rw-r--r--drivers/net/netxen/netxen_nic_ctx.c710
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c168
-rw-r--r--drivers/net/netxen/netxen_nic_hdr.h251
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c2196
-rw-r--r--drivers/net/netxen/netxen_nic_hw.h60
-rw-r--r--drivers/net/netxen/netxen_nic_init.c806
-rw-r--r--drivers/net/netxen/netxen_nic_isr.c220
-rw-r--r--drivers/net/netxen/netxen_nic_main.c1169
-rw-r--r--drivers/net/netxen/netxen_nic_niu.c114
-rw-r--r--drivers/net/netxen/netxen_nic_phan_reg.h31
12 files changed, 4551 insertions, 1751 deletions
diff --git a/drivers/net/netxen/Makefile b/drivers/net/netxen/Makefile
index a07cdc6f738..8e7c4c910d2 100644
--- a/drivers/net/netxen/Makefile
+++ b/drivers/net/netxen/Makefile
@@ -32,4 +32,4 @@
obj-$(CONFIG_NETXEN_NIC) := netxen_nic.o
netxen_nic-y := netxen_nic_hw.o netxen_nic_main.o netxen_nic_init.o \
- netxen_nic_isr.o netxen_nic_ethtool.o netxen_nic_niu.o
+ netxen_nic_ethtool.o netxen_nic_niu.o netxen_nic_ctx.o
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index da4c4fb9706..8e736614407 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -54,6 +54,7 @@
#include <linux/mm.h>
#include <linux/mman.h>
+#include <linux/vmalloc.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -63,10 +64,12 @@
#include "netxen_nic_hw.h"
-#define _NETXEN_NIC_LINUX_MAJOR 3
-#define _NETXEN_NIC_LINUX_MINOR 4
-#define _NETXEN_NIC_LINUX_SUBVERSION 18
-#define NETXEN_NIC_LINUX_VERSIONID "3.4.18"
+#define _NETXEN_NIC_LINUX_MAJOR 4
+#define _NETXEN_NIC_LINUX_MINOR 0
+#define _NETXEN_NIC_LINUX_SUBVERSION 0
+#define NETXEN_NIC_LINUX_VERSIONID "4.0.0"
+
+#define NETXEN_VERSION_CODE(a, b, c) (((a) << 16) + ((b) << 8) + (c))
#define NETXEN_NUM_FLASH_SECTORS (64)
#define NETXEN_FLASH_SECTOR_SIZE (64 * 1024)
@@ -84,7 +87,7 @@
#define TX_RINGSIZE \
(sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count)
#define RCV_BUFFSIZE \
- (sizeof(struct netxen_rx_buffer) * rcv_desc->max_rx_desc_count)
+ (sizeof(struct netxen_rx_buffer) * rds_ring->max_rx_desc_count)
#define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a)))
#define NETXEN_NETDEV_STATUS 0x1
@@ -111,6 +114,13 @@
#define NX_P2_C0 0x24
#define NX_P2_C1 0x25
+#define NX_P3_A0 0x30
+#define NX_P3_A2 0x30
+#define NX_P3_B0 0x40
+#define NX_P3_B1 0x41
+
+#define NX_IS_REVISION_P2(REVISION) (REVISION <= NX_P2_C1)
+#define NX_IS_REVISION_P3(REVISION) (REVISION >= NX_P3_A0)
#define FIRST_PAGE_GROUP_START 0
#define FIRST_PAGE_GROUP_END 0x100000
@@ -125,6 +135,16 @@
#define SECOND_PAGE_GROUP_SIZE SECOND_PAGE_GROUP_END - SECOND_PAGE_GROUP_START
#define THIRD_PAGE_GROUP_SIZE THIRD_PAGE_GROUP_END - THIRD_PAGE_GROUP_START
+#define P2_MAX_MTU (8000)
+#define P3_MAX_MTU (9600)
+#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_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 MAX_RX_BUFFER_LENGTH 1760
#define MAX_RX_JUMBO_BUFFER_LENGTH 8062
#define MAX_RX_LRO_BUFFER_LENGTH ((48*1024)-512)
@@ -132,7 +152,6 @@
#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 NETXEN_ROM_ROUNDUP 0x80000000ULL
/*
* Maximum number of ring contexts
@@ -140,16 +159,16 @@
#define MAX_RING_CTX 1
/* Opcodes to be used with the commands */
-enum {
- TX_ETHER_PKT = 0x01,
-/* The following opcodes are for IP checksum */
- TX_TCP_PKT,
- TX_UDP_PKT,
- TX_IP_PKT,
- TX_TCP_LSO,
- TX_IPSEC,
- TX_IPSEC_CMD
-};
+#define TX_ETHER_PKT 0x01
+#define TX_TCP_PKT 0x02
+#define TX_UDP_PKT 0x03
+#define TX_IP_PKT 0x04
+#define TX_TCP_LSO 0x05
+#define TX_TCP_LSO6 0x06
+#define TX_IPSEC 0x07
+#define TX_IPSEC_CMD 0x0a
+#define TX_TCPV6_PKT 0x0b
+#define TX_UDPV6_PKT 0x0c
/* The following opcodes are for internal consumption. */
#define NETXEN_CONTROL_OP 0x10
@@ -191,6 +210,7 @@ enum {
#define MAX_RCV_DESCRIPTORS 16384
#define MAX_CMD_DESCRIPTORS_HOST (MAX_CMD_DESCRIPTORS / 4)
#define MAX_RCV_DESCRIPTORS_1G (MAX_RCV_DESCRIPTORS / 4)
+#define MAX_RCV_DESCRIPTORS_10G 8192
#define MAX_JUMBO_RCV_DESCRIPTORS 1024
#define MAX_LRO_RCV_DESCRIPTORS 64
#define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS
@@ -219,8 +239,6 @@ enum {
#define MPORT_MULTI_FUNCTION_MODE 0x2222
#include "netxen_nic_phan_reg.h"
-extern unsigned long long netxen_dma_mask;
-extern unsigned long last_schedule_time;
/*
* NetXen host-peg signal message structure
@@ -289,7 +307,7 @@ struct netxen_ring_ctx {
#define netxen_set_cmd_desc_port(cmd_desc, var) \
((cmd_desc)->port_ctxid |= ((var) & 0x0F))
#define netxen_set_cmd_desc_ctxid(cmd_desc, var) \
- ((cmd_desc)->port_ctxid |= ((var) & 0xF0))
+ ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
#define netxen_set_cmd_desc_flags(cmd_desc, val) \
(cmd_desc)->flags_opcode = ((cmd_desc)->flags_opcode & \
@@ -377,8 +395,8 @@ struct rcv_desc {
};
/* opcode field in status_desc */
-#define RCV_NIC_PKT (0xA)
-#define STATUS_NIC_PKT ((RCV_NIC_PKT) << 12)
+#define NETXEN_NIC_RXPKT_DESC 0x04
+#define NETXEN_OLD_RXPKT_DESC 0x3f
/* for status field in status_desc */
#define STATUS_NEED_CKSUM (1)
@@ -410,6 +428,8 @@ struct rcv_desc {
(((sts_data) >> 28) & 0xFFFF)
#define netxen_get_sts_prot(sts_data) \
(((sts_data) >> 44) & 0x0F)
+#define netxen_get_sts_pkt_offset(sts_data) \
+ (((sts_data) >> 48) & 0x1F)
#define netxen_get_sts_opcode(sts_data) \
(((sts_data) >> 58) & 0x03F)
@@ -424,17 +444,30 @@ struct rcv_desc {
struct status_desc {
/* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
- 28-43 reference_handle, 44-47 protocol, 48-52 unused
+ 28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
53-55 desc_cnt, 56-57 owner, 58-63 opcode
*/
__le64 status_desc_data;
- __le32 hash_value;
- u8 hash_type;
- u8 msg_type;
- u8 unused;
- /* Bit pattern: 0-6 lro_count indicates frag sequence,
- 7 last_frag indicates last frag */
- u8 lro;
+ union {
+ struct {
+ __le32 hash_value;
+ u8 hash_type;
+ u8 msg_type;
+ u8 unused;
+ union {
+ /* Bit pattern: 0-6 lro_count indicates frag
+ * sequence, 7 last_frag indicates last frag
+ */
+ u8 lro;
+
+ /* chained buffers */
+ u8 nr_frags;
+ };
+ };
+ struct {
+ __le16 frag_handles[4];
+ };
+ };
} __attribute__ ((aligned(16)));
enum {
@@ -464,7 +497,20 @@ typedef enum {
NETXEN_BRDTYPE_P2_SB31_10G_IMEZ = 0x000d,
NETXEN_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e,
- NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f
+ NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f,
+
+ NETXEN_BRDTYPE_P3_REF_QG = 0x0021,
+ NETXEN_BRDTYPE_P3_HMEZ = 0x0022,
+ NETXEN_BRDTYPE_P3_10G_CX4_LP = 0x0023,
+ NETXEN_BRDTYPE_P3_4_GB = 0x0024,
+ NETXEN_BRDTYPE_P3_IMEZ = 0x0025,
+ NETXEN_BRDTYPE_P3_10G_SFP_PLUS = 0x0026,
+ NETXEN_BRDTYPE_P3_10000_BASE_T = 0x0027,
+ NETXEN_BRDTYPE_P3_XG_LOM = 0x0028,
+ NETXEN_BRDTYPE_P3_4_GB_MM = 0x0029,
+ NETXEN_BRDTYPE_P3_10G_CX4 = 0x0031,
+ NETXEN_BRDTYPE_P3_10G_XFP = 0x0032
+
} netxen_brdtype_t;
typedef enum {
@@ -747,6 +793,7 @@ struct netxen_cmd_buffer {
/* In rx_buffer, we do not need multiple fragments as is a single buffer */
struct netxen_rx_buffer {
+ struct list_head list;
struct sk_buff *skb;
u64 dma;
u16 ref_handle;
@@ -765,7 +812,6 @@ struct netxen_rx_buffer {
* contains interrupt info as well shared hardware info.
*/
struct netxen_hardware_context {
- struct pci_dev *pdev;
void __iomem *pci_base0;
void __iomem *pci_base1;
void __iomem *pci_base2;
@@ -773,15 +819,20 @@ struct netxen_hardware_context {
unsigned long first_page_group_start;
void __iomem *db_base;
unsigned long db_len;
+ unsigned long pci_len0;
+
+ u8 cut_through;
+ int qdr_sn_window;
+ int ddr_mn_window;
+ unsigned long mn_win_crb;
+ unsigned long ms_win_crb;
u8 revision_id;
u16 board_type;
struct netxen_board_info boardcfg;
- u32 xg_linkup;
- u32 qg_linksup;
+ u32 linkup;
/* Address of cmd ring in Phantom */
struct cmd_desc_type0 *cmd_desc_head;
- struct pci_dev *cmd_desc_pdev;
dma_addr_t cmd_desc_phys_addr;
struct netxen_adapter *adapter;
int pci_func;
@@ -813,17 +864,17 @@ struct netxen_adapter_stats {
* Rcv Descriptor Context. One such per Rcv Descriptor. There may
* be one Rcv Descriptor for normal packets, one for jumbo and may be others.
*/
-struct netxen_rcv_desc_ctx {
+struct nx_host_rds_ring {
u32 flags;
u32 producer;
- u32 rcv_pending; /* Num of bufs posted in phantom */
dma_addr_t phys_addr;
- struct pci_dev *phys_pdev;
+ u32 crb_rcv_producer; /* reg offset */
struct rcv_desc *desc_head; /* address of rx ring in Phantom */
u32 max_rx_desc_count;
u32 dma_size;
u32 skb_size;
struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */
+ struct list_head free_list;
int begin_alloc;
};
@@ -834,17 +885,319 @@ struct netxen_rcv_desc_ctx {
* present elsewhere.
*/
struct netxen_recv_context {
- struct netxen_rcv_desc_ctx rcv_desc[NUM_RCV_DESC_RINGS];
- u32 status_rx_producer;
+ u32 state;
+ u16 context_id;
+ u16 virt_port;
+
+ struct nx_host_rds_ring rds_rings[NUM_RCV_DESC_RINGS];
u32 status_rx_consumer;
+ u32 crb_sts_consumer; /* reg offset */
dma_addr_t rcv_status_desc_phys_addr;
- struct pci_dev *rcv_status_desc_pdev;
struct status_desc *rcv_status_desc_head;
};
-#define NETXEN_NIC_MSI_ENABLED 0x02
-#define NETXEN_DMA_MASK 0xfffffffe
-#define NETXEN_DB_MAPSIZE_BYTES 0x1000
+/* New HW context creation */
+
+#define NX_OS_CRB_RETRY_COUNT 4000
+#define NX_CDRP_SIGNATURE_MAKE(pcifn, version) \
+ (((pcifn) & 0xff) | (((version) & 0xff) << 8) | (0xcafe << 16))
+
+#define NX_CDRP_CLEAR 0x00000000
+#define NX_CDRP_CMD_BIT 0x80000000
+
+/*
+ * All responses must have the NX_CDRP_CMD_BIT cleared
+ * in the crb NX_CDRP_CRB_OFFSET.
+ */
+#define NX_CDRP_FORM_RSP(rsp) (rsp)
+#define NX_CDRP_IS_RSP(rsp) (((rsp) & NX_CDRP_CMD_BIT) == 0)
+
+#define NX_CDRP_RSP_OK 0x00000001
+#define NX_CDRP_RSP_FAIL 0x00000002
+#define NX_CDRP_RSP_TIMEOUT 0x00000003
+
+/*
+ * All commands must have the NX_CDRP_CMD_BIT set in
+ * the crb NX_CDRP_CRB_OFFSET.
+ */
+#define NX_CDRP_FORM_CMD(cmd) (NX_CDRP_CMD_BIT | (cmd))
+#define NX_CDRP_IS_CMD(cmd) (((cmd) & NX_CDRP_CMD_BIT) != 0)
+
+#define NX_CDRP_CMD_SUBMIT_CAPABILITIES 0x00000001
+#define NX_CDRP_CMD_READ_MAX_RDS_PER_CTX 0x00000002
+#define NX_CDRP_CMD_READ_MAX_SDS_PER_CTX 0x00000003
+#define NX_CDRP_CMD_READ_MAX_RULES_PER_CTX 0x00000004
+#define NX_CDRP_CMD_READ_MAX_RX_CTX 0x00000005
+#define NX_CDRP_CMD_READ_MAX_TX_CTX 0x00000006
+#define NX_CDRP_CMD_CREATE_RX_CTX 0x00000007
+#define NX_CDRP_CMD_DESTROY_RX_CTX 0x00000008
+#define NX_CDRP_CMD_CREATE_TX_CTX 0x00000009
+#define NX_CDRP_CMD_DESTROY_TX_CTX 0x0000000a
+#define NX_CDRP_CMD_SETUP_STATISTICS 0x0000000e
+#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_RCODE_SUCCESS 0
+#define NX_RCODE_NO_HOST_MEM 1
+#define NX_RCODE_NO_HOST_RESOURCE 2
+#define NX_RCODE_NO_CARD_CRB 3
+#define NX_RCODE_NO_CARD_MEM 4
+#define NX_RCODE_NO_CARD_RESOURCE 5
+#define NX_RCODE_INVALID_ARGS 6
+#define NX_RCODE_INVALID_ACTION 7
+#define NX_RCODE_INVALID_STATE 8
+#define NX_RCODE_NOT_SUPPORTED 9
+#define NX_RCODE_NOT_PERMITTED 10
+#define NX_RCODE_NOT_READY 11
+#define NX_RCODE_DOES_NOT_EXIST 12
+#define NX_RCODE_ALREADY_EXISTS 13
+#define NX_RCODE_BAD_SIGNATURE 14
+#define NX_RCODE_CMD_NOT_IMPL 15
+#define NX_RCODE_CMD_INVALID 16
+#define NX_RCODE_TIMEOUT 17
+#define NX_RCODE_CMD_FAILED 18
+#define NX_RCODE_MAX_EXCEEDED 19
+#define NX_RCODE_MAX 20
+
+#define NX_DESTROY_CTX_RESET 0
+#define NX_DESTROY_CTX_D3_RESET 1
+#define NX_DESTROY_CTX_MAX 2
+
+/*
+ * Capabilities
+ */
+#define NX_CAP_BIT(class, bit) (1 << bit)
+#define NX_CAP0_LEGACY_CONTEXT NX_CAP_BIT(0, 0)
+#define NX_CAP0_MULTI_CONTEXT NX_CAP_BIT(0, 1)
+#define NX_CAP0_LEGACY_MN NX_CAP_BIT(0, 2)
+#define NX_CAP0_LEGACY_MS NX_CAP_BIT(0, 3)
+#define NX_CAP0_CUT_THROUGH NX_CAP_BIT(0, 4)
+#define NX_CAP0_LRO NX_CAP_BIT(0, 5)
+#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)
+
+/*
+ * Context state
+ */
+#define NX_HOST_CTX_STATE_FREED 0
+#define NX_HOST_CTX_STATE_ALLOCATED 1
+#define NX_HOST_CTX_STATE_ACTIVE 2
+#define NX_HOST_CTX_STATE_DISABLED 3
+#define NX_HOST_CTX_STATE_QUIESCED 4
+#define NX_HOST_CTX_STATE_MAX 5
+
+/*
+ * Rx context
+ */
+
+typedef struct {
+ u64 host_phys_addr; /* Ring base addr */
+ u32 ring_size; /* Ring entries */
+ u16 msi_index;
+ u16 rsvd; /* Padding */
+} nx_hostrq_sds_ring_t;
+
+typedef struct {
+ u64 host_phys_addr; /* Ring base addr */
+ u64 buff_size; /* Packet buffer size */
+ u32 ring_size; /* Ring entries */
+ u32 ring_kind; /* Class of ring */
+} nx_hostrq_rds_ring_t;
+
+typedef struct {
+ u64 host_rsp_dma_addr; /* Response dma'd here */
+ u32 capabilities[4]; /* Flag bit vector */
+ u32 host_int_crb_mode; /* Interrupt crb usage */
+ u32 host_rds_crb_mode; /* RDS crb usage */
+ /* These ring offsets are relative to data[0] below */
+ u32 rds_ring_offset; /* Offset to RDS config */
+ u32 sds_ring_offset; /* Offset to SDS config */
+ u16 num_rds_rings; /* Count of RDS rings */
+ u16 num_sds_rings; /* Count of SDS rings */
+ u16 rsvd1; /* Padding */
+ u16 rsvd2; /* Padding */
+ u8 reserved[128]; /* reserve space for future expansion*/
+ /* MUST BE 64-bit aligned.
+ The following is packed:
+ - N hostrq_rds_rings
+ - N hostrq_sds_rings */
+ char data[0];
+} nx_hostrq_rx_ctx_t;
+
+typedef struct {
+ u32 host_producer_crb; /* Crb to use */
+ u32 rsvd1; /* Padding */
+} nx_cardrsp_rds_ring_t;
+
+typedef struct {
+ u32 host_consumer_crb; /* Crb to use */
+ u32 interrupt_crb; /* Crb to use */
+} nx_cardrsp_sds_ring_t;
+
+typedef struct {
+ /* These ring offsets are relative to data[0] below */
+ u32 rds_ring_offset; /* Offset to RDS config */
+ u32 sds_ring_offset; /* Offset to SDS config */
+ u32 host_ctx_state; /* Starting State */
+ u32 num_fn_per_port; /* How many PCI fn share the port */
+ u16 num_rds_rings; /* Count of RDS rings */
+ u16 num_sds_rings; /* Count of SDS rings */
+ u16 context_id; /* Handle for context */
+ u8 phys_port; /* Physical id of port */
+ u8 virt_port; /* Virtual/Logical id of port */
+ u8 reserved[128]; /* save space for future expansion */
+ /* MUST BE 64-bit aligned.
+ The following is packed:
+ - N cardrsp_rds_rings
+ - N cardrs_sds_rings */
+ char data[0];
+} nx_cardrsp_rx_ctx_t;
+
+#define SIZEOF_HOSTRQ_RX(HOSTRQ_RX, rds_rings, sds_rings) \
+ (sizeof(HOSTRQ_RX) + \
+ (rds_rings)*(sizeof(nx_hostrq_rds_ring_t)) + \
+ (sds_rings)*(sizeof(nx_hostrq_sds_ring_t)))
+
+#define SIZEOF_CARDRSP_RX(CARDRSP_RX, rds_rings, sds_rings) \
+ (sizeof(CARDRSP_RX) + \
+ (rds_rings)*(sizeof(nx_cardrsp_rds_ring_t)) + \
+ (sds_rings)*(sizeof(nx_cardrsp_sds_ring_t)))
+
+/*
+ * Tx context
+ */
+
+typedef struct {
+ u64 host_phys_addr; /* Ring base addr */
+ u32 ring_size; /* Ring entries */
+ u32 rsvd; /* Padding */
+} nx_hostrq_cds_ring_t;
+
+typedef struct {
+ u64 host_rsp_dma_addr; /* Response dma'd here */
+ u64 cmd_cons_dma_addr; /* */
+ u64 dummy_dma_addr; /* */
+ u32 capabilities[4]; /* Flag bit vector */
+ u32 host_int_crb_mode; /* Interrupt crb usage */
+ u32 rsvd1; /* Padding */
+ u16 rsvd2; /* Padding */
+ u16 interrupt_ctl;
+ u16 msi_index;
+ u16 rsvd3; /* Padding */
+ nx_hostrq_cds_ring_t cds_ring; /* Desc of cds ring */
+ u8 reserved[128]; /* future expansion */
+} nx_hostrq_tx_ctx_t;
+
+typedef struct {
+ u32 host_producer_crb; /* Crb to use */
+ u32 interrupt_crb; /* Crb to use */
+} nx_cardrsp_cds_ring_t;
+
+typedef struct {
+ u32 host_ctx_state; /* Starting state */
+ u16 context_id; /* Handle for context */
+ u8 phys_port; /* Physical id of port */
+ u8 virt_port; /* Virtual/Logical id of port */
+ nx_cardrsp_cds_ring_t cds_ring; /* Card cds settings */
+ u8 reserved[128]; /* future expansion */
+} nx_cardrsp_tx_ctx_t;
+
+#define SIZEOF_HOSTRQ_TX(HOSTRQ_TX) (sizeof(HOSTRQ_TX))
+#define SIZEOF_CARDRSP_TX(CARDRSP_TX) (sizeof(CARDRSP_TX))
+
+/* CRB */
+
+#define NX_HOST_RDS_CRB_MODE_UNIQUE 0
+#define NX_HOST_RDS_CRB_MODE_SHARED 1
+#define NX_HOST_RDS_CRB_MODE_CUSTOM 2
+#define NX_HOST_RDS_CRB_MODE_MAX 3
+
+#define NX_HOST_INT_CRB_MODE_UNIQUE 0
+#define NX_HOST_INT_CRB_MODE_SHARED 1
+#define NX_HOST_INT_CRB_MODE_NORX 2
+#define NX_HOST_INT_CRB_MODE_NOTX 3
+#define NX_HOST_INT_CRB_MODE_NORXTX 4
+
+
+/* MAC */
+
+#define MC_COUNT_P2 16
+#define MC_COUNT_P3 38
+
+#define NETXEN_MAC_NOOP 0
+#define NETXEN_MAC_ADD 1
+#define NETXEN_MAC_DEL 2
+
+typedef struct nx_mac_list_s {
+ struct nx_mac_list_s *next;
+ uint8_t mac_addr[MAX_ADDR_LEN];
+} nx_mac_list_t;
+
+/*
+ * Interrupt coalescing defaults. The defaults are for 1500 MTU. It is
+ * adjusted based on configured MTU.
+ */
+#define NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US 3
+#define NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS 256
+#define NETXEN_DEFAULT_INTR_COALESCE_TX_PACKETS 64
+#define NETXEN_DEFAULT_INTR_COALESCE_TX_TIME_US 4
+
+#define NETXEN_NIC_INTR_DEFAULT 0x04
+
+typedef union {
+ struct {
+ uint16_t rx_packets;
+ uint16_t rx_time_us;
+ uint16_t tx_packets;
+ uint16_t tx_time_us;
+ } data;
+ uint64_t word;
+} nx_nic_intr_coalesce_data_t;
+
+typedef struct {
+ uint16_t stats_time_us;
+ uint16_t rate_sample_time;
+ uint16_t flags;
+ uint16_t rsvd_1;
+ uint32_t low_threshold;
+ uint32_t high_threshold;
+ nx_nic_intr_coalesce_data_t normal;
+ nx_nic_intr_coalesce_data_t low;
+ nx_nic_intr_coalesce_data_t high;
+ nx_nic_intr_coalesce_data_t irq;
+} nx_nic_intr_coalesce_t;
+
+typedef struct {
+ u64 qhdr;
+ u64 req_hdr;
+ u64 words[6];
+} nx_nic_req_t;
+
+typedef struct {
+ u8 op;
+ u8 tag;
+ u8 mac_addr[6];
+} nx_mac_req_t;
+
+#define MAX_PENDING_DESC_BLOCK_SIZE 64
+
+#define NETXEN_NIC_MSI_ENABLED 0x02
+#define NETXEN_NIC_MSIX_ENABLED 0x04
+#define NETXEN_IS_MSI_FAMILY(adapter) \
+ ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED))
+
+#define MSIX_ENTRIES_PER_ADAPTER 8
+#define NETXEN_MSIX_TBL_SPACE 8192
+#define NETXEN_PCI_REG_MSIX_TBL 0x44
+
+#define NETXEN_DB_MAPSIZE_BYTES 0x1000
+
+#define NETXEN_NETDEV_WEIGHT 120
+#define NETXEN_ADAPTER_UP_MAGIC 777
+#define NETXEN_NIC_PEG_TUNE 0
struct netxen_dummy_dma {
void *addr;
@@ -854,46 +1207,65 @@ struct netxen_dummy_dma {
struct netxen_adapter {
struct netxen_hardware_context ahw;
- struct netxen_adapter *master;
struct net_device *netdev;
struct pci_dev *pdev;
+ int pci_using_dac;
struct napi_struct napi;
struct net_device_stats net_stats;
- unsigned char mac_addr[ETH_ALEN];
int mtu;
int portnum;
u8 physical_port;
+ u16 tx_context_id;
+
+ uint8_t mc_enabled;
+ uint8_t max_mc_count;
+ nx_mac_list_t *mac_list;
+
+ struct netxen_legacy_intr_set legacy_intr;
+ u32 crb_intr_mask;
struct work_struct watchdog_task;
struct timer_list watchdog_timer;
struct work_struct tx_timeout_task;
u32 curr_window;
+ u32 crb_win;
+ rwlock_t adapter_lock;
+
+ uint64_t dma_mask;
u32 cmd_producer;
__le32 *cmd_consumer;
u32 last_cmd_consumer;
+ u32 crb_addr_cmd_producer;
+ u32 crb_addr_cmd_consumer;
u32 max_tx_desc_count;
u32 max_rx_desc_count;
u32 max_jumbo_rx_desc_count;
u32 max_lro_rx_desc_count;
+ int max_rds_rings;
+
u32 flags;
u32 irq;
int driver_mismatch;
u32 temp;
+ u32 fw_major;
+
+ u8 msix_supported;
+ u8 max_possible_rss_rings;
+ struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER];
+
struct netxen_adapter_stats stats;
- u16 portno;
u16 link_speed;
u16 link_duplex;
u16 state;
u16 link_autoneg;
int rx_csum;
int status;
- spinlock_t stats_lock;
struct netxen_cmd_buffer *cmd_buf_arr; /* Command buffers for xmit */
@@ -905,25 +1277,33 @@ struct netxen_adapter {
int is_up;
struct netxen_dummy_dma dummy_dma;
+ nx_nic_intr_coalesce_t coal;
/* Context interface shared between card and host */
struct netxen_ring_ctx *ctx_desc;
- struct pci_dev *ctx_desc_pdev;
dma_addr_t ctx_desc_phys_addr;
int intr_scheme;
int msi_mode;
int (*enable_phy_interrupts) (struct netxen_adapter *);
int (*disable_phy_interrupts) (struct netxen_adapter *);
- void (*handle_phy_intr) (struct netxen_adapter *);
int (*macaddr_set) (struct netxen_adapter *, netxen_ethernet_macaddr_t);
int (*set_mtu) (struct netxen_adapter *, int);
int (*set_promisc) (struct netxen_adapter *, netxen_niu_prom_mode_t);
- int (*unset_promisc) (struct netxen_adapter *, netxen_niu_prom_mode_t);
int (*phy_read) (struct netxen_adapter *, long reg, u32 *);
int (*phy_write) (struct netxen_adapter *, long reg, u32 val);
int (*init_port) (struct netxen_adapter *, int);
- void (*init_niu) (struct netxen_adapter *);
int (*stop_port) (struct netxen_adapter *);
+
+ int (*hw_read_wx)(struct netxen_adapter *, ulong, void *, int);
+ int (*hw_write_wx)(struct netxen_adapter *, ulong, void *, int);
+ 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);
+ void (*pci_write_normalize)(struct netxen_adapter *, u64, u32);
+ u32 (*pci_read_normalize)(struct netxen_adapter *, u64);
+ unsigned long (*pci_set_window)(struct netxen_adapter *,
+ unsigned long long);
}; /* netxen_adapter structure */
/*
@@ -988,8 +1368,6 @@ 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);
-void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter);
-void netxen_nic_gbe_handle_phy_intr(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,
@@ -998,27 +1376,61 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
/* Functions available from netxen_nic_hw.c */
int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);
int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu);
-void netxen_nic_init_niu_gb(struct netxen_adapter *adapter);
-void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw);
void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val);
int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off);
void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value);
-void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value);
+void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value);
+void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value);
+void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value);
int netxen_nic_get_board_info(struct netxen_adapter *adapter);
-int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
- int len);
-int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
- int len);
+
+int netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len);
+int netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len);
+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);
+
+int netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len);
+int netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len);
+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);
void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
unsigned long off, int data);
+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_phantom_init(struct netxen_adapter *adapter, int pegtune_val);
+int netxen_receive_peg_ready(struct netxen_adapter *adapter);
int netxen_load_firmware(struct netxen_adapter *adapter);
int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose);
+
int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp);
int netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr,
u8 *bytes, size_t size);
@@ -1032,33 +1444,43 @@ void netxen_halt_pegs(struct netxen_adapter *adapter);
int netxen_rom_se(struct netxen_adapter *adapter, int addr);
-/* Functions from netxen_nic_isr.c */
-void netxen_initialize_adapter_sw(struct netxen_adapter *adapter);
-void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
- struct pci_dev **used_dev);
+int netxen_alloc_sw_resources(struct netxen_adapter *adapter);
+void netxen_free_sw_resources(struct netxen_adapter *adapter);
+
+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_free_hw_resources(struct netxen_adapter *adapter);
void netxen_tso_check(struct netxen_adapter *adapter,
struct cmd_desc_type0 *desc, struct sk_buff *skb);
-int netxen_nic_hw_resources(struct netxen_adapter *adapter);
void netxen_nic_clear_stats(struct netxen_adapter *adapter);
void netxen_watchdog_task(struct work_struct *work);
void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
u32 ringid);
int netxen_process_cmd_ring(struct netxen_adapter *adapter);
u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
-void netxen_nic_set_multi(struct net_device *netdev);
+void netxen_p2_nic_set_multi(struct net_device *netdev);
+void netxen_p3_nic_set_multi(struct net_device *netdev);
+int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
+
+u32 nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, u32 mtu);
int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
+
int netxen_nic_set_mac(struct net_device *netdev, void *p);
struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);
+void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
+ uint32_t crb_producer);
/*
* NetXen Board information
*/
-#define NETXEN_MAX_SHORT_NAME 16
+#define NETXEN_MAX_SHORT_NAME 32
struct netxen_brdinfo {
netxen_brdtype_t brdtype; /* type of board */
long ports; /* max no of physical ports */
@@ -1072,6 +1494,17 @@ static const struct netxen_brdinfo netxen_boards[] = {
{NETXEN_BRDTYPE_P2_SB31_10G, 1, "XGb XFP"},
{NETXEN_BRDTYPE_P2_SB35_4G, 4, "Quad Gb"},
{NETXEN_BRDTYPE_P2_SB31_2G, 2, "Dual Gb"},
+ {NETXEN_BRDTYPE_P3_REF_QG, 4, "Reference Quad Gig "},
+ {NETXEN_BRDTYPE_P3_HMEZ, 2, "Dual XGb HMEZ"},
+ {NETXEN_BRDTYPE_P3_10G_CX4_LP, 2, "Dual XGb CX4 LP"},
+ {NETXEN_BRDTYPE_P3_4_GB, 4, "Quad Gig LP"},
+ {NETXEN_BRDTYPE_P3_IMEZ, 2, "Dual XGb IMEZ"},
+ {NETXEN_BRDTYPE_P3_10G_SFP_PLUS, 2, "Dual XGb SFP+ LP"},
+ {NETXEN_BRDTYPE_P3_10000_BASE_T, 1, "XGB 10G BaseT LP"},
+ {NETXEN_BRDTYPE_P3_XG_LOM, 2, "Dual XGb LOM"},
+ {NETXEN_BRDTYPE_P3_4_GB_MM, 4, "Quad GB - March Madness"},
+ {NETXEN_BRDTYPE_P3_10G_CX4, 2, "Reference Dual CX4 Option"},
+ {NETXEN_BRDTYPE_P3_10G_XFP, 1, "Reference Single XFP Option"}
};
#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(netxen_boards)
@@ -1097,7 +1530,7 @@ dma_watchdog_shutdown_request(struct netxen_adapter *adapter)
u32 ctrl;
/* check if already inactive */
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
printk(KERN_ERR "failed to read dma watchdog status\n");
@@ -1117,7 +1550,7 @@ dma_watchdog_shutdown_poll_result(struct netxen_adapter *adapter)
{
u32 ctrl;
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
printk(KERN_ERR "failed to read dma watchdog status\n");
@@ -1129,7 +1562,7 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter)
{
u32 ctrl;
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
printk(KERN_ERR "failed to read dma watchdog status\n");
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
new file mode 100644
index 00000000000..64babc59e69
--- /dev/null
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -0,0 +1,710 @@
+/*
+ * Copyright (C) 2003 - 2008 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,
+ * 3965 Freedom Circle, Fourth floor,
+ * Santa Clara, CA 95054
+ *
+ */
+
+#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 */
+ netxen_nic_read_w0(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM5_LOCK), &done);
+
+ 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
+ netxen_nic_write_w1(adapter,
+ NETXEN_API_LOCK_ID, NX_OS_API_LOCK_DRIVER);
+#endif
+ return 0;
+}
+
+static int
+netxen_api_unlock(struct netxen_adapter *adapter)
+{
+ u32 val;
+
+ /* Release PCIE HW semaphore5 */
+ netxen_nic_read_w0(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM5_UNLOCK), &val);
+ return 0;
+}
+
+static u32
+netxen_poll_rsp(struct netxen_adapter *adapter)
+{
+ u32 raw_rsp, rsp = NX_CDRP_RSP_OK;
+ int timeout = 0;
+
+ do {
+ /* give atleast 1ms for firmware to respond */
+ msleep(1);
+
+ if (++timeout > NX_OS_CRB_RETRY_COUNT)
+ return NX_CDRP_RSP_TIMEOUT;
+
+ netxen_nic_read_w1(adapter, NX_CDRP_CRB_OFFSET,
+ &raw_rsp);
+
+ rsp = le32_to_cpu(raw_rsp);
+ } while (!NX_CDRP_IS_RSP(rsp));
+
+ return rsp;
+}
+
+static u32
+netxen_issue_cmd(struct netxen_adapter *adapter,
+ u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd)
+{
+ u32 rsp;
+ u32 signature = 0;
+ u32 rcode = NX_RCODE_SUCCESS;
+
+ signature = NX_CDRP_SIGNATURE_MAKE(pci_fn, version);
+
+ /* Acquire semaphore before accessing CRB */
+ if (netxen_api_lock(adapter))
+ return NX_RCODE_TIMEOUT;
+
+ netxen_nic_write_w1(adapter, NX_SIGN_CRB_OFFSET,
+ cpu_to_le32(signature));
+
+ netxen_nic_write_w1(adapter, NX_ARG1_CRB_OFFSET,
+ cpu_to_le32(arg1));
+
+ netxen_nic_write_w1(adapter, NX_ARG2_CRB_OFFSET,
+ cpu_to_le32(arg2));
+
+ netxen_nic_write_w1(adapter, NX_ARG3_CRB_OFFSET,
+ cpu_to_le32(arg3));
+
+ netxen_nic_write_w1(adapter, NX_CDRP_CRB_OFFSET,
+ cpu_to_le32(NX_CDRP_FORM_CMD(cmd)));
+
+ rsp = netxen_poll_rsp(adapter);
+
+ if (rsp == NX_CDRP_RSP_TIMEOUT) {
+ printk(KERN_ERR "%s: card response timeout.\n",
+ netxen_nic_driver_name);
+
+ rcode = NX_RCODE_TIMEOUT;
+ } else if (rsp == NX_CDRP_RSP_FAIL) {
+ netxen_nic_read_w1(adapter, NX_ARG1_CRB_OFFSET, &rcode);
+ rcode = le32_to_cpu(rcode);
+
+ printk(KERN_ERR "%s: failed card response code:0x%x\n",
+ netxen_nic_driver_name, rcode);
+ }
+
+ /* Release semaphore */
+ netxen_api_unlock(adapter);
+
+ return rcode;
+}
+
+u32
+nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, u32 mtu)
+{
+ u32 rcode = NX_RCODE_SUCCESS;
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+
+ if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE)
+ rcode = netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ recv_ctx->context_id,
+ mtu,
+ 0,
+ NX_CDRP_CMD_SET_MTU);
+
+ return rcode;
+}
+
+static int
+nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
+{
+ void *addr;
+ nx_hostrq_rx_ctx_t *prq;
+ nx_cardrsp_rx_ctx_t *prsp;
+ nx_hostrq_rds_ring_t *prq_rds;
+ nx_hostrq_sds_ring_t *prq_sds;
+ nx_cardrsp_rds_ring_t *prsp_rds;
+ nx_cardrsp_sds_ring_t *prsp_sds;
+ struct nx_host_rds_ring *rds_ring;
+
+ dma_addr_t hostrq_phys_addr, cardrsp_phys_addr;
+ u64 phys_addr;
+
+ int i, nrds_rings, nsds_rings;
+ size_t rq_size, rsp_size;
+ u32 cap, reg;
+
+ int err;
+
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+
+ /* only one sds ring for now */
+ nrds_rings = adapter->max_rds_rings;
+ nsds_rings = 1;
+
+ rq_size =
+ SIZEOF_HOSTRQ_RX(nx_hostrq_rx_ctx_t, nrds_rings, nsds_rings);
+ rsp_size =
+ SIZEOF_CARDRSP_RX(nx_cardrsp_rx_ctx_t, nrds_rings, nsds_rings);
+
+ addr = pci_alloc_consistent(adapter->pdev,
+ rq_size, &hostrq_phys_addr);
+ if (addr == NULL)
+ return -ENOMEM;
+ prq = (nx_hostrq_rx_ctx_t *)addr;
+
+ addr = pci_alloc_consistent(adapter->pdev,
+ rsp_size, &cardrsp_phys_addr);
+ if (addr == NULL) {
+ err = -ENOMEM;
+ goto out_free_rq;
+ }
+ prsp = (nx_cardrsp_rx_ctx_t *)addr;
+
+ prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr);
+
+ cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN);
+ cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS);
+
+ prq->capabilities[0] = cpu_to_le32(cap);
+ prq->host_int_crb_mode =
+ cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED);
+ prq->host_rds_crb_mode =
+ cpu_to_le32(NX_HOST_RDS_CRB_MODE_UNIQUE);
+
+ prq->num_rds_rings = cpu_to_le16(nrds_rings);
+ prq->num_sds_rings = cpu_to_le16(nsds_rings);
+ prq->rds_ring_offset = 0;
+ prq->sds_ring_offset = prq->rds_ring_offset +
+ (sizeof(nx_hostrq_rds_ring_t) * nrds_rings);
+
+ prq_rds = (nx_hostrq_rds_ring_t *)(prq->data + prq->rds_ring_offset);
+
+ for (i = 0; i < nrds_rings; i++) {
+
+ rds_ring = &recv_ctx->rds_rings[i];
+
+ prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr);
+ prq_rds[i].ring_size = cpu_to_le32(rds_ring->max_rx_desc_count);
+ prq_rds[i].ring_kind = cpu_to_le32(i);
+ prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size);
+ }
+
+ prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + prq->sds_ring_offset);
+
+ prq_sds[0].host_phys_addr =
+ cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
+ prq_sds[0].ring_size = cpu_to_le32(adapter->max_rx_desc_count);
+ /* only one msix vector for now */
+ prq_sds[0].msi_index = cpu_to_le32(0);
+
+ /* now byteswap offsets */
+ prq->rds_ring_offset = cpu_to_le32(prq->rds_ring_offset);
+ prq->sds_ring_offset = cpu_to_le32(prq->sds_ring_offset);
+
+ phys_addr = hostrq_phys_addr;
+ err = netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ (u32)(phys_addr >> 32),
+ (u32)(phys_addr & 0xffffffff),
+ rq_size,
+ NX_CDRP_CMD_CREATE_RX_CTX);
+ if (err) {
+ printk(KERN_WARNING
+ "Failed to create rx ctx in firmware%d\n", err);
+ goto out_free_rsp;
+ }
+
+
+ prsp_rds = ((nx_cardrsp_rds_ring_t *)
+ &prsp->data[prsp->rds_ring_offset]);
+
+ for (i = 0; i < le32_to_cpu(prsp->num_rds_rings); i++) {
+ 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);
+ }
+
+ prsp_sds = ((nx_cardrsp_sds_ring_t *)
+ &prsp->data[prsp->sds_ring_offset]);
+ reg = le32_to_cpu(prsp_sds[0].host_consumer_crb);
+ recv_ctx->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200);
+
+ reg = le32_to_cpu(prsp_sds[0].interrupt_crb);
+ adapter->crb_intr_mask = NETXEN_NIC_REG(reg - 0x200);
+
+ recv_ctx->state = le32_to_cpu(prsp->host_ctx_state);
+ recv_ctx->context_id = le16_to_cpu(prsp->context_id);
+ recv_ctx->virt_port = le16_to_cpu(prsp->virt_port);
+
+out_free_rsp:
+ pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr);
+out_free_rq:
+ pci_free_consistent(adapter->pdev, rq_size, prq, hostrq_phys_addr);
+ return err;
+}
+
+static void
+nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0];
+
+ if (netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ recv_ctx->context_id,
+ NX_DESTROY_CTX_RESET,
+ 0,
+ NX_CDRP_CMD_DESTROY_RX_CTX)) {
+
+ printk(KERN_WARNING
+ "%s: Failed to destroy rx ctx in firmware\n",
+ netxen_nic_driver_name);
+ }
+}
+
+static int
+nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter)
+{
+ nx_hostrq_tx_ctx_t *prq;
+ nx_hostrq_cds_ring_t *prq_cds;
+ nx_cardrsp_tx_ctx_t *prsp;
+ void *rq_addr, *rsp_addr;
+ size_t rq_size, rsp_size;
+ u32 temp;
+ int err = 0;
+ u64 offset, phys_addr;
+ dma_addr_t rq_phys_addr, rsp_phys_addr;
+
+ rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t);
+ rq_addr = pci_alloc_consistent(adapter->pdev,
+ rq_size, &rq_phys_addr);
+ if (!rq_addr)
+ return -ENOMEM;
+
+ rsp_size = SIZEOF_CARDRSP_TX(nx_cardrsp_tx_ctx_t);
+ rsp_addr = pci_alloc_consistent(adapter->pdev,
+ rsp_size, &rsp_phys_addr);
+ if (!rsp_addr) {
+ err = -ENOMEM;
+ goto out_free_rq;
+ }
+
+ memset(rq_addr, 0, rq_size);
+ prq = (nx_hostrq_tx_ctx_t *)rq_addr;
+
+ memset(rsp_addr, 0, rsp_size);
+ prsp = (nx_cardrsp_tx_ctx_t *)rsp_addr;
+
+ prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr);
+
+ temp = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN | NX_CAP0_LSO);
+ prq->capabilities[0] = cpu_to_le32(temp);
+
+ prq->host_int_crb_mode =
+ cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED);
+
+ prq->interrupt_ctl = 0;
+ prq->msi_index = 0;
+
+ prq->dummy_dma_addr = cpu_to_le64(adapter->dummy_dma.phys_addr);
+
+ offset = adapter->ctx_desc_phys_addr+sizeof(struct netxen_ring_ctx);
+ prq->cmd_cons_dma_addr = cpu_to_le64(offset);
+
+ prq_cds = &prq->cds_ring;
+
+ prq_cds->host_phys_addr =
+ cpu_to_le64(adapter->ahw.cmd_desc_phys_addr);
+
+ prq_cds->ring_size = cpu_to_le32(adapter->max_tx_desc_count);
+
+ phys_addr = rq_phys_addr;
+ err = netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ (u32)(phys_addr >> 32),
+ ((u32)phys_addr & 0xffffffff),
+ rq_size,
+ NX_CDRP_CMD_CREATE_TX_CTX);
+
+ if (err == NX_RCODE_SUCCESS) {
+ temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
+ adapter->crb_addr_cmd_producer =
+ NETXEN_NIC_REG(temp - 0x200);
+#if 0
+ adapter->tx_state =
+ le32_to_cpu(prsp->host_ctx_state);
+#endif
+ adapter->tx_context_id =
+ le16_to_cpu(prsp->context_id);
+ } else {
+ printk(KERN_WARNING
+ "Failed to create tx ctx in firmware%d\n", err);
+ err = -EIO;
+ }
+
+ pci_free_consistent(adapter->pdev, rsp_size, rsp_addr, rsp_phys_addr);
+
+out_free_rq:
+ pci_free_consistent(adapter->pdev, rq_size, rq_addr, rq_phys_addr);
+
+ return err;
+}
+
+static void
+nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter)
+{
+ if (netxen_issue_cmd(adapter,
+ adapter->ahw.pci_func,
+ NXHAL_VERSION,
+ adapter->tx_context_id,
+ NX_DESTROY_CTX_RESET,
+ 0,
+ NX_CDRP_CMD_DESTROY_TX_CTX)) {
+
+ printk(KERN_WARNING
+ "%s: Failed to destroy tx ctx in firmware\n",
+ netxen_nic_driver_name);
+ }
+}
+
+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)},
+ {NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)},
+ {NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)}
+};
+
+#define CRB_CTX_ADDR_REG_LO(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][0])
+#define CRB_CTX_ADDR_REG_HI(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][2])
+#define CRB_CTX_SIGNATURE_REG(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][1])
+
+#define lower32(x) ((u32)((x) & 0xffffffff))
+#define upper32(x) ((u32)(((u64)(x) >> 32) & 0xffffffff))
+
+static struct netxen_recv_crb recv_crb_registers[] = {
+ /* Instance 0 */
+ {
+ /* crb_rcv_producer: */
+ {
+ NETXEN_NIC_REG(0x100),
+ /* Jumbo frames */
+ NETXEN_NIC_REG(0x110),
+ /* LRO */
+ NETXEN_NIC_REG(0x120)
+ },
+ /* crb_sts_consumer: */
+ NETXEN_NIC_REG(0x138),
+ },
+ /* Instance 1 */
+ {
+ /* crb_rcv_producer: */
+ {
+ NETXEN_NIC_REG(0x144),
+ /* Jumbo frames */
+ NETXEN_NIC_REG(0x154),
+ /* LRO */
+ NETXEN_NIC_REG(0x164)
+ },
+ /* crb_sts_consumer: */
+ NETXEN_NIC_REG(0x17c),
+ },
+ /* Instance 2 */
+ {
+ /* crb_rcv_producer: */
+ {
+ NETXEN_NIC_REG(0x1d8),
+ /* Jumbo frames */
+ NETXEN_NIC_REG(0x1f8),
+ /* LRO */
+ NETXEN_NIC_REG(0x208)
+ },
+ /* crb_sts_consumer: */
+ NETXEN_NIC_REG(0x220),
+ },
+ /* Instance 3 */
+ {
+ /* crb_rcv_producer: */
+ {
+ NETXEN_NIC_REG(0x22c),
+ /* Jumbo frames */
+ NETXEN_NIC_REG(0x23c),
+ /* LRO */
+ NETXEN_NIC_REG(0x24c)
+ },
+ /* crb_sts_consumer: */
+ NETXEN_NIC_REG(0x264),
+ },
+};
+
+static int
+netxen_init_old_ctx(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ int ctx, ring;
+ int func_id = adapter->portnum;
+
+ adapter->ctx_desc->cmd_ring_addr =
+ cpu_to_le64(adapter->ahw.cmd_desc_phys_addr);
+ adapter->ctx_desc->cmd_ring_size =
+ cpu_to_le32(adapter->max_tx_desc_count);
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
+ cpu_to_le64(rds_ring->phys_addr);
+ adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
+ cpu_to_le32(rds_ring->max_rx_desc_count);
+ }
+ adapter->ctx_desc->sts_ring_addr =
+ cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
+ adapter->ctx_desc->sts_ring_size =
+ cpu_to_le32(adapter->max_rx_desc_count);
+ }
+
+ adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_LO(func_id),
+ lower32(adapter->ctx_desc_phys_addr));
+ adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_HI(func_id),
+ upper32(adapter->ctx_desc_phys_addr));
+ adapter->pci_write_normalize(adapter, CRB_CTX_SIGNATURE_REG(func_id),
+ NETXEN_CTX_SIGNATURE | func_id);
+ return 0;
+}
+
+static uint32_t sw_int_mask[4] = {
+ CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
+ CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
+};
+
+int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
+{
+ struct netxen_hardware_context *hw = &adapter->ahw;
+ u32 state = 0;
+ void *addr;
+ int err = 0;
+ int ctx, ring;
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+
+ err = netxen_receive_peg_ready(adapter);
+ if (err) {
+ printk(KERN_ERR "Rcv Peg initialization not complete:%x.\n",
+ state);
+ return err;
+ }
+
+ addr = pci_alloc_consistent(adapter->pdev,
+ sizeof(struct netxen_ring_ctx) + sizeof(uint32_t),
+ &adapter->ctx_desc_phys_addr);
+
+ if (addr == NULL) {
+ DPRINTK(ERR, "failed to allocate hw context\n");
+ return -ENOMEM;
+ }
+ memset(addr, 0, sizeof(struct netxen_ring_ctx));
+ adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
+ adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum);
+ adapter->ctx_desc->cmd_consumer_offset =
+ cpu_to_le64(adapter->ctx_desc_phys_addr +
+ sizeof(struct netxen_ring_ctx));
+ adapter->cmd_consumer =
+ (__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx));
+
+ /* cmd desc ring */
+ addr = pci_alloc_consistent(adapter->pdev,
+ sizeof(struct cmd_desc_type0) *
+ adapter->max_tx_desc_count,
+ &hw->cmd_desc_phys_addr);
+
+ if (addr == NULL) {
+ printk(KERN_ERR "%s failed to allocate tx desc ring\n",
+ netxen_nic_driver_name);
+ return -ENOMEM;
+ }
+
+ hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ /* rx desc ring */
+ rds_ring = &recv_ctx->rds_rings[ring];
+ addr = pci_alloc_consistent(adapter->pdev,
+ RCV_DESC_RINGSIZE,
+ &rds_ring->phys_addr);
+ if (addr == NULL) {
+ printk(KERN_ERR "%s failed to allocate rx "
+ "desc ring[%d]\n",
+ netxen_nic_driver_name, ring);
+ err = -ENOMEM;
+ goto err_out_free;
+ }
+ rds_ring->desc_head = (struct rcv_desc *)addr;
+
+ if (adapter->fw_major < 4)
+ rds_ring->crb_rcv_producer =
+ recv_crb_registers[adapter->portnum].
+ crb_rcv_producer[ring];
+ }
+
+ /* status desc ring */
+ addr = pci_alloc_consistent(adapter->pdev,
+ STATUS_DESC_RINGSIZE,
+ &recv_ctx->rcv_status_desc_phys_addr);
+ if (addr == NULL) {
+ printk(KERN_ERR "%s failed to allocate sts desc ring\n",
+ netxen_nic_driver_name);
+ err = -ENOMEM;
+ goto err_out_free;
+ }
+ recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
+
+ if (adapter->fw_major < 4)
+ recv_ctx->crb_sts_consumer =
+ recv_crb_registers[adapter->portnum].
+ crb_sts_consumer;
+ }
+
+ if (adapter->fw_major >= 4) {
+ adapter->intr_scheme = INTR_SCHEME_PERPORT;
+ adapter->msi_mode = MSI_MODE_MULTIFUNC;
+
+ err = nx_fw_cmd_create_rx_ctx(adapter);
+ if (err)
+ goto err_out_free;
+ err = nx_fw_cmd_create_tx_ctx(adapter);
+ if (err)
+ goto err_out_free;
+ } else {
+
+ adapter->intr_scheme = adapter->pci_read_normalize(adapter,
+ CRB_NIC_CAPABILITIES_FW);
+ adapter->msi_mode = adapter->pci_read_normalize(adapter,
+ CRB_NIC_MSI_MODE_FW);
+ adapter->crb_intr_mask = sw_int_mask[adapter->portnum];
+
+ err = netxen_init_old_ctx(adapter);
+ if (err) {
+ netxen_free_hw_resources(adapter);
+ return err;
+ }
+
+ }
+
+ return 0;
+
+err_out_free:
+ netxen_free_hw_resources(adapter);
+ return err;
+}
+
+void netxen_free_hw_resources(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ int ctx, ring;
+
+ if (adapter->fw_major >= 4) {
+ nx_fw_cmd_destroy_tx_ctx(adapter);
+ nx_fw_cmd_destroy_rx_ctx(adapter);
+ }
+
+ if (adapter->ctx_desc != NULL) {
+ pci_free_consistent(adapter->pdev,
+ sizeof(struct netxen_ring_ctx) +
+ sizeof(uint32_t),
+ adapter->ctx_desc,
+ adapter->ctx_desc_phys_addr);
+ adapter->ctx_desc = NULL;
+ }
+
+ if (adapter->ahw.cmd_desc_head != NULL) {
+ pci_free_consistent(adapter->pdev,
+ sizeof(struct cmd_desc_type0) *
+ adapter->max_tx_desc_count,
+ adapter->ahw.cmd_desc_head,
+ adapter->ahw.cmd_desc_phys_addr);
+ adapter->ahw.cmd_desc_head = NULL;
+ }
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+
+ if (rds_ring->desc_head != NULL) {
+ pci_free_consistent(adapter->pdev,
+ RCV_DESC_RINGSIZE,
+ rds_ring->desc_head,
+ rds_ring->phys_addr);
+ rds_ring->desc_head = NULL;
+ }
+ }
+
+ if (recv_ctx->rcv_status_desc_head != NULL) {
+ pci_free_consistent(adapter->pdev,
+ STATUS_DESC_RINGSIZE,
+ recv_ctx->rcv_status_desc_head,
+ recv_ctx->rcv_status_desc_phys_addr);
+ recv_ctx->rcv_status_desc_head = NULL;
+ }
+ }
+}
+
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index 723487bf200..48ee06b6f4e 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -93,17 +93,21 @@ 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);
- fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_FW_VERSION_MAJOR));
- fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_FW_VERSION_MINOR));
- fw_build = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ fw_major = adapter->pci_read_normalize(adapter,
+ NETXEN_FW_VERSION_MAJOR);
+ fw_minor = adapter->pci_read_normalize(adapter,
+ NETXEN_FW_VERSION_MINOR);
+ fw_build = adapter->pci_read_normalize(adapter,
+ NETXEN_FW_VERSION_SUB);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build);
strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
@@ -159,9 +163,16 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
switch ((netxen_brdtype_t) boardinfo->board_type) {
case NETXEN_BRDTYPE_P2_SB35_4G:
case NETXEN_BRDTYPE_P2_SB31_2G:
+ case NETXEN_BRDTYPE_P3_REF_QG:
+ case NETXEN_BRDTYPE_P3_4_GB:
+ case NETXEN_BRDTYPE_P3_4_GB_MM:
+ case NETXEN_BRDTYPE_P3_10000_BASE_T:
+
ecmd->supported |= SUPPORTED_Autoneg;
ecmd->advertising |= ADVERTISED_Autoneg;
case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+ case NETXEN_BRDTYPE_P3_10G_CX4:
+ case NETXEN_BRDTYPE_P3_10G_CX4_LP:
ecmd->supported |= SUPPORTED_TP;
ecmd->advertising |= ADVERTISED_TP;
ecmd->port = PORT_TP;
@@ -171,12 +182,17 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
break;
case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
+ case NETXEN_BRDTYPE_P3_IMEZ:
+ case NETXEN_BRDTYPE_P3_XG_LOM:
+ case NETXEN_BRDTYPE_P3_HMEZ:
ecmd->supported |= SUPPORTED_MII;
ecmd->advertising |= ADVERTISED_MII;
ecmd->port = PORT_FIBRE;
ecmd->autoneg = AUTONEG_DISABLE;
break;
case NETXEN_BRDTYPE_P2_SB31_10G:
+ case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
+ case NETXEN_BRDTYPE_P3_10G_XFP:
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
ecmd->port = PORT_FIBRE;
@@ -349,19 +365,18 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
{
struct netxen_adapter *adapter = netdev_priv(dev);
__u32 mode, *regs_buff = p;
- void __iomem *addr;
int i, window;
memset(p, 0, NETXEN_NIC_REGS_LEN);
regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
(adapter->pdev)->device;
/* which mode */
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_MODE, &regs_buff[0]);
+ adapter->hw_read_wx(adapter, NETXEN_NIU_MODE, &regs_buff[0], 4);
mode = regs_buff[0];
/* Common registers to all the modes */
- NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER,
- &regs_buff[2]);
+ adapter->hw_read_wx(adapter,
+ NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER, &regs_buff[2], 4);
/* GB/XGB Mode */
mode = (mode / 2) - 1;
window = 0;
@@ -372,9 +387,9 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
window = adapter->physical_port *
NETXEN_NIC_PORT_WINDOW;
- NETXEN_NIC_LOCKED_READ_REG(niu_registers[mode].
- reg[i - 3] + window,
- &regs_buff[i]);
+ adapter->hw_read_wx(adapter,
+ niu_registers[mode].reg[i - 3] + window,
+ &regs_buff[i], 4);
}
}
@@ -398,7 +413,7 @@ static u32 netxen_nic_test_link(struct net_device *dev)
return !val;
}
} else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
- val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
+ val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
return (val == XG_LINK_UP) ? 0 : 1;
}
return -EIO;
@@ -427,6 +442,7 @@ netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
return 0;
}
+#if 0
static int
netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
u8 * bytes)
@@ -447,7 +463,6 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
}
printk(KERN_INFO "%s: flash unlocked. \n",
netxen_nic_driver_name);
- last_schedule_time = jiffies;
ret = netxen_flash_erase_secondary(adapter);
if (ret != FLASH_SUCCESS) {
printk(KERN_ERR "%s: Flash erase failed.\n",
@@ -497,6 +512,7 @@ netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
return netxen_rom_fast_write_words(adapter, offset, bytes, eeprom->len);
}
+#endif /* 0 */
static void
netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
@@ -508,9 +524,9 @@ netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
ring->rx_jumbo_pending = 0;
for (i = 0; i < MAX_RCV_CTX; ++i) {
ring->rx_pending += adapter->recv_ctx[i].
- rcv_desc[RCV_DESC_NORMAL_CTXID].max_rx_desc_count;
+ rds_rings[RCV_DESC_NORMAL_CTXID].max_rx_desc_count;
ring->rx_jumbo_pending += adapter->recv_ctx[i].
- rcv_desc[RCV_DESC_JUMBO_CTXID].max_rx_desc_count;
+ rds_rings[RCV_DESC_JUMBO_CTXID].max_rx_desc_count;
}
ring->tx_pending = adapter->max_tx_desc_count;
@@ -655,7 +671,7 @@ static int netxen_nic_reg_test(struct net_device *dev)
data_written = (u32)0xa5a5a5a5;
netxen_nic_reg_write(adapter, CRB_SCRATCHPAD_TEST, data_written);
- data_read = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_SCRATCHPAD_TEST));
+ data_read = adapter->pci_read_normalize(adapter, CRB_SCRATCHPAD_TEST);
if (data_written != data_read)
return 1;
@@ -736,6 +752,117 @@ static int netxen_nic_set_rx_csum(struct net_device *dev, u32 data)
return 0;
}
+static u32 netxen_nic_get_tso(struct net_device *dev)
+{
+ struct netxen_adapter *adapter = netdev_priv(dev);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0;
+
+ return (dev->features & NETIF_F_TSO) != 0;
+}
+
+static int netxen_nic_set_tso(struct net_device *dev, u32 data)
+{
+ if (data) {
+ struct netxen_adapter *adapter = netdev_priv(dev);
+
+ dev->features |= NETIF_F_TSO;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ dev->features |= NETIF_F_TSO6;
+ } else
+ dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+
+ return 0;
+}
+
+/*
+ * Set the coalescing parameters. Currently only normal is supported.
+ * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
+ * firmware coalescing to default.
+ */
+static int netxen_set_intr_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ethcoal)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+
+ if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ return -EINVAL;
+
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ return -EINVAL;
+
+ /*
+ * Return Error if unsupported values or
+ * unsupported parameters are set.
+ */
+ if (ethcoal->rx_coalesce_usecs > 0xffff ||
+ ethcoal->rx_max_coalesced_frames > 0xffff ||
+ ethcoal->tx_coalesce_usecs > 0xffff ||
+ ethcoal->tx_max_coalesced_frames > 0xffff ||
+ ethcoal->rx_coalesce_usecs_irq ||
+ ethcoal->rx_max_coalesced_frames_irq ||
+ ethcoal->tx_coalesce_usecs_irq ||
+ ethcoal->tx_max_coalesced_frames_irq ||
+ ethcoal->stats_block_coalesce_usecs ||
+ ethcoal->use_adaptive_rx_coalesce ||
+ ethcoal->use_adaptive_tx_coalesce ||
+ ethcoal->pkt_rate_low ||
+ ethcoal->rx_coalesce_usecs_low ||
+ ethcoal->rx_max_coalesced_frames_low ||
+ ethcoal->tx_coalesce_usecs_low ||
+ ethcoal->tx_max_coalesced_frames_low ||
+ ethcoal->pkt_rate_high ||
+ ethcoal->rx_coalesce_usecs_high ||
+ ethcoal->rx_max_coalesced_frames_high ||
+ ethcoal->tx_coalesce_usecs_high ||
+ ethcoal->tx_max_coalesced_frames_high)
+ return -EINVAL;
+
+ if (!ethcoal->rx_coalesce_usecs ||
+ !ethcoal->rx_max_coalesced_frames) {
+ 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;
+ } else {
+ adapter->coal.flags = 0;
+ adapter->coal.normal.data.rx_time_us =
+ ethcoal->rx_coalesce_usecs;
+ adapter->coal.normal.data.rx_packets =
+ ethcoal->rx_max_coalesced_frames;
+ }
+ adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
+ adapter->coal.normal.data.tx_packets =
+ ethcoal->tx_max_coalesced_frames;
+
+ netxen_config_intr_coalesce(adapter);
+
+ return 0;
+}
+
+static int netxen_get_intr_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *ethcoal)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+
+ if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ return -EINVAL;
+
+ if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
+ return -EINVAL;
+
+ ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
+ ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
+ ethcoal->rx_max_coalesced_frames =
+ adapter->coal.normal.data.rx_packets;
+ ethcoal->tx_max_coalesced_frames =
+ adapter->coal.normal.data.tx_packets;
+
+ return 0;
+}
+
struct ethtool_ops netxen_nic_ethtool_ops = {
.get_settings = netxen_nic_get_settings,
.set_settings = netxen_nic_set_settings,
@@ -745,17 +872,22 @@ struct ethtool_ops netxen_nic_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_eeprom_len = netxen_nic_get_eeprom_len,
.get_eeprom = netxen_nic_get_eeprom,
+#if 0
.set_eeprom = netxen_nic_set_eeprom,
+#endif
.get_ringparam = netxen_nic_get_ringparam,
.get_pauseparam = netxen_nic_get_pauseparam,
.set_pauseparam = netxen_nic_set_pauseparam,
.set_tx_csum = ethtool_op_set_tx_csum,
.set_sg = ethtool_op_set_sg,
- .set_tso = ethtool_op_set_tso,
+ .get_tso = netxen_nic_get_tso,
+ .set_tso = netxen_nic_set_tso,
.self_test = netxen_nic_diag_test,
.get_strings = netxen_nic_get_strings,
.get_ethtool_stats = netxen_nic_get_ethtool_stats,
.get_sset_count = netxen_get_sset_count,
.get_rx_csum = netxen_nic_get_rx_csum,
.set_rx_csum = netxen_nic_set_rx_csum,
+ .get_coalesce = netxen_get_intr_coalesce,
+ .set_coalesce = netxen_set_intr_coalesce,
};
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
index 24d027e29c4..3ce13e451aa 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -126,7 +126,8 @@ enum {
NETXEN_HW_PEGR0_CRB_AGT_ADR,
NETXEN_HW_PEGR1_CRB_AGT_ADR,
NETXEN_HW_PEGR2_CRB_AGT_ADR,
- NETXEN_HW_PEGR3_CRB_AGT_ADR
+ NETXEN_HW_PEGR3_CRB_AGT_ADR,
+ NETXEN_HW_PEGN4_CRB_AGT_ADR
};
/* Hub 5 */
@@ -316,6 +317,8 @@ enum {
((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN2_CRB_AGT_ADR)
#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN3 \
((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN3_CRB_AGT_ADR)
+#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN4 \
+ ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN4_CRB_AGT_ADR)
#define NETXEN_HW_CRB_HUB_AGT_ADR_PGNC \
((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGNC_CRB_AGT_ADR)
#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR0 \
@@ -435,6 +438,7 @@ enum {
#define NETXEN_CRB_ROMUSB \
NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_ROMUSB)
#define NETXEN_CRB_I2Q NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_I2Q)
+#define NETXEN_CRB_SMB NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SMB)
#define NETXEN_CRB_MAX NETXEN_PCI_CRB_WINDOW(64)
#define NETXEN_CRB_PCIX_HOST NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PH)
@@ -446,6 +450,7 @@ enum {
#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)
+#define NETXEN_CRB_QDR_NET NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SN)
#define NETXEN_CRB_PCIX_MD NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PS)
#define NETXEN_CRB_PCIE NETXEN_CRB_PCIX_MD
@@ -461,11 +466,20 @@ enum {
#define ISR_INT_TARGET_MASK_F2 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F2))
#define ISR_INT_TARGET_STATUS_F3 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F3))
#define ISR_INT_TARGET_MASK_F3 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F3))
+#define ISR_INT_TARGET_STATUS_F4 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F4))
+#define ISR_INT_TARGET_MASK_F4 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F4))
+#define ISR_INT_TARGET_STATUS_F5 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F5))
+#define ISR_INT_TARGET_MASK_F5 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F5))
+#define ISR_INT_TARGET_STATUS_F6 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F6))
+#define ISR_INT_TARGET_MASK_F6 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F6))
+#define ISR_INT_TARGET_STATUS_F7 (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F7))
+#define ISR_INT_TARGET_MASK_F7 (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F7))
#define NETXEN_PCI_MAPSIZE 128
#define NETXEN_PCI_DDR_NET (0x00000000UL)
#define NETXEN_PCI_QDR_NET (0x04000000UL)
#define NETXEN_PCI_DIRECT_CRB (0x04400000UL)
+#define NETXEN_PCI_CAMQM (0x04800000UL)
#define NETXEN_PCI_CAMQM_MAX (0x04ffffffUL)
#define NETXEN_PCI_OCM0 (0x05000000UL)
#define NETXEN_PCI_OCM0_MAX (0x050fffffUL)
@@ -474,6 +488,13 @@ enum {
#define NETXEN_PCI_CRBSPACE (0x06000000UL)
#define NETXEN_PCI_128MB_SIZE (0x08000000UL)
#define NETXEN_PCI_32MB_SIZE (0x02000000UL)
+#define NETXEN_PCI_2MB_SIZE (0x00200000UL)
+
+#define NETXEN_PCI_MN_2M (0)
+#define NETXEN_PCI_MS_2M (0x80000)
+#define NETXEN_PCI_OCM0_2M (0x000c0000UL)
+#define NETXEN_PCI_CAMQM_2M_BASE (0x000ff800UL)
+#define NETXEN_PCI_CAMQM_2M_END (0x04800800UL)
#define NETXEN_CRB_CAM NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_CAM)
@@ -484,7 +505,14 @@ enum {
#define NETXEN_ADDR_OCM1 (0x0000000200400000ULL)
#define NETXEN_ADDR_OCM1_MAX (0x00000002004fffffULL)
#define NETXEN_ADDR_QDR_NET (0x0000000300000000ULL)
-#define NETXEN_ADDR_QDR_NET_MAX (0x00000003003fffffULL)
+#define NETXEN_ADDR_QDR_NET_MAX_P2 (0x00000003003fffffULL)
+#define NETXEN_ADDR_QDR_NET_MAX_P3 (0x0000000303ffffffULL)
+
+/*
+ * Register offsets for MN
+ */
+#define NETXEN_MIU_CONTROL (0x000)
+#define NETXEN_MIU_MN_CONTROL (NETXEN_CRB_DDR_NET+NETXEN_MIU_CONTROL)
/* 200ms delay in each loop */
#define NETXEN_NIU_PHY_WAITLEN 200000
@@ -550,6 +578,9 @@ enum {
#define NETXEN_MULTICAST_ADDR_HI_2 (NETXEN_CRB_NIU + 0x1018)
#define NETXEN_MULTICAST_ADDR_HI_3 (NETXEN_CRB_NIU + 0x101c)
+#define NETXEN_UNICAST_ADDR_BASE (NETXEN_CRB_NIU + 0x1080)
+#define NETXEN_MULTICAST_ADDR_BASE (NETXEN_CRB_NIU + 0x1100)
+
#define NETXEN_NIU_GB_MAC_CONFIG_0(I) \
(NETXEN_CRB_NIU + 0x30000 + (I)*0x10000)
#define NETXEN_NIU_GB_MAC_CONFIG_1(I) \
@@ -630,16 +661,76 @@ enum {
#define NETXEN_NIU_XG1_CONTROL_CHAR_CNT (NETXEN_CRB_NIU + 0x80054)
#define NETXEN_NIU_XG1_PAUSE_FRAME_CNT (NETXEN_CRB_NIU + 0x80058)
+/* P3 802.3ap */
+#define NETXEN_NIU_AP_MAC_CONFIG_0(I) (NETXEN_CRB_NIU+0xa0000+(I)*0x10000)
+#define NETXEN_NIU_AP_MAC_CONFIG_1(I) (NETXEN_CRB_NIU+0xa0004+(I)*0x10000)
+#define NETXEN_NIU_AP_MAC_IPG_IFG(I) (NETXEN_CRB_NIU+0xa0008+(I)*0x10000)
+#define NETXEN_NIU_AP_HALF_DUPLEX_CTRL(I) (NETXEN_CRB_NIU+0xa000c+(I)*0x10000)
+#define NETXEN_NIU_AP_MAX_FRAME_SIZE(I) (NETXEN_CRB_NIU+0xa0010+(I)*0x10000)
+#define NETXEN_NIU_AP_TEST_REG(I) (NETXEN_CRB_NIU+0xa001c+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_CONFIG(I) (NETXEN_CRB_NIU+0xa0020+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_COMMAND(I) (NETXEN_CRB_NIU+0xa0024+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_ADDR(I) (NETXEN_CRB_NIU+0xa0028+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_CTRL(I) (NETXEN_CRB_NIU+0xa002c+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_STATUS(I) (NETXEN_CRB_NIU+0xa0030+(I)*0x10000)
+#define NETXEN_NIU_AP_MII_MGMT_INDICATE(I) (NETXEN_CRB_NIU+0xa0034+(I)*0x10000)
+#define NETXEN_NIU_AP_INTERFACE_CTRL(I) (NETXEN_CRB_NIU+0xa0038+(I)*0x10000)
+#define NETXEN_NIU_AP_INTERFACE_STATUS(I) (NETXEN_CRB_NIU+0xa003c+(I)*0x10000)
+#define NETXEN_NIU_AP_STATION_ADDR_0(I) (NETXEN_CRB_NIU+0xa0040+(I)*0x10000)
+#define NETXEN_NIU_AP_STATION_ADDR_1(I) (NETXEN_CRB_NIU+0xa0044+(I)*0x10000)
+
+/*
+ * Register offsets for MN
+ */
+#define MIU_CONTROL (0x000)
+#define MIU_TEST_AGT_CTRL (0x090)
+#define MIU_TEST_AGT_ADDR_LO (0x094)
+#define MIU_TEST_AGT_ADDR_HI (0x098)
+#define MIU_TEST_AGT_WRDATA_LO (0x0a0)
+#define MIU_TEST_AGT_WRDATA_HI (0x0a4)
+#define MIU_TEST_AGT_WRDATA(i) (0x0a0+(4*(i)))
+#define MIU_TEST_AGT_RDDATA_LO (0x0a8)
+#define MIU_TEST_AGT_RDDATA_HI (0x0ac)
+#define MIU_TEST_AGT_RDDATA(i) (0x0a8+(4*(i)))
+#define MIU_TEST_AGT_ADDR_MASK 0xfffffff8
+#define MIU_TEST_AGT_UPPER_ADDR(off) (0)
+
+/* MIU_TEST_AGT_CTRL flags. work for SIU as well */
+#define MIU_TA_CTL_START 1
+#define MIU_TA_CTL_ENABLE 2
+#define MIU_TA_CTL_WRITE 4
+#define MIU_TA_CTL_BUSY 8
+
+#define SIU_TEST_AGT_CTRL (0x060)
+#define SIU_TEST_AGT_ADDR_LO (0x064)
+#define SIU_TEST_AGT_ADDR_HI (0x078)
+#define SIU_TEST_AGT_WRDATA_LO (0x068)
+#define SIU_TEST_AGT_WRDATA_HI (0x06c)
+#define SIU_TEST_AGT_WRDATA(i) (0x068+(4*(i)))
+#define SIU_TEST_AGT_RDDATA_LO (0x070)
+#define SIU_TEST_AGT_RDDATA_HI (0x074)
+#define SIU_TEST_AGT_RDDATA(i) (0x070+(4*(i)))
+
+#define SIU_TEST_AGT_ADDR_MASK 0x3ffff8
+#define SIU_TEST_AGT_UPPER_ADDR(off) ((off)>>22)
+
/* XG Link status */
#define XG_LINK_UP 0x10
#define XG_LINK_DOWN 0x20
+#define XG_LINK_UP_P3 0x01
+#define XG_LINK_DOWN_P3 0x02
+#define XG_LINK_STATE_P3_MASK 0xf
+#define XG_LINK_STATE_P3(pcifn,val) \
+ (((val) >> ((pcifn) * 4)) & XG_LINK_STATE_P3_MASK)
+
#define NETXEN_CAM_RAM_BASE (NETXEN_CRB_CAM + 0x02000)
#define NETXEN_CAM_RAM(reg) (NETXEN_CAM_RAM_BASE + (reg))
#define NETXEN_FW_VERSION_MAJOR (NETXEN_CAM_RAM(0x150))
#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_CRB_WIN_LOCK_ID (NETXEN_CAM_RAM(0x124))
#define NETXEN_PHY_LOCK_ID (NETXEN_CAM_RAM(0x120))
@@ -654,30 +745,71 @@ enum {
#define PCIX_INT_VECTOR (0x10100)
#define PCIX_INT_MASK (0x10104)
-#define PCIX_MN_WINDOW_F0 (0x10200)
-#define PCIX_MN_WINDOW(_f) (PCIX_MN_WINDOW_F0 + (0x20 * (_f)))
-#define PCIX_MS_WINDOW (0x10204)
-#define PCIX_SN_WINDOW_F0 (0x10208)
-#define PCIX_SN_WINDOW(_f) (PCIX_SN_WINDOW_F0 + (0x20 * (_f)))
#define PCIX_CRB_WINDOW (0x10210)
#define PCIX_CRB_WINDOW_F0 (0x10210)
#define PCIX_CRB_WINDOW_F1 (0x10230)
#define PCIX_CRB_WINDOW_F2 (0x10250)
#define PCIX_CRB_WINDOW_F3 (0x10270)
+#define PCIX_CRB_WINDOW_F4 (0x102ac)
+#define PCIX_CRB_WINDOW_F5 (0x102bc)
+#define PCIX_CRB_WINDOW_F6 (0x102cc)
+#define PCIX_CRB_WINDOW_F7 (0x102dc)
+#define PCIE_CRB_WINDOW_REG(func) (((func) < 4) ? \
+ (PCIX_CRB_WINDOW_F0 + (0x20 * (func))) :\
+ (PCIX_CRB_WINDOW_F4 + (0x10 * ((func)-4))))
+
+#define PCIX_MN_WINDOW (0x10200)
+#define PCIX_MN_WINDOW_F0 (0x10200)
+#define PCIX_MN_WINDOW_F1 (0x10220)
+#define PCIX_MN_WINDOW_F2 (0x10240)
+#define PCIX_MN_WINDOW_F3 (0x10260)
+#define PCIX_MN_WINDOW_F4 (0x102a0)
+#define PCIX_MN_WINDOW_F5 (0x102b0)
+#define PCIX_MN_WINDOW_F6 (0x102c0)
+#define PCIX_MN_WINDOW_F7 (0x102d0)
+#define PCIE_MN_WINDOW_REG(func) (((func) < 4) ? \
+ (PCIX_MN_WINDOW_F0 + (0x20 * (func))) :\
+ (PCIX_MN_WINDOW_F4 + (0x10 * ((func)-4))))
+
+#define PCIX_SN_WINDOW (0x10208)
+#define PCIX_SN_WINDOW_F0 (0x10208)
+#define PCIX_SN_WINDOW_F1 (0x10228)
+#define PCIX_SN_WINDOW_F2 (0x10248)
+#define PCIX_SN_WINDOW_F3 (0x10268)
+#define PCIX_SN_WINDOW_F4 (0x102a8)
+#define PCIX_SN_WINDOW_F5 (0x102b8)
+#define PCIX_SN_WINDOW_F6 (0x102c8)
+#define PCIX_SN_WINDOW_F7 (0x102d8)
+#define PCIE_SN_WINDOW_REG(func) (((func) < 4) ? \
+ (PCIX_SN_WINDOW_F0 + (0x20 * (func))) :\
+ (PCIX_SN_WINDOW_F4 + (0x10 * ((func)-4))))
#define PCIX_TARGET_STATUS (0x10118)
+#define PCIX_TARGET_STATUS_F1 (0x10160)
+#define PCIX_TARGET_STATUS_F2 (0x10164)
+#define PCIX_TARGET_STATUS_F3 (0x10168)
+#define PCIX_TARGET_STATUS_F4 (0x10360)
+#define PCIX_TARGET_STATUS_F5 (0x10364)
+#define PCIX_TARGET_STATUS_F6 (0x10368)
+#define PCIX_TARGET_STATUS_F7 (0x1036c)
+
#define PCIX_TARGET_MASK (0x10128)
-#define PCIX_TARGET_STATUS_F1 (0x10160)
-#define PCIX_TARGET_MASK_F1 (0x10170)
-#define PCIX_TARGET_STATUS_F2 (0x10164)
-#define PCIX_TARGET_MASK_F2 (0x10174)
-#define PCIX_TARGET_STATUS_F3 (0x10168)
-#define PCIX_TARGET_MASK_F3 (0x10178)
+#define PCIX_TARGET_MASK_F1 (0x10170)
+#define PCIX_TARGET_MASK_F2 (0x10174)
+#define PCIX_TARGET_MASK_F3 (0x10178)
+#define PCIX_TARGET_MASK_F4 (0x10370)
+#define PCIX_TARGET_MASK_F5 (0x10374)
+#define PCIX_TARGET_MASK_F6 (0x10378)
+#define PCIX_TARGET_MASK_F7 (0x1037c)
#define PCIX_MSI_F0 (0x13000)
#define PCIX_MSI_F1 (0x13004)
#define PCIX_MSI_F2 (0x13008)
#define PCIX_MSI_F3 (0x1300c)
+#define PCIX_MSI_F4 (0x13010)
+#define PCIX_MSI_F5 (0x13014)
+#define PCIX_MSI_F6 (0x13018)
+#define PCIX_MSI_F7 (0x1301c)
#define PCIX_MSI_F(i) (0x13000+((i)*4))
#define PCIX_PS_MEM_SPACE (0x90000)
@@ -695,11 +827,102 @@ enum {
#define PCIE_SEM2_UNLOCK (0x1c014) /* Flash unlock */
#define PCIE_SEM3_LOCK (0x1c018) /* Phy lock */
#define PCIE_SEM3_UNLOCK (0x1c01c) /* Phy unlock */
-
+#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_SETUP_FUNCTION (0x12040)
+#define PCIE_SETUP_FUNCTION2 (0x12048)
#define PCIE_TGT_SPLIT_CHICKEN (0x12080)
+#define PCIE_CHICKEN3 (0x120c8)
#define PCIE_MAX_MASTER_SPLIT (0x14048)
+#define NETXEN_PORT_MODE_NONE 0
+#define NETXEN_PORT_MODE_XG 1
+#define NETXEN_PORT_MODE_GB 2
+#define NETXEN_PORT_MODE_802_3_AP 3
+#define NETXEN_PORT_MODE_AUTO_NEG 4
+#define NETXEN_PORT_MODE_AUTO_NEG_1G 5
+#define NETXEN_PORT_MODE_AUTO_NEG_XG 6
+#define NETXEN_PORT_MODE_ADDR (NETXEN_CAM_RAM(0x24))
+#define NETXEN_WOL_PORT_MODE (NETXEN_CAM_RAM(0x198))
+
#define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14)
+#define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
+
+/*
+ * PCI Interrupt Vector Values.
+ */
+#define PCIX_INT_VECTOR_BIT_F0 0x0080
+#define PCIX_INT_VECTOR_BIT_F1 0x0100
+#define PCIX_INT_VECTOR_BIT_F2 0x0200
+#define PCIX_INT_VECTOR_BIT_F3 0x0400
+#define PCIX_INT_VECTOR_BIT_F4 0x0800
+#define PCIX_INT_VECTOR_BIT_F5 0x1000
+#define PCIX_INT_VECTOR_BIT_F6 0x2000
+#define PCIX_INT_VECTOR_BIT_F7 0x4000
+
+struct netxen_legacy_intr_set {
+ uint32_t int_vec_bit;
+ uint32_t tgt_status_reg;
+ uint32_t tgt_mask_reg;
+ uint32_t pci_int_reg;
+};
+
+#define NX_LEGACY_INTR_CONFIG \
+{ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F0, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(0) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F1, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F1, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F1, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(1) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F2, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F2, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F2, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(2) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F3, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F3, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F3, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(3) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F4, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F4, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F4, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(4) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F5, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F5, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F5, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(5) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F6, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F6, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F6, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(6) }, \
+ \
+ { \
+ .int_vec_bit = PCIX_INT_VECTOR_BIT_F7, \
+ .tgt_status_reg = ISR_INT_TARGET_STATUS_F7, \
+ .tgt_mask_reg = ISR_INT_TARGET_MASK_F7, \
+ .pci_int_reg = ISR_MSI_INT_TRIGGER(7) }, \
+}
+
#endif /* __NETXEN_NIC_HDR_H_ */
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index c43d06b8de9..96a3bc6426e 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -38,242 +38,262 @@
#include <net/ip.h>
-struct netxen_recv_crb recv_crb_registers[] = {
- /*
- * Instance 0.
- */
- {
- /* rcv_desc_crb: */
- {
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x100),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x104),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x108),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x10c),
-
- },
- /* Jumbo frames */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x110),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x114),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x118),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x11c),
- },
- /* LRO */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x120),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x124),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x128),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x12c),
- }
- },
- /* crb_rcvstatus_ring: */
- NETXEN_NIC_REG(0x130),
- /* crb_rcv_status_producer: */
- NETXEN_NIC_REG(0x134),
- /* crb_rcv_status_consumer: */
- NETXEN_NIC_REG(0x138),
- /* crb_rcvpeg_state: */
- NETXEN_NIC_REG(0x13c),
- /* crb_status_ring_size */
- NETXEN_NIC_REG(0x140),
-
- },
- /*
- * Instance 1,
- */
- {
- /* rcv_desc_crb: */
- {
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x144),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x148),
- /* crb_globalrcv_ring: */
- NETXEN_NIC_REG(0x14c),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x150),
-
- },
- /* Jumbo frames */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x154),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x158),
- /* crb_globalrcv_ring: */
- NETXEN_NIC_REG(0x15c),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x160),
- },
- /* LRO */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x164),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x168),
- /* crb_globalrcv_ring: */
- NETXEN_NIC_REG(0x16c),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x170),
- }
-
- },
- /* crb_rcvstatus_ring: */
- NETXEN_NIC_REG(0x174),
- /* crb_rcv_status_producer: */
- NETXEN_NIC_REG(0x178),
- /* crb_rcv_status_consumer: */
- NETXEN_NIC_REG(0x17c),
- /* crb_rcvpeg_state: */
- NETXEN_NIC_REG(0x180),
- /* crb_status_ring_size */
- NETXEN_NIC_REG(0x184),
- },
- /*
- * Instance 2,
- */
- {
- {
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x1d8),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x1dc),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x1f0),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x1f4),
- },
- /* Jumbo frames */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x1f8),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x1fc),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x200),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x204),
- },
- /* LRO */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x208),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x20c),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x210),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x214),
- }
- },
- /* crb_rcvstatus_ring: */
- NETXEN_NIC_REG(0x218),
- /* crb_rcv_status_producer: */
- NETXEN_NIC_REG(0x21c),
- /* crb_rcv_status_consumer: */
- NETXEN_NIC_REG(0x220),
- /* crb_rcvpeg_state: */
- NETXEN_NIC_REG(0x224),
- /* crb_status_ring_size */
- NETXEN_NIC_REG(0x228),
- },
- /*
- * Instance 3,
- */
- {
- {
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x22c),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x230),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x234),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x238),
- },
- /* Jumbo frames */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x23c),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x240),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x244),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x248),
- },
- /* LRO */
- {
- /* crb_rcv_producer_offset: */
- NETXEN_NIC_REG(0x24c),
- /* crb_rcv_consumer_offset: */
- NETXEN_NIC_REG(0x250),
- /* crb_gloablrcv_ring: */
- NETXEN_NIC_REG(0x254),
- /* crb_rcv_ring_size */
- NETXEN_NIC_REG(0x258),
- }
- },
- /* crb_rcvstatus_ring: */
- NETXEN_NIC_REG(0x25c),
- /* crb_rcv_status_producer: */
- NETXEN_NIC_REG(0x260),
- /* crb_rcv_status_consumer: */
- NETXEN_NIC_REG(0x264),
- /* crb_rcvpeg_state: */
- NETXEN_NIC_REG(0x268),
- /* crb_status_ring_size */
- NETXEN_NIC_REG(0x26c),
- },
+#define MASK(n) ((1ULL<<(n))-1)
+#define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff))
+#define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff))
+#define MS_WIN(addr) (addr & 0x0ffc0000)
+
+#define GET_MEM_OFFS_2M(addr) (addr & MASK(18))
+
+#define CRB_BLK(off) ((off >> 20) & 0x3f)
+#define CRB_SUBBLK(off) ((off >> 16) & 0xf)
+#define CRB_WINDOW_2M (0x130060)
+#define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
+#define CRB_INDIRECT_2M (0x1e0000UL)
+
+#define CRB_WIN_LOCK_TIMEOUT 100000000
+static crb_128M_2M_block_map_t crb_128M_2M_map[64] = {
+ {{{0, 0, 0, 0} } }, /* 0: PCI */
+ {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */
+ {1, 0x0110000, 0x0120000, 0x130000},
+ {1, 0x0120000, 0x0122000, 0x124000},
+ {1, 0x0130000, 0x0132000, 0x126000},
+ {1, 0x0140000, 0x0142000, 0x128000},
+ {1, 0x0150000, 0x0152000, 0x12a000},
+ {1, 0x0160000, 0x0170000, 0x110000},
+ {1, 0x0170000, 0x0172000, 0x12e000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x01e0000, 0x01e0800, 0x122000},
+ {0, 0x0000000, 0x0000000, 0x000000} } },
+ {{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */
+ {{{0, 0, 0, 0} } }, /* 3: */
+ {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */
+ {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE */
+ {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU */
+ {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM */
+ {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x08f0000, 0x08f2000, 0x172000} } },
+ {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1*/
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x09f0000, 0x09f2000, 0x176000} } },
+ {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2*/
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x0af0000, 0x0af2000, 0x17a000} } },
+ {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3*/
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {1, 0x0bf0000, 0x0bf2000, 0x17e000} } },
+ {{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */
+ {{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */
+ {{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */
+ {{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */
+ {{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */
+ {{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */
+ {{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */
+ {{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */
+ {{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */
+ {{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */
+ {{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */
+ {{{0, 0, 0, 0} } }, /* 23: */
+ {{{0, 0, 0, 0} } }, /* 24: */
+ {{{0, 0, 0, 0} } }, /* 25: */
+ {{{0, 0, 0, 0} } }, /* 26: */
+ {{{0, 0, 0, 0} } }, /* 27: */
+ {{{0, 0, 0, 0} } }, /* 28: */
+ {{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */
+ {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */
+ {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */
+ {{{0} } }, /* 32: PCI */
+ {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */
+ {1, 0x2110000, 0x2120000, 0x130000},
+ {1, 0x2120000, 0x2122000, 0x124000},
+ {1, 0x2130000, 0x2132000, 0x126000},
+ {1, 0x2140000, 0x2142000, 0x128000},
+ {1, 0x2150000, 0x2152000, 0x12a000},
+ {1, 0x2160000, 0x2170000, 0x110000},
+ {1, 0x2170000, 0x2172000, 0x12e000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000},
+ {0, 0x0000000, 0x0000000, 0x000000} } },
+ {{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */
+ {{{0} } }, /* 35: */
+ {{{0} } }, /* 36: */
+ {{{0} } }, /* 37: */
+ {{{0} } }, /* 38: */
+ {{{0} } }, /* 39: */
+ {{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */
+ {{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */
+ {{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */
+ {{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */
+ {{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */
+ {{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */
+ {{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */
+ {{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */
+ {{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */
+ {{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */
+ {{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */
+ {{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */
+ {{{0} } }, /* 52: */
+ {{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */
+ {{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */
+ {{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */
+ {{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */
+ {{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */
+ {{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */
+ {{{0} } }, /* 59: I2C0 */
+ {{{0} } }, /* 60: I2C1 */
+ {{{1, 0x3d00000, 0x3d04000, 0x1d8000} } },/* 61: LPC */
+ {{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */
+ {{{1, 0x3f00000, 0x3f01000, 0x168000} } } /* 63: P2NR0 */
};
-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)},
- {NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)},
- {NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)}
+/*
+ * top 12 bits of crb internal address (hub, agent)
+ */
+static unsigned crb_hub_agt[64] =
+{
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PS,
+ NETXEN_HW_CRB_HUB_AGT_ADR_MN,
+ NETXEN_HW_CRB_HUB_AGT_ADR_MS,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SRE,
+ NETXEN_HW_CRB_HUB_AGT_ADR_NIU,
+ NETXEN_HW_CRB_HUB_AGT_ADR_QMN,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SQN0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SQN1,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SQN2,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SQN3,
+ NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,
+ NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,
+ NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN4,
+ NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN1,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN2,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGN3,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGND,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGNI,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGS0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGS1,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGS2,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGS3,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGSI,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SN,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_EG,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PS,
+ NETXEN_HW_CRB_HUB_AGT_ADR_CAM,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_TIMR,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX1,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX2,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX3,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX4,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX5,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX6,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX7,
+ NETXEN_HW_CRB_HUB_AGT_ADR_XDMA,
+ NETXEN_HW_CRB_HUB_AGT_ADR_I2Q,
+ NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX8,
+ NETXEN_HW_CRB_HUB_AGT_ADR_RPMX9,
+ NETXEN_HW_CRB_HUB_AGT_ADR_OCM0,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_SMB,
+ NETXEN_HW_CRB_HUB_AGT_ADR_I2C0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_I2C1,
+ 0,
+ NETXEN_HW_CRB_HUB_AGT_ADR_PGNC,
+ 0,
};
-#define CRB_CTX_ADDR_REG_LO(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][0])
-#define CRB_CTX_ADDR_REG_HI(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][2])
-#define CRB_CTX_SIGNATURE_REG(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][1])
-
/* PCI Windowing for DDR regions. */
#define ADDR_IN_RANGE(addr, low, high) \
(((addr) <= (high)) && ((addr) >= (low)))
-#define NETXEN_FLASH_BASE (NETXEN_BOOTLD_START)
-#define NETXEN_PHANTOM_MEM_BASE (NETXEN_FLASH_BASE)
#define NETXEN_MAX_MTU 8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE
#define NETXEN_MIN_MTU 64
#define NETXEN_ETH_FCS_SIZE 4
#define NETXEN_ENET_HEADER_SIZE 14
-#define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */
+#define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */
#define NETXEN_FIRMWARE_LEN ((16 * 1024) / 4)
#define NETXEN_NIU_HDRSIZE (0x1 << 6)
#define NETXEN_NIU_TLRSIZE (0x1 << 5)
-#define lower32(x) ((u32)((x) & 0xffffffff))
-#define upper32(x) \
- ((u32)(((unsigned long long)(x) >> 32) & 0xffffffff))
-
#define NETXEN_NIC_ZERO_PAUSE_ADDR 0ULL
#define NETXEN_NIC_UNIT_PAUSE_ADDR 0x200ULL
#define NETXEN_NIC_EPG_PAUSE_ADDR1 0x2200010000c28001ULL
@@ -281,10 +301,6 @@ static u64 ctx_addr_sig_regs[][3] = {
#define NETXEN_NIC_WINDOW_MARGIN 0x100000
-static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
- unsigned long long addr);
-void netxen_free_hw_resources(struct netxen_adapter *adapter);
-
int netxen_nic_set_mac(struct net_device *netdev, void *p)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
@@ -296,266 +312,370 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
- DPRINTK(INFO, "valid ether addr\n");
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
- if (adapter->macaddr_set)
- adapter->macaddr_set(adapter, addr->sa_data);
+ /* For P3, MAC addr is not set in NIU */
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ if (adapter->macaddr_set)
+ adapter->macaddr_set(adapter, addr->sa_data);
return 0;
}
-/*
- * netxen_nic_set_multi - Multicast
- */
-void netxen_nic_set_multi(struct net_device *netdev)
+#define NETXEN_UNICAST_ADDR(port, index) \
+ (NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8))
+#define NETXEN_MCAST_ADDR(port, index) \
+ (NETXEN_MULTICAST_ADDR_BASE+(port*0x80)+(index*8))
+#define MAC_HI(addr) \
+ ((addr[2] << 16) | (addr[1] << 8) | (addr[0]))
+#define MAC_LO(addr) \
+ ((addr[5] << 16) | (addr[4] << 8) | (addr[3]))
+
+static int
+netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter)
+{
+ u32 val = 0;
+ u16 port = adapter->physical_port;
+ u8 *addr = adapter->netdev->dev_addr;
+
+ if (adapter->mc_enabled)
+ return 0;
+
+ adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+ val |= (1UL << (28+port));
+ adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+
+ /* add broadcast addr to filter */
+ val = 0xffffff;
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_UNICAST_ADDR(port, 0)+4, val);
+
+ /* add station addr to filter */
+ val = MAC_HI(addr);
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), val);
+ val = MAC_LO(addr);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_UNICAST_ADDR(port, 1)+4, val);
+
+ adapter->mc_enabled = 1;
+ return 0;
+}
+
+static int
+netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter)
+{
+ u32 val = 0;
+ u16 port = adapter->physical_port;
+ u8 *addr = adapter->netdev->dev_addr;
+
+ if (!adapter->mc_enabled)
+ return 0;
+
+ adapter->hw_read_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+ val &= ~(1UL << (28+port));
+ adapter->hw_write_wx(adapter, NETXEN_MAC_ADDR_CNTL_REG, &val, 4);
+
+ val = MAC_HI(addr);
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 0), val);
+ val = MAC_LO(addr);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_UNICAST_ADDR(port, 0)+4, val);
+
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1), 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0);
+
+ adapter->mc_enabled = 0;
+ return 0;
+}
+
+static int
+netxen_nic_set_mcast_addr(struct netxen_adapter *adapter,
+ int index, u8 *addr)
+{
+ u32 hi = 0, lo = 0;
+ u16 port = adapter->physical_port;
+
+ lo = MAC_LO(addr);
+ hi = MAC_HI(addr);
+
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_MCAST_ADDR(port, index), hi);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_MCAST_ADDR(port, index)+4, lo);
+
+ return 0;
+}
+
+void netxen_p2_nic_set_multi(struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
struct dev_mc_list *mc_ptr;
+ u8 null_addr[6];
+ int index = 0;
+
+ memset(null_addr, 0, 6);
- mc_ptr = netdev->mc_list;
if (netdev->flags & IFF_PROMISC) {
- if (adapter->set_promisc)
- adapter->set_promisc(adapter,
- NETXEN_NIU_PROMISC_MODE);
- } else {
- if (adapter->unset_promisc)
- adapter->unset_promisc(adapter,
- NETXEN_NIU_NON_PROMISC_MODE);
+
+ adapter->set_promisc(adapter,
+ NETXEN_NIU_PROMISC_MODE);
+
+ /* Full promiscuous mode */
+ netxen_nic_disable_mcast_filter(adapter);
+
+ return;
+ }
+
+ if (netdev->mc_count == 0) {
+ adapter->set_promisc(adapter,
+ NETXEN_NIU_NON_PROMISC_MODE);
+ netxen_nic_disable_mcast_filter(adapter);
+ return;
}
+
+ adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE);
+ if (netdev->flags & IFF_ALLMULTI ||
+ netdev->mc_count > adapter->max_mc_count) {
+ netxen_nic_disable_mcast_filter(adapter);
+ return;
+ }
+
+ netxen_nic_enable_mcast_filter(adapter);
+
+ for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next, index++)
+ netxen_nic_set_mcast_addr(adapter, index, mc_ptr->dmi_addr);
+
+ if (index != netdev->mc_count)
+ printk(KERN_WARNING "%s: %s multicast address count mismatch\n",
+ netxen_nic_driver_name, netdev->name);
+
+ /* Clear out remaining addresses */
+ for (; index < adapter->max_mc_count; index++)
+ netxen_nic_set_mcast_addr(adapter, index, null_addr);
}
-/*
- * netxen_nic_change_mtu - Change the Maximum Transfer Unit
- * @returns 0 on success, negative on failure
- */
-int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
+static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
+ u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list)
{
- struct netxen_adapter *adapter = netdev_priv(netdev);
- int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE;
+ nx_mac_list_t *cur, *prev;
+
+ /* if in del_list, move it to adapter->mac_list */
+ for (cur = *del_list, prev = NULL; cur;) {
+ if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
+ if (prev == NULL)
+ *del_list = cur->next;
+ else
+ prev->next = cur->next;
+ cur->next = adapter->mac_list;
+ adapter->mac_list = cur;
+ return 0;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+
+ /* make sure to add each mac address only once */
+ for (cur = adapter->mac_list; cur; cur = cur->next) {
+ if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
+ return 0;
+ }
+ /* not in del_list, create new entry and add to add_list */
+ cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL);
+ if (cur == NULL) {
+ printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may"
+ "not work properly from now.\n", __func__);
+ return -1;
+ }
- if ((eff_mtu > NETXEN_MAX_MTU) || (eff_mtu < NETXEN_MIN_MTU)) {
- printk(KERN_ERR "%s: %s %d is not supported.\n",
- netxen_nic_driver_name, netdev->name, mtu);
+ memcpy(cur->mac_addr, addr, ETH_ALEN);
+ cur->next = *add_list;
+ *add_list = cur;
+ return 0;
+}
+
+static int
+netxen_send_cmd_descs(struct netxen_adapter *adapter,
+ struct cmd_desc_type0 *cmd_desc_arr, int nr_elements)
+{
+ uint32_t i, producer;
+ struct netxen_cmd_buffer *pbuf;
+ struct cmd_desc_type0 *cmd_desc;
+
+ if (nr_elements > MAX_PENDING_DESC_BLOCK_SIZE || nr_elements == 0) {
+ printk(KERN_WARNING "%s: Too many command descriptors in a "
+ "request\n", __func__);
return -EINVAL;
}
- if (adapter->set_mtu)
- adapter->set_mtu(adapter, mtu);
- netdev->mtu = mtu;
+ i = 0;
+
+ producer = adapter->cmd_producer;
+ do {
+ cmd_desc = &cmd_desc_arr[i];
+
+ pbuf = &adapter->cmd_buf_arr[producer];
+ pbuf->mss = 0;
+ pbuf->total_length = 0;
+ pbuf->skb = NULL;
+ pbuf->cmd = 0;
+ pbuf->frag_count = 0;
+ pbuf->port = 0;
+
+ /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */
+ memcpy(&adapter->ahw.cmd_desc_head[producer],
+ &cmd_desc_arr[i], sizeof(struct cmd_desc_type0));
+
+ producer = get_next_index(producer,
+ adapter->max_tx_desc_count);
+ i++;
+
+ } while (i != nr_elements);
+
+ adapter->cmd_producer = producer;
+
+ /* write producer index to start the xmit */
+
+ netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer);
return 0;
}
-/*
- * check if the firmware has been downloaded and ready to run and
- * setup the address for the descriptors in the adapter
- */
-int netxen_nic_hw_resources(struct netxen_adapter *adapter)
+#define NIC_REQUEST 0x14
+#define NETXEN_MAC_EVENT 0x1
+
+static int nx_p3_sre_macaddr_change(struct net_device *dev,
+ u8 *addr, unsigned op)
{
- struct netxen_hardware_context *hw = &adapter->ahw;
- u32 state = 0;
- void *addr;
- int loops = 0, err = 0;
- int ctx, ring;
- struct netxen_recv_context *recv_ctx;
- struct netxen_rcv_desc_ctx *rcv_desc;
- int func_id = adapter->portnum;
-
- DPRINTK(INFO, "crb_base: %lx %x", NETXEN_PCI_CRBSPACE,
- PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCI_CRBSPACE));
- DPRINTK(INFO, "cam base: %lx %x", NETXEN_CRB_CAM,
- pci_base_offset(adapter, NETXEN_CRB_CAM));
- DPRINTK(INFO, "cam RAM: %lx %x", NETXEN_CAM_RAM_BASE,
- pci_base_offset(adapter, NETXEN_CAM_RAM_BASE));
-
-
- for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
- DPRINTK(INFO, "Command Peg ready..waiting for rcv peg\n");
- loops = 0;
- state = 0;
- /* Window 1 call */
- state = readl(NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers[ctx].
- crb_rcvpeg_state));
- while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) {
- msleep(1);
- /* Window 1 call */
- state = readl(NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers
- [ctx].
- crb_rcvpeg_state));
- loops++;
- }
- if (loops >= 20) {
- printk(KERN_ERR "Rcv Peg initialization not complete:"
- "%x.\n", state);
- err = -EIO;
- return err;
- }
+ struct netxen_adapter *adapter = (struct netxen_adapter *)dev->priv;
+ nx_nic_req_t req;
+ nx_mac_req_t mac_req;
+ int rv;
+
+ memset(&req, 0, sizeof(nx_nic_req_t));
+ req.qhdr |= (NIC_REQUEST << 23);
+ req.req_hdr |= NETXEN_MAC_EVENT;
+ req.req_hdr |= ((u64)adapter->portnum << 16);
+ mac_req.op = op;
+ memcpy(&mac_req.mac_addr, addr, 6);
+ req.words[0] = cpu_to_le64(*(u64 *)&mac_req);
+
+ rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0) {
+ printk(KERN_ERR "ERROR. Could not send mac update\n");
+ return rv;
}
- adapter->intr_scheme = readl(
- NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW));
- adapter->msi_mode = readl(
- NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_FW));
-
- addr = netxen_alloc(adapter->ahw.pdev,
- sizeof(struct netxen_ring_ctx) +
- sizeof(uint32_t),
- (dma_addr_t *) & adapter->ctx_desc_phys_addr,
- &adapter->ctx_desc_pdev);
-
- if (addr == NULL) {
- DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
- err = -ENOMEM;
- return err;
- }
- memset(addr, 0, sizeof(struct netxen_ring_ctx));
- adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
- adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum);
- adapter->ctx_desc->cmd_consumer_offset =
- cpu_to_le64(adapter->ctx_desc_phys_addr +
- sizeof(struct netxen_ring_ctx));
- adapter->cmd_consumer = (__le32 *) (((char *)addr) +
- sizeof(struct netxen_ring_ctx));
-
- addr = netxen_alloc(adapter->ahw.pdev,
- sizeof(struct cmd_desc_type0) *
- adapter->max_tx_desc_count,
- (dma_addr_t *) & hw->cmd_desc_phys_addr,
- &adapter->ahw.cmd_desc_pdev);
-
- if (addr == NULL) {
- DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
- netxen_free_hw_resources(adapter);
- return -ENOMEM;
- }
-
- adapter->ctx_desc->cmd_ring_addr =
- cpu_to_le64(hw->cmd_desc_phys_addr);
- adapter->ctx_desc->cmd_ring_size =
- cpu_to_le32(adapter->max_tx_desc_count);
-
- hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
-
- for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
- recv_ctx = &adapter->recv_ctx[ctx];
-
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
- addr = netxen_alloc(adapter->ahw.pdev,
- RCV_DESC_RINGSIZE,
- &rcv_desc->phys_addr,
- &rcv_desc->phys_pdev);
- if (addr == NULL) {
- DPRINTK(ERR, "bad return from "
- "pci_alloc_consistent\n");
- netxen_free_hw_resources(adapter);
- err = -ENOMEM;
- return err;
- }
- rcv_desc->desc_head = (struct rcv_desc *)addr;
- adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
- cpu_to_le64(rcv_desc->phys_addr);
- adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
- cpu_to_le32(rcv_desc->max_rx_desc_count);
- }
- addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE,
- &recv_ctx->rcv_status_desc_phys_addr,
- &recv_ctx->rcv_status_desc_pdev);
- if (addr == NULL) {
- DPRINTK(ERR, "bad return from"
- " pci_alloc_consistent\n");
- netxen_free_hw_resources(adapter);
- err = -ENOMEM;
- return err;
- }
- recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
- adapter->ctx_desc->sts_ring_addr =
- cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
- adapter->ctx_desc->sts_ring_size =
- cpu_to_le32(adapter->max_rx_desc_count);
-
- }
- /* Window = 1 */
-
- writel(lower32(adapter->ctx_desc_phys_addr),
- NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_LO(func_id)));
- writel(upper32(adapter->ctx_desc_phys_addr),
- NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_ADDR_REG_HI(func_id)));
- writel(NETXEN_CTX_SIGNATURE | func_id,
- NETXEN_CRB_NORMALIZE(adapter, CRB_CTX_SIGNATURE_REG(func_id)));
- return err;
+ return 0;
}
-void netxen_free_hw_resources(struct netxen_adapter *adapter)
+void netxen_p3_nic_set_multi(struct net_device *netdev)
{
- struct netxen_recv_context *recv_ctx;
- struct netxen_rcv_desc_ctx *rcv_desc;
- int ctx, ring;
-
- if (adapter->ctx_desc != NULL) {
- pci_free_consistent(adapter->ctx_desc_pdev,
- sizeof(struct netxen_ring_ctx) +
- sizeof(uint32_t),
- adapter->ctx_desc,
- adapter->ctx_desc_phys_addr);
- adapter->ctx_desc = NULL;
- }
-
- if (adapter->ahw.cmd_desc_head != NULL) {
- pci_free_consistent(adapter->ahw.cmd_desc_pdev,
- sizeof(struct cmd_desc_type0) *
- adapter->max_tx_desc_count,
- adapter->ahw.cmd_desc_head,
- adapter->ahw.cmd_desc_phys_addr);
- adapter->ahw.cmd_desc_head = NULL;
- }
-
- for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
- recv_ctx = &adapter->recv_ctx[ctx];
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
-
- if (rcv_desc->desc_head != NULL) {
- pci_free_consistent(rcv_desc->phys_pdev,
- RCV_DESC_RINGSIZE,
- rcv_desc->desc_head,
- rcv_desc->phys_addr);
- rcv_desc->desc_head = NULL;
- }
- }
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ nx_mac_list_t *cur, *next, *del_list, *add_list = NULL;
+ struct dev_mc_list *mc_ptr;
+ u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ adapter->set_promisc(adapter, NETXEN_NIU_PROMISC_MODE);
- if (recv_ctx->rcv_status_desc_head != NULL) {
- pci_free_consistent(recv_ctx->rcv_status_desc_pdev,
- STATUS_DESC_RINGSIZE,
- recv_ctx->rcv_status_desc_head,
- recv_ctx->
- rcv_status_desc_phys_addr);
- recv_ctx->rcv_status_desc_head = NULL;
+ /*
+ * Programming mac addresses will automaticly enabling L2 filtering.
+ * HW will replace timestamp with L2 conid when L2 filtering is
+ * enabled. This causes problem for LSA. Do not enabling L2 filtering
+ * until that problem is fixed.
+ */
+ if ((netdev->flags & IFF_PROMISC) ||
+ (netdev->mc_count > adapter->max_mc_count))
+ return;
+
+ del_list = adapter->mac_list;
+ adapter->mac_list = NULL;
+
+ nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list);
+ if (netdev->mc_count > 0) {
+ nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list);
+ for (mc_ptr = netdev->mc_list; mc_ptr;
+ mc_ptr = mc_ptr->next) {
+ nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr,
+ &add_list, &del_list);
}
}
+ for (cur = del_list; cur;) {
+ nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL);
+ next = cur->next;
+ kfree(cur);
+ cur = next;
+ }
+ for (cur = add_list; cur;) {
+ nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD);
+ next = cur->next;
+ cur->next = adapter->mac_list;
+ adapter->mac_list = cur;
+ cur = next;
+ }
}
-void netxen_tso_check(struct netxen_adapter *adapter,
- struct cmd_desc_type0 *desc, struct sk_buff *skb)
+#define NETXEN_CONFIG_INTR_COALESCE 3
+
+/*
+ * Send the interrupt coalescing parameter set by ethtool to the card.
+ */
+int netxen_config_intr_coalesce(struct netxen_adapter *adapter)
{
- if (desc->mss) {
- desc->total_hdr_length = (sizeof(struct ethhdr) +
- ip_hdrlen(skb) + tcp_hdrlen(skb));
- netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
- } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
- if (ip_hdr(skb)->protocol == IPPROTO_TCP) {
- netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
- } else if (ip_hdr(skb)->protocol == IPPROTO_UDP) {
- netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
- } else {
- return;
- }
+ nx_nic_req_t req;
+ int rv;
+
+ memset(&req, 0, sizeof(nx_nic_req_t));
+
+ req.qhdr |= (NIC_REQUEST << 23);
+ req.req_hdr |= NETXEN_CONFIG_INTR_COALESCE;
+ req.req_hdr |= ((u64)adapter->portnum << 16);
+
+ memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal));
+
+ rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+ if (rv != 0) {
+ printk(KERN_ERR "ERROR. Could not send "
+ "interrupt coalescing parameters\n");
}
- desc->tcp_hdr_offset = skb_transport_offset(skb);
- desc->ip_hdr_offset = skb_network_offset(skb);
+
+ return rv;
+}
+
+/*
+ * netxen_nic_change_mtu - Change the Maximum Transfer Unit
+ * @returns 0 on success, negative on failure
+ */
+
+#define MTU_FUDGE_FACTOR 100
+
+int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ int max_mtu;
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ max_mtu = P3_MAX_MTU;
+ else
+ max_mtu = P2_MAX_MTU;
+
+ if (mtu > max_mtu) {
+ printk(KERN_ERR "%s: mtu > %d bytes unsupported\n",
+ netdev->name, max_mtu);
+ return -EINVAL;
+ }
+
+ if (adapter->set_mtu)
+ adapter->set_mtu(adapter, mtu);
+ netdev->mtu = mtu;
+
+ mtu += MTU_FUDGE_FACTOR;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ nx_fw_cmd_set_mtu(adapter, mtu);
+ else if (adapter->set_mtu)
+ adapter->set_mtu(adapter, mtu);
+
+ return 0;
}
int netxen_is_flash_supported(struct netxen_adapter *adapter)
@@ -632,41 +752,49 @@ int netxen_get_flash_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 */
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM7_LOCK), &done, 4);
+ if (done == 1)
+ break;
+ if (timeout >= CRB_WIN_LOCK_TIMEOUT)
+ return -1;
+ timeout++;
+ udelay(1);
+ }
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_CRB_WIN_LOCK_ID, adapter->portnum);
+ return 0;
+}
+
+static void crb_win_unlock(struct netxen_adapter *adapter)
+{
+ int val;
+
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM7_UNLOCK), &val, 4);
+}
+
/*
* Changes the CRB window to the specified window.
*/
-void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
+void
+netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw)
{
void __iomem *offset;
u32 tmp;
int count = 0;
+ uint8_t func = adapter->ahw.pci_func;
if (adapter->curr_window == wndw)
return;
- switch(adapter->ahw.pci_func) {
- case 0:
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW));
- break;
- case 1:
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F1));
- break;
- case 2:
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F2));
- break;
- case 3:
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW_F3));
- break;
- default:
- printk(KERN_INFO "Changing the window for PCI function "
- "%d\n", adapter->ahw.pci_func);
- offset = PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW));
- break;
- }
/*
* Move the CRB window.
* We need to write to the "direct access" region of PCI
@@ -675,6 +803,8 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
* register address is received by PCI. The direct region bypasses
* the CRB bus.
*/
+ offset = PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(func)));
if (wndw & 0x1)
wndw = NETXEN_WINDOW_ONE;
@@ -685,7 +815,7 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
while ((tmp = readl(offset)) != wndw) {
printk(KERN_WARNING "%s: %s WARNING: CRB window value not "
"registered properly: 0x%08x.\n",
- netxen_nic_driver_name, __FUNCTION__, tmp);
+ netxen_nic_driver_name, __func__, tmp);
mdelay(1);
if (count >= 10)
break;
@@ -698,51 +828,119 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
adapter->curr_window = 0;
}
+/*
+ * Return -1 if off is not valid,
+ * 1 if window access is needed. 'off' is set to offset from
+ * CRB space in 128M pci map
+ * 0 if no window access is needed. 'off' is set to 2M addr
+ * In: 'off' is offset from base in 128M pci map
+ */
+static int
+netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter,
+ ulong *off, int len)
+{
+ unsigned long end = *off + len;
+ crb_128M_2M_sub_block_map_t *m;
+
+
+ if (*off >= NETXEN_CRB_MAX)
+ return -1;
+
+ if (*off >= NETXEN_PCI_CAMQM && (end <= NETXEN_PCI_CAMQM_2M_END)) {
+ *off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE +
+ (ulong)adapter->ahw.pci_base0;
+ return 0;
+ }
+
+ if (*off < NETXEN_PCI_CRBSPACE)
+ return -1;
+
+ *off -= NETXEN_PCI_CRBSPACE;
+ end = *off + len;
+
+ /*
+ * Try direct map
+ */
+ m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
+
+ if (m->valid && (m->start_128M <= *off) && (m->end_128M >= end)) {
+ *off = *off + m->start_2M - m->start_128M +
+ (ulong)adapter->ahw.pci_base0;
+ return 0;
+ }
+
+ /*
+ * Not in direct map, use crb window
+ */
+ return 1;
+}
+
+/*
+ * In: 'off' is offset from CRB space in 128M pci map
+ * Out: 'off' is 2M pci map addr
+ * side effect: lock crb window
+ */
+static void
+netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off)
+{
+ u32 win_read;
+
+ adapter->crb_win = CRB_HI(*off);
+ writel(adapter->crb_win, (void *)(CRB_WINDOW_2M +
+ adapter->ahw.pci_base0));
+ /*
+ * Read back value to make sure write has gone through before trying
+ * to use it.
+ */
+ win_read = readl((void *)(CRB_WINDOW_2M + adapter->ahw.pci_base0));
+ if (win_read != adapter->crb_win) {
+ printk(KERN_ERR "%s: Written crbwin (0x%x) != "
+ "Read crbwin (0x%x), off=0x%lx\n",
+ __func__, adapter->crb_win, win_read, *off);
+ }
+ *off = (*off & MASK(16)) + CRB_INDIRECT_2M +
+ (ulong)adapter->ahw.pci_base0;
+}
+
int netxen_load_firmware(struct netxen_adapter *adapter)
{
int i;
u32 data, size = 0;
- u32 flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE;
- u64 off;
- void __iomem *addr;
+ u32 flashaddr = NETXEN_BOOTLD_START, memaddr = NETXEN_BOOTLD_START;
- size = NETXEN_FIRMWARE_LEN;
- writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
+ size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START)/4;
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_CAS_RST, 1);
for (i = 0; i < size; i++) {
- int retries = 10;
if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0)
return -EIO;
- off = netxen_nic_pci_set_window(adapter, memaddr);
- addr = pci_base_offset(adapter, off);
- writel(data, addr);
- do {
- if (readl(addr) == data)
- break;
- msleep(100);
- writel(data, addr);
- } while (--retries);
- if (!retries) {
- printk(KERN_ERR "%s: firmware load aborted, write failed at 0x%x\n",
- netxen_nic_driver_name, memaddr);
- return -EIO;
- }
+ adapter->pci_mem_write(adapter, memaddr, &data, 4);
flashaddr += 4;
memaddr += 4;
+ cond_resched();
+ }
+ msleep(1);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d);
+ else {
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff);
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_CAS_RST, 0);
}
- udelay(100);
- /* make sure Casper is powered on */
- writel(0x3fff,
- NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL));
- writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST));
return 0;
}
int
-netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
- int len)
+netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len)
{
void __iomem *addr;
@@ -750,7 +948,7 @@ netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
addr = NETXEN_CRB_NORMALIZE(adapter, off);
} else { /* Window 0 */
addr = pci_base_offset(adapter, off);
- netxen_nic_pci_change_crbwindow(adapter, 0);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
}
DPRINTK(INFO, "writing to base %lx offset %llx addr %p"
@@ -758,7 +956,7 @@ netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
pci_base(adapter, off), off, addr,
*(unsigned long long *)data, len);
if (!addr) {
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
return 1;
}
@@ -785,14 +983,14 @@ netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data,
break;
}
if (!ADDR_IN_WINDOW1(off))
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
return 0;
}
int
-netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
- int len)
+netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len)
{
void __iomem *addr;
@@ -800,13 +998,13 @@ netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
addr = NETXEN_CRB_NORMALIZE(adapter, off);
} else { /* Window 0 */
addr = pci_base_offset(adapter, off);
- netxen_nic_pci_change_crbwindow(adapter, 0);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
}
DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
pci_base(adapter, off), off, addr);
if (!addr) {
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
return 1;
}
switch (len) {
@@ -830,81 +1028,195 @@ netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data,
DPRINTK(INFO, "read %lx\n", *(unsigned long *)data);
if (!ADDR_IN_WINDOW1(off))
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
return 0;
}
-void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
-{ /* Only for window 1 */
- void __iomem *addr;
+int
+netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len)
+{
+ unsigned long flags = 0;
+ int rv;
+
+ rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
+
+ if (rv == -1) {
+ printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
+ __func__, off);
+ dump_stack();
+ return -1;
+ }
+
+ if (rv == 1) {
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ crb_win_lock(adapter);
+ netxen_nic_pci_set_crbwindow_2M(adapter, &off);
+ }
- addr = NETXEN_CRB_NORMALIZE(adapter, off);
- DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n",
- pci_base(adapter, off), off, addr, val);
- writel(val, addr);
+ DPRINTK(1, INFO, "write data %lx to offset %llx, len=%d\n",
+ *(unsigned long *)data, off, len);
+ switch (len) {
+ case 1:
+ writeb(*(uint8_t *)data, (void *)off);
+ break;
+ case 2:
+ writew(*(uint16_t *)data, (void *)off);
+ break;
+ case 4:
+ writel(*(uint32_t *)data, (void *)off);
+ break;
+ case 8:
+ writeq(*(uint64_t *)data, (void *)off);
+ break;
+ default:
+ DPRINTK(1, INFO,
+ "writing data %lx to offset %llx, num words=%d\n",
+ *(unsigned long *)data, off, (len>>3));
+ break;
+ }
+ if (rv == 1) {
+ crb_win_unlock(adapter);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ }
+
+ return 0;
}
-int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
-{ /* Only for window 1 */
- void __iomem *addr;
- int val;
+int
+netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter,
+ ulong off, void *data, int len)
+{
+ unsigned long flags = 0;
+ int rv;
- addr = NETXEN_CRB_NORMALIZE(adapter, off);
- DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n",
- pci_base(adapter, off), off, addr);
- val = readl(addr);
- writel(val, addr);
+ rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len);
+
+ if (rv == -1) {
+ printk(KERN_ERR "%s: invalid offset: 0x%016lx\n",
+ __func__, off);
+ dump_stack();
+ return -1;
+ }
+
+ if (rv == 1) {
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ crb_win_lock(adapter);
+ netxen_nic_pci_set_crbwindow_2M(adapter, &off);
+ }
+
+ DPRINTK(1, INFO, "read from offset %lx, len=%d\n", off, len);
+
+ switch (len) {
+ case 1:
+ *(uint8_t *)data = readb((void *)off);
+ break;
+ case 2:
+ *(uint16_t *)data = readw((void *)off);
+ break;
+ case 4:
+ *(uint32_t *)data = readl((void *)off);
+ break;
+ case 8:
+ *(uint64_t *)data = readq((void *)off);
+ break;
+ default:
+ break;
+ }
+ DPRINTK(1, INFO, "read %lx\n", *(unsigned long *)data);
+
+ if (rv == 1) {
+ crb_win_unlock(adapter);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ }
+
+ return 0;
+}
+
+void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val)
+{
+ adapter->hw_write_wx(adapter, off, &val, 4);
+}
+
+int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off)
+{
+ int val;
+ adapter->hw_read_wx(adapter, off, &val, 4);
return val;
}
/* Change the window to 0, write and change back to window 1. */
void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value)
{
- void __iomem *addr;
-
- netxen_nic_pci_change_crbwindow(adapter, 0);
- addr = pci_base_offset(adapter, index);
- writel(value, addr);
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ adapter->hw_write_wx(adapter, index, &value, 4);
}
/* Change the window to 0, read and change back to window 1. */
-void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value)
+void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 *value)
{
- void __iomem *addr;
+ adapter->hw_read_wx(adapter, index, value, 4);
+}
- addr = pci_base_offset(adapter, index);
+void netxen_nic_write_w1(struct netxen_adapter *adapter, u32 index, u32 value)
+{
+ adapter->hw_write_wx(adapter, index, &value, 4);
+}
+
+void netxen_nic_read_w1(struct netxen_adapter *adapter, u32 index, u32 *value)
+{
+ adapter->hw_read_wx(adapter, index, value, 4);
+}
+
+/*
+ * 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;
+ }
- netxen_nic_pci_change_crbwindow(adapter, 0);
- *value = readl(addr);
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ return 1;
}
static int netxen_pci_set_window_warning_count;
-static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
- unsigned long long addr)
+unsigned long
+netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter,
+ unsigned long long addr)
{
- static int ddr_mn_window = -1;
- static int qdr_sn_window = -1;
+ void __iomem *offset;
int window;
+ unsigned long long qdr_max;
+ uint8_t func = adapter->ahw.pci_func;
+
+ 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 */
addr -= NETXEN_ADDR_DDR_NET;
window = (addr >> 25) & 0x3ff;
- if (ddr_mn_window != window) {
- ddr_mn_window = window;
- writel(window, PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG
- (PCIX_MN_WINDOW(adapter->ahw.pci_func))));
+ if (adapter->ahw.ddr_mn_window != window) {
+ adapter->ahw.ddr_mn_window = window;
+ offset = PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG(PCIE_MN_WINDOW_REG(func)));
+ writel(window, offset);
/* MUST make sure window is set before we forge on... */
- readl(PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG
- (PCIX_MN_WINDOW(adapter->ahw.pci_func))));
+ readl(offset);
}
addr -= (window * NETXEN_WINDOW_ONE);
addr += NETXEN_PCI_DDR_NET;
@@ -914,22 +1226,17 @@ static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
} else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) {
addr -= NETXEN_ADDR_OCM1;
addr += NETXEN_PCI_OCM1;
- } else
- if (ADDR_IN_RANGE
- (addr, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX)) {
+ } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) {
/* QDR network side */
addr -= NETXEN_ADDR_QDR_NET;
window = (addr >> 22) & 0x3f;
- if (qdr_sn_window != window) {
- qdr_sn_window = window;
- writel((window << 22),
- PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG
- (PCIX_SN_WINDOW(adapter->ahw.pci_func))));
+ if (adapter->ahw.qdr_sn_window != window) {
+ adapter->ahw.qdr_sn_window = window;
+ offset = PCI_OFFSET_SECOND_RANGE(adapter,
+ NETXEN_PCIX_PH_REG(PCIE_SN_WINDOW_REG(func)));
+ writel((window << 22), offset);
/* MUST make sure window is set before we forge on... */
- readl(PCI_OFFSET_SECOND_RANGE(adapter,
- NETXEN_PCIX_PH_REG
- (PCIX_SN_WINDOW(adapter->ahw.pci_func))));
+ readl(offset);
}
addr -= (window * 0x400000);
addr += NETXEN_PCI_QDR_NET;
@@ -943,11 +1250,711 @@ static unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter,
printk("%s: Warning:netxen_nic_pci_set_window()"
" Unknown address range!\n",
netxen_nic_driver_name);
+ addr = -1UL;
+ }
+ return addr;
+}
+
+/*
+ * Note : only 32-bit writes!
+ */
+int netxen_nic_pci_write_immediate_128M(struct netxen_adapter *adapter,
+ u64 off, u32 data)
+{
+ writel(data, (void __iomem *)(PCI_OFFSET_SECOND_RANGE(adapter, off)));
+ return 0;
+}
+
+u32 netxen_nic_pci_read_immediate_128M(struct netxen_adapter *adapter, u64 off)
+{
+ return readl((void __iomem *)(pci_base_offset(adapter, off)));
+}
+
+void netxen_nic_pci_write_normalize_128M(struct netxen_adapter *adapter,
+ u64 off, u32 data)
+{
+ writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
+}
+
+u32 netxen_nic_pci_read_normalize_128M(struct netxen_adapter *adapter, u64 off)
+{
+ return readl(NETXEN_CRB_NORMALIZE(adapter, off));
+}
+
+unsigned long
+netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter,
+ unsigned long long addr)
+{
+ int window;
+ u32 win_read;
+
+ if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) {
+ /* DDR network side */
+ window = MN_WIN(addr);
+ adapter->ahw.ddr_mn_window = window;
+ adapter->hw_write_wx(adapter,
+ adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+ &window, 4);
+ adapter->hw_read_wx(adapter,
+ adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+ &win_read, 4);
+ if ((win_read << 17) != window) {
+ printk(KERN_INFO "Written MNwin (0x%x) != "
+ "Read MNwin (0x%x)\n", window, win_read);
+ }
+ addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_DDR_NET;
+ } else if (ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) {
+ if ((addr & 0x00ff800) == 0xff800) {
+ printk("%s: QM access not handled.\n", __func__);
+ addr = -1UL;
+ }
+
+ window = OCM_WIN(addr);
+ adapter->ahw.ddr_mn_window = window;
+ adapter->hw_write_wx(adapter,
+ adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+ &window, 4);
+ adapter->hw_read_wx(adapter,
+ adapter->ahw.mn_win_crb | NETXEN_PCI_CRBSPACE,
+ &win_read, 4);
+ if ((win_read >> 7) != window) {
+ printk(KERN_INFO "%s: Written OCMwin (0x%x) != "
+ "Read OCMwin (0x%x)\n",
+ __func__, window, win_read);
+ }
+ addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_OCM0_2M;
+
+ } else if (ADDR_IN_RANGE(addr,
+ NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX_P3)) {
+ /* QDR network side */
+ window = MS_WIN(addr);
+ adapter->ahw.qdr_sn_window = window;
+ adapter->hw_write_wx(adapter,
+ adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
+ &window, 4);
+ adapter->hw_read_wx(adapter,
+ adapter->ahw.ms_win_crb | NETXEN_PCI_CRBSPACE,
+ &win_read, 4);
+ if (win_read != window) {
+ printk(KERN_INFO "%s: Written MSwin (0x%x) != "
+ "Read MSwin (0x%x)\n",
+ __func__, window, win_read);
+ }
+ addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_QDR_NET;
+ } else {
+ /*
+ * peg gdb frequently accesses memory that doesn't exist,
+ * this limits the chit chat so debugging isn't slowed down.
+ */
+ if ((netxen_pci_set_window_warning_count++ < 8)
+ || (netxen_pci_set_window_warning_count%64 == 0)) {
+ printk("%s: Warning:%s Unknown address range!\n",
+ __func__, netxen_nic_driver_name);
+}
+ addr = -1UL;
}
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 *addr;
+ int ret = 0;
+ u64 start;
+ uint8_t *mem_ptr = NULL;
+ 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, off);
+ return -1;
+ }
+
+ addr = (void *)(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 == 0UL) {
+ *(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);
+ DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
+
+ 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 *addr;
+ int ret = 0;
+ u64 start;
+ uint8_t *mem_ptr = NULL;
+ 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, off);
+ return -1;
+ }
+
+ addr = (void *)(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 == 0UL)
+ 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);
+ DPRINTK(1, INFO, "writing data %llx to offset %llx\n",
+ *(unsigned long long *)data, start);
+ if (mem_ptr)
+ iounmap(mem_ptr);
+ return ret;
+}
+
+#define MAX_CTL_CHECK 1000
+
+int
+netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size)
+{
+ unsigned long flags, mem_crb;
+ int i, j, ret = 0, loop, sz[2], off0;
+ uint32_t temp;
+ uint64_t off8, tmpw, word[2] = {0, 0};
+
+ /*
+ * 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);
+
+ 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 = (unsigned long)pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
+
+ if ((size != 8) || (off0 != 0)) {
+ for (i = 0; i < loop; i++) {
+ if (adapter->pci_mem_read(adapter,
+ off8 + (i << 3), &word[i], 8))
+ return -1;
+ }
+ }
+
+ switch (size) {
+ case 1:
+ tmpw = *((uint8_t *)data);
+ break;
+ case 2:
+ tmpw = *((uint16_t *)data);
+ break;
+ case 4:
+ tmpw = *((uint32_t *)data);
+ break;
+ case 8:
+ default:
+ tmpw = *((uint64_t *)data);
+ break;
+ }
+ word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+ word[0] |= tmpw << (off0 * 8);
+
+ if (loop == 2) {
+ word[1] &= ~(~0ULL << (sz[1] * 8));
+ word[1] |= tmpw >> (sz[0] * 8);
+ }
+
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+
+ for (i = 0; i < loop; i++) {
+ writel((uint32_t)(off8 + (i << 3)),
+ (void *)(mem_crb+MIU_TEST_AGT_ADDR_LO));
+ writel(0,
+ (void *)(mem_crb+MIU_TEST_AGT_ADDR_HI));
+ writel(word[i] & 0xffffffff,
+ (void *)(mem_crb+MIU_TEST_AGT_WRDATA_LO));
+ writel((word[i] >> 32) & 0xffffffff,
+ (void *)(mem_crb+MIU_TEST_AGT_WRDATA_HI));
+ writel(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+ writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE,
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ temp = readl(
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+ if ((temp & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk("%s: %s Fail to write through agent\n",
+ __func__, netxen_nic_driver_name);
+ ret = -1;
+ break;
+ }
+ }
+
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ return ret;
+}
+
+int
+netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter,
+ u64 off, void *data, int size)
+{
+ unsigned long flags, mem_crb;
+ int i, j = 0, k, start, end, loop, sz[2], off0[2];
+ uint32_t temp;
+ uint64_t off8, val, word[2] = {0, 0};
+
+
+ /*
+ * 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);
+
+ 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 = (unsigned long)pci_base_offset(adapter, NETXEN_CRB_DDR_NET);
+
+ write_lock_irqsave(&adapter->adapter_lock, flags);
+ netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+
+ for (i = 0; i < loop; i++) {
+ writel((uint32_t)(off8 + (i << 3)),
+ (void *)(mem_crb+MIU_TEST_AGT_ADDR_LO));
+ writel(0,
+ (void *)(mem_crb+MIU_TEST_AGT_ADDR_HI));
+ writel(MIU_TA_CTL_ENABLE,
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+ writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE,
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ temp = readl(
+ (void *)(mem_crb+MIU_TEST_AGT_CTRL));
+ if ((temp & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk(KERN_ERR "%s: %s Fail to read through agent\n",
+ __func__, netxen_nic_driver_name);
+ break;
+ }
+
+ start = off0[i] >> 2;
+ end = (off0[i] + sz[i] - 1) >> 2;
+ for (k = start; k <= end; k++) {
+ word[i] |= ((uint64_t) readl(
+ (void *)(mem_crb +
+ MIU_TEST_AGT_RDDATA(k))) << (32*k));
+ }
+ }
+
+ netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ write_unlock_irqrestore(&adapter->adapter_lock, flags);
+
+ if (j >= MAX_CTL_CHECK)
+ return -1;
+
+ if (sz[0] == 8) {
+ val = word[0];
+ } else {
+ val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
+ ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
+ }
+
+ switch (size) {
+ case 1:
+ *(uint8_t *)data = val;
+ break;
+ case 2:
+ *(uint16_t *)data = val;
+ break;
+ case 4:
+ *(uint32_t *)data = val;
+ break;
+ case 8:
+ *(uint64_t *)data = val;
+ break;
+ }
+ DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
+ return 0;
+}
+
+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};
+
+ /*
+ * 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);
+ }
+
+ 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;
+
+ if ((size != 8) || (off0 != 0)) {
+ for (i = 0; i < loop; i++) {
+ if (adapter->pci_mem_read(adapter, off8 + (i << 3),
+ &word[i], 8))
+ return -1;
+ }
+ }
+
+ switch (size) {
+ case 1:
+ tmpw = *((uint8_t *)data);
+ break;
+ case 2:
+ tmpw = *((uint16_t *)data);
+ break;
+ case 4:
+ tmpw = *((uint32_t *)data);
+ break;
+ case 8:
+ default:
+ tmpw = *((uint64_t *)data);
+ break;
+ }
+
+ word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8));
+ word[0] |= tmpw << (off0 * 8);
+
+ if (loop == 2) {
+ word[1] &= ~(~0ULL << (sz[1] * 8));
+ word[1] |= tmpw >> (sz[0] * 8);
+ }
+
+ /*
+ * don't lock here - write_wx gets the lock if each time
+ * write_lock_irqsave(&adapter->adapter_lock, flags);
+ * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+ */
+
+ for (i = 0; i < loop; i++) {
+ temp = off8 + (i << 3);
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_ADDR_LO, &temp, 4);
+ temp = 0;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_ADDR_HI, &temp, 4);
+ temp = word[i] & 0xffffffff;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_WRDATA_LO, &temp, 4);
+ temp = (word[i] >> 32) & 0xffffffff;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_WRDATA_HI, &temp, 4);
+ temp = MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+ temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE;
+ adapter->hw_write_wx(adapter,
+ mem_crb+MIU_TEST_AGT_CTRL, &temp, 4);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ adapter->hw_read_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+ if ((temp & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk(KERN_ERR "%s: Fail to write through agent\n",
+ netxen_nic_driver_name);
+ ret = -1;
+ break;
+ }
+ }
+
+ /*
+ * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ * write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ */
+ return ret;
+}
+
+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};
+
+ /*
+ * 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_read_direct(adapter,
+ off, data, size);
+ }
+
+ 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;
+
+ /*
+ * don't lock here - write_wx gets the lock if each time
+ * write_lock_irqsave(&adapter->adapter_lock, flags);
+ * netxen_nic_pci_change_crbwindow_128M(adapter, 0);
+ */
+
+ for (i = 0; i < loop; i++) {
+ temp = off8 + (i << 3);
+ adapter->hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_ADDR_LO, &temp, 4);
+ temp = 0;
+ adapter->hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_ADDR_HI, &temp, 4);
+ temp = MIU_TA_CTL_ENABLE;
+ adapter->hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+ temp = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE;
+ adapter->hw_write_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+
+ for (j = 0; j < MAX_CTL_CHECK; j++) {
+ adapter->hw_read_wx(adapter,
+ mem_crb + MIU_TEST_AGT_CTRL, &temp, 4);
+ if ((temp & MIU_TA_CTL_BUSY) == 0)
+ break;
+ }
+
+ if (j >= MAX_CTL_CHECK) {
+ printk(KERN_ERR "%s: Fail to read through agent\n",
+ netxen_nic_driver_name);
+ break;
+ }
+
+ start = off0[i] >> 2;
+ end = (off0[i] + sz[i] - 1) >> 2;
+ for (k = start; k <= end; k++) {
+ adapter->hw_read_wx(adapter,
+ mem_crb + MIU_TEST_AGT_RDDATA(k), &temp, 4);
+ word[i] |= ((uint64_t)temp << (32 * k));
+ }
+ }
+
+ /*
+ * netxen_nic_pci_change_crbwindow_128M(adapter, 1);
+ * write_unlock_irqrestore(&adapter->adapter_lock, flags);
+ */
+
+ if (j >= MAX_CTL_CHECK)
+ return -1;
+
+ if (sz[0] == 8) {
+ val = word[0];
+ } else {
+ val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) |
+ ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8));
+ }
+
+ switch (size) {
+ case 1:
+ *(uint8_t *)data = val;
+ break;
+ case 2:
+ *(uint16_t *)data = val;
+ break;
+ case 4:
+ *(uint32_t *)data = val;
+ break;
+ case 8:
+ *(uint64_t *)data = val;
+ break;
+ }
+ DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data);
+ return 0;
+}
+
+/*
+ * Note : only 32-bit writes!
+ */
+int netxen_nic_pci_write_immediate_2M(struct netxen_adapter *adapter,
+ u64 off, u32 data)
+{
+ adapter->hw_write_wx(adapter, off, &data, 4);
+
+ return 0;
+}
+
+u32 netxen_nic_pci_read_immediate_2M(struct netxen_adapter *adapter, u64 off)
+{
+ u32 temp;
+ adapter->hw_read_wx(adapter, off, &temp, 4);
+ return temp;
+}
+
+void netxen_nic_pci_write_normalize_2M(struct netxen_adapter *adapter,
+ u64 off, u32 data)
+{
+ adapter->hw_write_wx(adapter, off, &data, 4);
+}
+
+u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off)
+{
+ u32 temp;
+ adapter->hw_read_wx(adapter, off, &temp, 4);
+ return temp;
+}
+
#if 0
int
netxen_nic_erase_pxe(struct netxen_adapter *adapter)
@@ -1003,12 +2010,25 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+ case NETXEN_BRDTYPE_P3_HMEZ:
+ case NETXEN_BRDTYPE_P3_XG_LOM:
+ case NETXEN_BRDTYPE_P3_10G_CX4:
+ case NETXEN_BRDTYPE_P3_10G_CX4_LP:
+ case NETXEN_BRDTYPE_P3_IMEZ:
+ case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
+ case NETXEN_BRDTYPE_P3_10G_XFP:
+ case NETXEN_BRDTYPE_P3_10000_BASE_T:
+
adapter->ahw.board_type = NETXEN_NIC_XGBE;
break;
case NETXEN_BRDTYPE_P1_BD:
case NETXEN_BRDTYPE_P1_SB:
case NETXEN_BRDTYPE_P1_SMAX:
case NETXEN_BRDTYPE_P1_SOCK:
+ case NETXEN_BRDTYPE_P3_REF_QG:
+ case NETXEN_BRDTYPE_P3_4_GB:
+ case NETXEN_BRDTYPE_P3_4_GB_MM:
+
adapter->ahw.board_type = NETXEN_NIC_GBE;
break;
default:
@@ -1042,25 +2062,11 @@ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)
return 0;
}
-void netxen_nic_init_niu_gb(struct netxen_adapter *adapter)
-{
- netxen_niu_gbe_init_port(adapter, adapter->physical_port);
-}
-
void
-netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off,
- int data)
+netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
+ unsigned long off, int data)
{
- void __iomem *addr;
-
- if (ADDR_IN_WINDOW1(off)) {
- writel(data, NETXEN_CRB_NORMALIZE(adapter, off));
- } else {
- netxen_nic_pci_change_crbwindow(adapter, 0);
- addr = pci_base_offset(adapter, off);
- writel(data, addr);
- netxen_nic_pci_change_crbwindow(adapter, 1);
- }
+ adapter->hw_write_wx(adapter, off, &data, 4);
}
void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
@@ -1147,12 +2153,11 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
addr += sizeof(u32);
}
- fw_major = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_FW_VERSION_MAJOR));
- fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_FW_VERSION_MINOR));
- fw_build =
- readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB));
+ adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MAJOR, &fw_major, 4);
+ adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_MINOR, &fw_minor, 4);
+ adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB, &fw_build, 4);
+
+ adapter->fw_major = fw_major;
if (adapter->portnum == 0) {
get_brd_name_by_type(board_info->board_type, brd_name);
@@ -1163,28 +2168,13 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
fw_minor, fw_build);
}
- if (fw_major != _NETXEN_NIC_LINUX_MAJOR) {
- adapter->driver_mismatch = 1;
- }
- if (fw_minor != _NETXEN_NIC_LINUX_MINOR &&
- fw_minor != (_NETXEN_NIC_LINUX_MINOR + 1)) {
+ if (NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build) <
+ NETXEN_VERSION_CODE(3, 4, 216)) {
adapter->driver_mismatch = 1;
- }
- if (adapter->driver_mismatch) {
- printk(KERN_ERR "%s: driver and firmware version mismatch\n",
- adapter->netdev->name);
+ printk(KERN_ERR "%s: firmware version %d.%d.%d unsupported\n",
+ netxen_nic_driver_name,
+ fw_major, fw_minor, fw_build);
return;
}
-
- switch (adapter->ahw.board_type) {
- case NETXEN_NIC_GBE:
- dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
- adapter->netdev->name);
- break;
- case NETXEN_NIC_XGBE:
- dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n",
- adapter->netdev->name);
- break;
- }
}
diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h
index a3ea1dd98c4..b8e0030f03d 100644
--- a/drivers/net/netxen/netxen_nic_hw.h
+++ b/drivers/net/netxen/netxen_nic_hw.h
@@ -82,19 +82,9 @@ struct netxen_adapter;
#define NETXEN_PCI_MAPSIZE_BYTES (NETXEN_PCI_MAPSIZE << 20)
-#define NETXEN_NIC_LOCKED_READ_REG(X, Y) \
- addr = pci_base_offset(adapter, X); \
- *(u32 *)Y = readl((void __iomem*) addr);
-
struct netxen_port;
void netxen_nic_set_link_parameters(struct netxen_adapter *adapter);
void netxen_nic_flash_print(struct netxen_adapter *adapter);
-int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off,
- void *data, int len);
-void netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
- unsigned long off, int data);
-int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off,
- void *data, int len);
typedef u8 netxen_ethernet_macaddr_t[6];
@@ -432,7 +422,8 @@ typedef enum {
/* Promiscous mode options (GbE mode only) */
typedef enum {
NETXEN_NIU_PROMISC_MODE = 0,
- NETXEN_NIU_NON_PROMISC_MODE
+ NETXEN_NIU_NON_PROMISC_MODE,
+ NETXEN_NIU_ALLMULTI_MODE
} netxen_niu_prom_mode_t;
/*
@@ -478,42 +469,6 @@ typedef enum {
#define netxen_xg_soft_reset(config_word) \
((config_word) |= 1 << 4)
-/*
- * MAC Control Register
- *
- * Bit 0-1 : id_pool0
- * Bit 2 : enable_xtnd0
- * Bit 4-5 : id_pool1
- * Bit 6 : enable_xtnd1
- * Bit 8-9 : id_pool2
- * Bit 10 : enable_xtnd2
- * Bit 12-13 : id_pool3
- * Bit 14 : enable_xtnd3
- * Bit 24-25 : mode_select
- * Bit 28-31 : enable_pool
- */
-
-#define netxen_nic_mcr_set_id_pool0(config, val) \
- ((config) |= ((val) &0x03))
-#define netxen_nic_mcr_set_enable_xtnd0(config) \
- ((config) |= 1 << 3)
-#define netxen_nic_mcr_set_id_pool1(config, val) \
- ((config) |= (((val) & 0x03) << 4))
-#define netxen_nic_mcr_set_enable_xtnd1(config) \
- ((config) |= 1 << 6)
-#define netxen_nic_mcr_set_id_pool2(config, val) \
- ((config) |= (((val) & 0x03) << 8))
-#define netxen_nic_mcr_set_enable_xtnd2(config) \
- ((config) |= 1 << 10)
-#define netxen_nic_mcr_set_id_pool3(config, val) \
- ((config) |= (((val) & 0x03) << 12))
-#define netxen_nic_mcr_set_enable_xtnd3(config) \
- ((config) |= 1 << 14)
-#define netxen_nic_mcr_set_mode_select(config, val) \
- ((config) |= (((val) & 0x03) << 24))
-#define netxen_nic_mcr_set_enable_pool(config, val) \
- ((config) |= (((val) & 0x0f) << 28))
-
/* Set promiscuous mode for a GbE interface */
int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
netxen_niu_prom_mode_t mode);
@@ -538,4 +493,15 @@ 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;
+ unsigned end_128M;
+ unsigned start_2M;
+} crb_128M_2M_sub_block_map_t;
+
+typedef struct {
+ crb_128M_2M_sub_block_map_t sub_block[16];
+} crb_128M_2M_block_map_t;
+
#endif /* __NETXEN_NIC_HW_H_ */
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 70d1b22ced2..01ab31b34a8 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -42,8 +42,6 @@ struct crb_addr_pair {
u32 data;
};
-unsigned long last_schedule_time;
-
#define NETXEN_MAX_CRB_XFORM 60
static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM];
#define NETXEN_ADDR_ERROR (0xffffffff)
@@ -117,6 +115,8 @@ static void crb_addr_transform_setup(void)
crb_addr_transform(C2C1);
crb_addr_transform(C2C0);
crb_addr_transform(SMB);
+ crb_addr_transform(OCM0);
+ crb_addr_transform(I2C0);
}
int netxen_init_firmware(struct netxen_adapter *adapter)
@@ -124,15 +124,15 @@ int netxen_init_firmware(struct netxen_adapter *adapter)
u32 state = 0, loops = 0, err = 0;
/* Window 1 call */
- state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+ state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
if (state == PHAN_INITIALIZE_ACK)
return 0;
while (state != PHAN_INITIALIZE_COMPLETE && loops < 2000) {
- udelay(100);
+ msleep(1);
/* Window 1 call */
- state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+ state = adapter->pci_read_normalize(adapter, CRB_CMDPEG_STATE);
loops++;
}
@@ -143,64 +143,193 @@ int netxen_init_firmware(struct netxen_adapter *adapter)
return err;
}
/* Window 1 call */
- writel(INTR_SCHEME_PERPORT,
- NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_HOST));
- writel(MSI_MODE_MULTIFUNC,
- NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_HOST));
- writel(MPORT_MULTI_FUNCTION_MODE,
- NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE));
- writel(PHAN_INITIALIZE_ACK,
- NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+ adapter->pci_write_normalize(adapter,
+ CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT);
+ adapter->pci_write_normalize(adapter,
+ CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC);
+ adapter->pci_write_normalize(adapter,
+ CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE);
+ adapter->pci_write_normalize(adapter,
+ CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
return err;
}
-#define NETXEN_ADDR_LIMIT 0xffffffffULL
+void netxen_release_rx_buffers(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ struct netxen_rx_buffer *rx_buf;
+ int i, ctxid, ring;
+
+ for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
+ recv_ctx = &adapter->recv_ctx[ctxid];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ for (i = 0; i < rds_ring->max_rx_desc_count; ++i) {
+ rx_buf = &(rds_ring->rx_buf_arr[i]);
+ if (rx_buf->state == NETXEN_BUFFER_FREE)
+ continue;
+ pci_unmap_single(adapter->pdev,
+ rx_buf->dma,
+ rds_ring->dma_size,
+ PCI_DMA_FROMDEVICE);
+ if (rx_buf->skb != NULL)
+ dev_kfree_skb_any(rx_buf->skb);
+ }
+ }
+ }
+}
-void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr,
- struct pci_dev **used_dev)
+void netxen_release_tx_buffers(struct netxen_adapter *adapter)
{
- void *addr;
+ struct netxen_cmd_buffer *cmd_buf;
+ struct netxen_skb_frag *buffrag;
+ int i, j;
+
+ cmd_buf = adapter->cmd_buf_arr;
+ for (i = 0; i < adapter->max_tx_desc_count; i++) {
+ buffrag = cmd_buf->frag_array;
+ if (buffrag->dma) {
+ pci_unmap_single(adapter->pdev, buffrag->dma,
+ buffrag->length, PCI_DMA_TODEVICE);
+ buffrag->dma = 0ULL;
+ }
+ for (j = 0; j < cmd_buf->frag_count; j++) {
+ buffrag++;
+ if (buffrag->dma) {
+ pci_unmap_page(adapter->pdev, buffrag->dma,
+ buffrag->length,
+ PCI_DMA_TODEVICE);
+ buffrag->dma = 0ULL;
+ }
+ }
+ /* Free the skb we received in netxen_nic_xmit_frame */
+ if (cmd_buf->skb) {
+ dev_kfree_skb_any(cmd_buf->skb);
+ cmd_buf->skb = NULL;
+ }
+ cmd_buf++;
+ }
+}
- addr = pci_alloc_consistent(pdev, sz, ptr);
- if ((unsigned long long)(*ptr) < NETXEN_ADDR_LIMIT) {
- *used_dev = pdev;
- return addr;
+void netxen_free_sw_resources(struct netxen_adapter *adapter)
+{
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ int ctx, ring;
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ctx++) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ if (rds_ring->rx_buf_arr) {
+ vfree(rds_ring->rx_buf_arr);
+ rds_ring->rx_buf_arr = NULL;
+ }
+ }
}
- pci_free_consistent(pdev, sz, addr, *ptr);
- addr = pci_alloc_consistent(NULL, sz, ptr);
- *used_dev = NULL;
- return addr;
+ if (adapter->cmd_buf_arr)
+ vfree(adapter->cmd_buf_arr);
+ return;
}
-void netxen_initialize_adapter_sw(struct netxen_adapter *adapter)
+int netxen_alloc_sw_resources(struct netxen_adapter *adapter)
{
- int ctxid, ring;
- u32 i;
- u32 num_rx_bufs = 0;
- struct netxen_rcv_desc_ctx *rcv_desc;
+ struct netxen_recv_context *recv_ctx;
+ struct nx_host_rds_ring *rds_ring;
+ struct netxen_rx_buffer *rx_buf;
+ int ctx, ring, i, num_rx_bufs;
- DPRINTK(INFO, "initializing some queues: %p\n", adapter);
- for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- struct netxen_rx_buffer *rx_buf;
- rcv_desc = &adapter->recv_ctx[ctxid].rcv_desc[ring];
- rcv_desc->begin_alloc = 0;
- rx_buf = rcv_desc->rx_buf_arr;
- num_rx_bufs = rcv_desc->max_rx_desc_count;
+ struct netxen_cmd_buffer *cmd_buf_arr;
+ struct net_device *netdev = adapter->netdev;
+
+ cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
+ if (cmd_buf_arr == NULL) {
+ printk(KERN_ERR "%s: Failed to allocate cmd buffer ring\n",
+ netdev->name);
+ return -ENOMEM;
+ }
+ memset(cmd_buf_arr, 0, TX_RINGSIZE);
+ adapter->cmd_buf_arr = cmd_buf_arr;
+
+ for (ctx = 0; ctx < MAX_RCV_CTX; ctx++) {
+ recv_ctx = &adapter->recv_ctx[ctx];
+ for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+ rds_ring = &recv_ctx->rds_rings[ring];
+ switch (RCV_DESC_TYPE(ring)) {
+ case RCV_DESC_NORMAL:
+ rds_ring->max_rx_desc_count =
+ adapter->max_rx_desc_count;
+ rds_ring->flags = RCV_DESC_NORMAL;
+ if (adapter->ahw.cut_through) {
+ rds_ring->dma_size =
+ NX_CT_DEFAULT_RX_BUF_LEN;
+ rds_ring->skb_size =
+ NX_CT_DEFAULT_RX_BUF_LEN;
+ } else {
+ rds_ring->dma_size = RX_DMA_MAP_LEN;
+ rds_ring->skb_size =
+ MAX_RX_BUFFER_LENGTH;
+ }
+ break;
+
+ case RCV_DESC_JUMBO:
+ rds_ring->max_rx_desc_count =
+ adapter->max_jumbo_rx_desc_count;
+ rds_ring->flags = RCV_DESC_JUMBO;
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ rds_ring->dma_size =
+ NX_P3_RX_JUMBO_BUF_MAX_LEN;
+ else
+ rds_ring->dma_size =
+ NX_P2_RX_JUMBO_BUF_MAX_LEN;
+ rds_ring->skb_size =
+ rds_ring->dma_size + NET_IP_ALIGN;
+ break;
+
+ case RCV_RING_LRO:
+ rds_ring->max_rx_desc_count =
+ adapter->max_lro_rx_desc_count;
+ rds_ring->flags = RCV_DESC_LRO;
+ rds_ring->dma_size = RX_LRO_DMA_MAP_LEN;
+ rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
+ break;
+
+ }
+ rds_ring->rx_buf_arr = (struct netxen_rx_buffer *)
+ vmalloc(RCV_BUFFSIZE);
+ if (rds_ring->rx_buf_arr == NULL) {
+ printk(KERN_ERR "%s: Failed to allocate "
+ "rx buffer ring %d\n",
+ netdev->name, ring);
+ /* free whatever was already allocated */
+ goto err_out;
+ }
+ memset(rds_ring->rx_buf_arr, 0, RCV_BUFFSIZE);
+ INIT_LIST_HEAD(&rds_ring->free_list);
+ rds_ring->begin_alloc = 0;
/*
* Now go through all of them, set reference handles
* and put them in the queues.
*/
+ num_rx_bufs = rds_ring->max_rx_desc_count;
+ rx_buf = rds_ring->rx_buf_arr;
for (i = 0; i < num_rx_bufs; i++) {
+ list_add_tail(&rx_buf->list,
+ &rds_ring->free_list);
rx_buf->ref_handle = i;
rx_buf->state = NETXEN_BUFFER_FREE;
- DPRINTK(INFO, "Rx buf:ctx%d i(%d) rx_buf:"
- "%p\n", ctxid, i, rx_buf);
rx_buf++;
}
}
}
+
+ return 0;
+
+err_out:
+ netxen_free_sw_resources(adapter);
+ return -ENOMEM;
}
void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
@@ -211,14 +340,12 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
netxen_niu_gbe_enable_phy_interrupts;
adapter->disable_phy_interrupts =
netxen_niu_gbe_disable_phy_interrupts;
- adapter->handle_phy_intr = netxen_nic_gbe_handle_phy_intr;
adapter->macaddr_set = netxen_niu_macaddr_set;
adapter->set_mtu = netxen_nic_set_mtu_gb;
adapter->set_promisc = netxen_niu_set_promiscuous_mode;
- adapter->unset_promisc = netxen_niu_set_promiscuous_mode;
adapter->phy_read = netxen_niu_gbe_phy_read;
adapter->phy_write = netxen_niu_gbe_phy_write;
- adapter->init_niu = netxen_nic_init_niu_gb;
+ adapter->init_port = netxen_niu_gbe_init_port;
adapter->stop_port = netxen_niu_disable_gbe_port;
break;
@@ -227,12 +354,10 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
netxen_niu_xgbe_enable_phy_interrupts;
adapter->disable_phy_interrupts =
netxen_niu_xgbe_disable_phy_interrupts;
- adapter->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr;
adapter->macaddr_set = netxen_niu_xg_macaddr_set;
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->unset_promisc = netxen_niu_xg_set_promiscuous_mode;
adapter->stop_port = netxen_niu_disable_xg_port;
break;
@@ -270,7 +395,9 @@ static u32 netxen_decode_crb_addr(u32 addr)
static long rom_max_timeout = 100;
static long rom_lock_timeout = 10000;
+#if 0
static long rom_write_timeout = 700;
+#endif
static int rom_lock(struct netxen_adapter *adapter)
{
@@ -319,6 +446,7 @@ static int netxen_wait_rom_done(struct netxen_adapter *adapter)
return 0;
}
+#if 0
static int netxen_rom_wren(struct netxen_adapter *adapter)
{
/* Set write enable latch in ROM status register */
@@ -348,6 +476,7 @@ static int netxen_do_rom_rdsr(struct netxen_adapter *adapter)
}
return netxen_rdcrbreg(adapter, NETXEN_ROMUSB_ROM_RDATA);
}
+#endif
static void netxen_rom_unlock(struct netxen_adapter *adapter)
{
@@ -358,6 +487,7 @@ static void netxen_rom_unlock(struct netxen_adapter *adapter)
}
+#if 0
static int netxen_rom_wip_poll(struct netxen_adapter *adapter)
{
long timeout = 0;
@@ -393,6 +523,7 @@ static int do_rom_fast_write(struct netxen_adapter *adapter, int addr,
return netxen_rom_wip_poll(adapter);
}
+#endif
static int do_rom_fast_read(struct netxen_adapter *adapter,
int addr, int *valp)
@@ -475,7 +606,6 @@ int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data)
netxen_rom_unlock(adapter);
return ret;
}
-#endif /* 0 */
static int do_rom_fast_write_words(struct netxen_adapter *adapter,
int addr, u8 *bytes, size_t size)
@@ -740,28 +870,25 @@ int netxen_flash_unlock(struct netxen_adapter *adapter)
return ret;
}
+#endif /* 0 */
#define NETXEN_BOARDTYPE 0x4008
#define NETXEN_BOARDNUM 0x400c
#define NETXEN_CHIPNUM 0x4010
-#define NETXEN_ROMBUS_RESET 0xFFFFFFFF
-#define NETXEN_ROM_FIRST_BARRIER 0x800000000ULL
-#define NETXEN_ROM_FOUND_INIT 0x400
int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
{
int addr, val;
- int n, i;
- int init_delay = 0;
+ int i, init_delay = 0;
struct crb_addr_pair *buf;
+ unsigned offset, n;
u32 off;
/* resetall */
netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
- NETXEN_ROMBUS_RESET);
+ 0xffffffff);
if (verbose) {
- int val;
if (netxen_rom_fast_read(adapter, NETXEN_BOARDTYPE, &val) == 0)
printk("P2 ROM board type: 0x%08x\n", val);
else
@@ -776,117 +903,141 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
printk("Could not read chip number\n");
}
- if (netxen_rom_fast_read(adapter, 0, &n) == 0
- && (n & NETXEN_ROM_FIRST_BARRIER)) {
- n &= ~NETXEN_ROM_ROUNDUP;
- if (n < NETXEN_ROM_FOUND_INIT) {
- if (verbose)
- printk("%s: %d CRB init values found"
- " in ROM.\n", netxen_nic_driver_name, n);
- } else {
- printk("%s:n=0x%x Error! NetXen card flash not"
- " initialized.\n", __FUNCTION__, n);
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
+ (n != 0xcafecafeUL) ||
+ netxen_rom_fast_read(adapter, 4, &n) != 0) {
+ printk(KERN_ERR "%s: ERROR Reading crb_init area: "
+ "n: %08x\n", netxen_nic_driver_name, n);
return -EIO;
}
- buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
- if (buf == NULL) {
- printk("%s: netxen_pinit_from_rom: Unable to calloc "
- "memory.\n", netxen_nic_driver_name);
- return -ENOMEM;
- }
- for (i = 0; i < n; i++) {
- if (netxen_rom_fast_read(adapter, 8 * i + 4, &val) != 0
- || netxen_rom_fast_read(adapter, 8 * i + 8,
- &addr) != 0)
- return -EIO;
-
- buf[i].addr = addr;
- buf[i].data = val;
-
- if (verbose)
- printk("%s: PCI: 0x%08x == 0x%08x\n",
- netxen_nic_driver_name, (unsigned int)
- netxen_decode_crb_addr(addr), val);
+ offset = n & 0xffffU;
+ n = (n >> 16) & 0xffffU;
+ } else {
+ if (netxen_rom_fast_read(adapter, 0, &n) != 0 ||
+ !(n & 0x80000000)) {
+ printk(KERN_ERR "%s: ERROR Reading crb_init area: "
+ "n: %08x\n", netxen_nic_driver_name, n);
+ return -EIO;
}
- for (i = 0; i < n; i++) {
+ offset = 1;
+ n &= ~0x80000000;
+ }
+
+ if (n < 1024) {
+ if (verbose)
+ printk(KERN_DEBUG "%s: %d CRB init values found"
+ " in ROM.\n", netxen_nic_driver_name, n);
+ } else {
+ printk(KERN_ERR "%s:n=0x%x Error! NetXen card flash not"
+ " initialized.\n", __func__, n);
+ return -EIO;
+ }
+
+ buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
+ if (buf == NULL) {
+ printk("%s: netxen_pinit_from_rom: Unable to calloc memory.\n",
+ netxen_nic_driver_name);
+ return -ENOMEM;
+ }
+ for (i = 0; i < n; i++) {
+ if (netxen_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
+ netxen_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0)
+ return -EIO;
+
+ buf[i].addr = addr;
+ buf[i].data = val;
- off = netxen_decode_crb_addr(buf[i].addr);
- if (off == NETXEN_ADDR_ERROR) {
- printk(KERN_ERR"CRB init value out of range %x\n",
+ if (verbose)
+ printk(KERN_DEBUG "%s: PCI: 0x%08x == 0x%08x\n",
+ netxen_nic_driver_name,
+ (u32)netxen_decode_crb_addr(addr), val);
+ }
+ for (i = 0; i < n; i++) {
+
+ off = netxen_decode_crb_addr(buf[i].addr);
+ if (off == NETXEN_ADDR_ERROR) {
+ printk(KERN_ERR"CRB init value out of range %x\n",
buf[i].addr);
+ continue;
+ }
+ off += NETXEN_PCI_CRBSPACE;
+ /* skipping cold reboot MAGIC */
+ if (off == NETXEN_CAM_RAM(0x1fc))
+ continue;
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ /* do not reset PCI */
+ if (off == (ROMUSB_GLB + 0xbc))
continue;
- }
- off += NETXEN_PCI_CRBSPACE;
- /* skipping cold reboot MAGIC */
- if (off == NETXEN_CAM_RAM(0x1fc))
+ if (off == (NETXEN_CRB_PEG_NET_1 + 0x18))
+ buf[i].data = 0x1020;
+ /* skip the function enable register */
+ if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION))
+ continue;
+ if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION2))
continue;
+ if ((off & 0x0ff00000) == NETXEN_CRB_SMB)
+ continue;
+ }
- /* After writing this register, HW needs time for CRB */
- /* to quiet down (else crb_window returns 0xffffffff) */
- if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
- init_delay = 1;
+ if (off == NETXEN_ADDR_ERROR) {
+ printk(KERN_ERR "%s: Err: Unknown addr: 0x%08x\n",
+ netxen_nic_driver_name, buf[i].addr);
+ continue;
+ }
+
+ /* After writing this register, HW needs time for CRB */
+ /* to quiet down (else crb_window returns 0xffffffff) */
+ if (off == NETXEN_ROMUSB_GLB_SW_RESET) {
+ init_delay = 1;
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
/* hold xdma in reset also */
buf[i].data = NETXEN_NIC_XDMA_RESET;
}
+ }
- if (ADDR_IN_WINDOW1(off)) {
- writel(buf[i].data,
- NETXEN_CRB_NORMALIZE(adapter, off));
- } else {
- netxen_nic_pci_change_crbwindow(adapter, 0);
- writel(buf[i].data,
- pci_base_offset(adapter, off));
+ adapter->hw_write_wx(adapter, off, &buf[i].data, 4);
- netxen_nic_pci_change_crbwindow(adapter, 1);
- }
- if (init_delay == 1) {
- msleep(1000);
- init_delay = 0;
- }
- msleep(1);
+ if (init_delay == 1) {
+ msleep(1000);
+ init_delay = 0;
}
- kfree(buf);
+ msleep(1);
+ }
+ kfree(buf);
- /* disable_peg_cache_all */
+ /* disable_peg_cache_all */
- /* unreset_net_cache */
- netxen_nic_hw_read_wx(adapter, NETXEN_ROMUSB_GLB_SW_RESET, &val,
- 4);
- netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET,
- (val & 0xffffff0f));
- /* p2dn replyCount */
- netxen_crb_writelit_adapter(adapter,
- NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
- /* disable_peg_cache 0 */
+ /* unreset_net_cache */
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ adapter->hw_read_wx(adapter,
+ NETXEN_ROMUSB_GLB_SW_RESET, &val, 4);
netxen_crb_writelit_adapter(adapter,
- NETXEN_CRB_PEG_NET_D + 0x4c, 8);
- /* disable_peg_cache 1 */
- netxen_crb_writelit_adapter(adapter,
- NETXEN_CRB_PEG_NET_I + 0x4c, 8);
-
- /* peg_clr_all */
-
- /* peg_clr 0 */
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8,
- 0);
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc,
- 0);
- /* peg_clr 1 */
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8,
- 0);
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc,
- 0);
- /* peg_clr 2 */
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8,
- 0);
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc,
- 0);
- /* peg_clr 3 */
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8,
- 0);
- netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc,
- 0);
+ NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f));
}
+
+ /* p2dn replyCount */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e);
+ /* disable_peg_cache 0 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8);
+ /* disable_peg_cache 1 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8);
+
+ /* peg_clr_all */
+
+ /* peg_clr 0 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0);
+ /* peg_clr 1 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0);
+ /* peg_clr 2 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0);
+ /* peg_clr 3 */
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0);
+ netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0);
return 0;
}
@@ -897,12 +1048,12 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
uint32_t lo;
adapter->dummy_dma.addr =
- pci_alloc_consistent(adapter->ahw.pdev,
+ 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",
- __FUNCTION__);
+ __func__);
return -ENOMEM;
}
@@ -910,8 +1061,13 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter)
hi = (addr >> 32) & 0xffffffff;
lo = addr & 0xffffffff;
- writel(hi, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI));
- writel(lo, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO));
+ adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi);
+ adapter->pci_write_normalize(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ uint32_t temp = 0;
+ adapter->hw_write_wx(adapter, CRB_HOST_DUMMY_BUF, &temp, 4);
+ }
return 0;
}
@@ -931,7 +1087,7 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter)
} while (--i);
if (i) {
- pci_free_consistent(adapter->ahw.pdev,
+ pci_free_consistent(adapter->pdev,
NETXEN_HOST_DUMMY_DMA_SIZE,
adapter->dummy_dma.addr,
adapter->dummy_dma.phys_addr);
@@ -946,22 +1102,24 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter)
int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
{
u32 val = 0;
- int retries = 30;
+ int retries = 60;
if (!pegtune_val) {
do {
- val = readl(NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMDPEG_STATE));
- pegtune_val = readl(NETXEN_CRB_NORMALIZE
- (adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
+ val = adapter->pci_read_normalize(adapter,
+ CRB_CMDPEG_STATE);
if (val == PHAN_INITIALIZE_COMPLETE ||
val == PHAN_INITIALIZE_ACK)
return 0;
- msleep(1000);
+ msleep(500);
+
} while (--retries);
+
if (!retries) {
+ pegtune_val = adapter->pci_read_normalize(adapter,
+ NETXEN_ROMUSB_GLB_PEGTUNE_DONE);
printk(KERN_WARNING "netxen_phantom_init: init failed, "
"pegtune_val=%x\n", pegtune_val);
return -1;
@@ -971,58 +1129,61 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
return 0;
}
-static int netxen_nic_check_temp(struct netxen_adapter *adapter)
+int netxen_receive_peg_ready(struct netxen_adapter *adapter)
{
- struct net_device *netdev = adapter->netdev;
- uint32_t temp, temp_state, temp_val;
- int rv = 0;
-
- temp = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_TEMP_STATE));
-
- temp_state = nx_get_temp_state(temp);
- temp_val = nx_get_temp_val(temp);
-
- if (temp_state == NX_TEMP_PANIC) {
- printk(KERN_ALERT
- "%s: Device temperature %d degrees C exceeds"
- " maximum allowed. Hardware has been shut down.\n",
- netxen_nic_driver_name, temp_val);
-
- netif_carrier_off(netdev);
- netif_stop_queue(netdev);
- rv = 1;
- } else if (temp_state == NX_TEMP_WARN) {
- if (adapter->temp == NX_TEMP_NORMAL) {
- printk(KERN_ALERT
- "%s: Device temperature %d degrees C "
- "exceeds operating range."
- " Immediate action needed.\n",
- netxen_nic_driver_name, temp_val);
- }
- } else {
- if (adapter->temp == NX_TEMP_WARN) {
- printk(KERN_INFO
- "%s: Device temperature is now %d degrees C"
- " in normal range.\n", netxen_nic_driver_name,
- temp_val);
- }
+ u32 val = 0;
+ int retries = 2000;
+
+ do {
+ val = adapter->pci_read_normalize(adapter, CRB_RCVPEG_STATE);
+
+ if (val == PHAN_PEG_RCV_INITIALIZED)
+ return 0;
+
+ msleep(10);
+
+ } while (--retries);
+
+ if (!retries) {
+ printk(KERN_ERR "Receive Peg initialization not "
+ "complete, state: 0x%x.\n", val);
+ return -EIO;
}
- adapter->temp = temp_state;
- return rv;
+
+ return 0;
}
-void netxen_watchdog_task(struct work_struct *work)
+static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter,
+ struct nx_host_rds_ring *rds_ring, u16 index, u16 cksum)
{
- struct netxen_adapter *adapter =
- container_of(work, struct netxen_adapter, watchdog_task);
+ struct netxen_rx_buffer *buffer;
+ struct sk_buff *skb;
- if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter))
- return;
+ buffer = &rds_ring->rx_buf_arr[index];
+
+ pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
+ PCI_DMA_FROMDEVICE);
- if (adapter->handle_phy_intr)
- adapter->handle_phy_intr(adapter);
+ skb = buffer->skb;
+ if (!skb)
+ goto no_skb;
- mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+ if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) {
+ adapter->stats.csummed++;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ } else
+ skb->ip_summed = CHECKSUM_NONE;
+
+ skb->dev = adapter->netdev;
+
+ buffer->skb = NULL;
+
+no_skb:
+ buffer->state = NETXEN_BUFFER_FREE;
+ buffer->lro_current_frags = 0;
+ buffer->lro_expected_frags = 0;
+ list_add_tail(&buffer->list, &rds_ring->free_list);
+ return skb;
}
/*
@@ -1031,9 +1192,8 @@ void netxen_watchdog_task(struct work_struct *work)
* invoke the routine to send more rx buffers to the Phantom...
*/
static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
- struct status_desc *desc)
+ struct status_desc *desc, struct status_desc *frag_desc)
{
- struct pci_dev *pdev = adapter->pdev;
struct net_device *netdev = adapter->netdev;
u64 sts_data = le64_to_cpu(desc->status_desc_data);
int index = netxen_get_sts_refhandle(sts_data);
@@ -1042,8 +1202,8 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
struct sk_buff *skb;
u32 length = netxen_get_sts_totallength(sts_data);
u32 desc_ctx;
- struct netxen_rcv_desc_ctx *rcv_desc;
- int ret;
+ u16 pkt_offset = 0, cksum;
+ struct nx_host_rds_ring *rds_ring;
desc_ctx = netxen_get_sts_type(sts_data);
if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) {
@@ -1052,13 +1212,13 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
return;
}
- rcv_desc = &recv_ctx->rcv_desc[desc_ctx];
- if (unlikely(index > rcv_desc->max_rx_desc_count)) {
+ rds_ring = &recv_ctx->rds_rings[desc_ctx];
+ if (unlikely(index > rds_ring->max_rx_desc_count)) {
DPRINTK(ERR, "Got a buffer index:%x Max is %x\n",
- index, rcv_desc->max_rx_desc_count);
+ index, rds_ring->max_rx_desc_count);
return;
}
- buffer = &rcv_desc->rx_buf_arr[index];
+ buffer = &rds_ring->rx_buf_arr[index];
if (desc_ctx == RCV_DESC_LRO_CTXID) {
buffer->lro_current_frags++;
if (netxen_get_sts_desc_lro_last_frag(desc)) {
@@ -1079,43 +1239,52 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
}
}
- pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size,
- PCI_DMA_FROMDEVICE);
+ cksum = netxen_get_sts_status(sts_data);
- skb = (struct sk_buff *)buffer->skb;
-
- if (likely(adapter->rx_csum &&
- netxen_get_sts_status(sts_data) == STATUS_CKSUM_OK)) {
- adapter->stats.csummed++;
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- } else
- skb->ip_summed = CHECKSUM_NONE;
+ skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum);
+ if (!skb)
+ return;
- skb->dev = netdev;
if (desc_ctx == RCV_DESC_LRO_CTXID) {
/* True length was only available on the last pkt */
skb_put(skb, buffer->lro_length);
} else {
- skb_put(skb, length);
+ if (length > rds_ring->skb_size)
+ skb_put(skb, rds_ring->skb_size);
+ else
+ skb_put(skb, length);
+
+ pkt_offset = netxen_get_sts_pkt_offset(sts_data);
+ if (pkt_offset)
+ skb_pull(skb, pkt_offset);
}
skb->protocol = eth_type_trans(skb, netdev);
- ret = netif_receive_skb(skb);
- netdev->last_rx = jiffies;
-
- rcv_desc->rcv_pending--;
-
/*
- * We just consumed one buffer so post a buffer.
+ * rx buffer chaining is disabled, walk and free
+ * any spurious rx buffer chain.
*/
- buffer->skb = NULL;
- buffer->state = NETXEN_BUFFER_FREE;
- buffer->lro_current_frags = 0;
- buffer->lro_expected_frags = 0;
+ if (frag_desc) {
+ u16 i, nr_frags = desc->nr_frags;
+
+ dev_kfree_skb_any(skb);
+ for (i = 0; i < nr_frags; i++) {
+ index = frag_desc->frag_handles[i];
+ skb = netxen_process_rxbuf(adapter,
+ rds_ring, index, cksum);
+ if (skb)
+ dev_kfree_skb_any(skb);
+ }
+ adapter->stats.rxdropped++;
+ } else {
- adapter->stats.no_rcv++;
- adapter->stats.rxbytes += length;
+ netif_receive_skb(skb);
+ netdev->last_rx = jiffies;
+
+ adapter->stats.no_rcv++;
+ adapter->stats.rxbytes += length;
+ }
}
/* Process Receive status ring */
@@ -1123,10 +1292,11 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
{
struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
struct status_desc *desc_head = recv_ctx->rcv_status_desc_head;
- struct status_desc *desc; /* used to read status desc here */
+ struct status_desc *desc, *frag_desc;
u32 consumer = recv_ctx->status_rx_consumer;
- u32 producer = 0;
int count = 0, ring;
+ u64 sts_data;
+ u16 opcode;
while (count < max) {
desc = &desc_head[consumer];
@@ -1135,24 +1305,38 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
netxen_get_sts_owner(desc));
break;
}
- netxen_process_rcv(adapter, ctxid, desc);
+
+ sts_data = le64_to_cpu(desc->status_desc_data);
+ opcode = netxen_get_sts_opcode(sts_data);
+ frag_desc = NULL;
+ if (opcode == NETXEN_NIC_RXPKT_DESC) {
+ if (desc->nr_frags) {
+ consumer = get_next_index(consumer,
+ adapter->max_rx_desc_count);
+ frag_desc = &desc_head[consumer];
+ netxen_set_sts_owner(frag_desc,
+ STATUS_OWNER_PHANTOM);
+ }
+ }
+
+ netxen_process_rcv(adapter, ctxid, desc, frag_desc);
+
netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM);
- consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1);
+
+ consumer = get_next_index(consumer,
+ adapter->max_rx_desc_count);
count++;
}
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++)
+ for (ring = 0; ring < adapter->max_rds_rings; ring++)
netxen_post_rx_buffers_nodb(adapter, ctxid, ring);
/* update the consumer index in phantom */
if (count) {
recv_ctx->status_rx_consumer = consumer;
- recv_ctx->status_rx_producer = producer;
/* Window = 1 */
- writel(consumer,
- NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers[adapter->portnum].
- crb_rcv_status_consumer));
+ adapter->pci_write_normalize(adapter,
+ recv_ctx->crb_sts_consumer, consumer);
}
return count;
@@ -1231,10 +1415,10 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter)
*/
void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
{
- struct pci_dev *pdev = adapter->ahw.pdev;
+ struct pci_dev *pdev = adapter->pdev;
struct sk_buff *skb;
struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
- struct netxen_rcv_desc_ctx *rcv_desc = NULL;
+ struct nx_host_rds_ring *rds_ring = NULL;
uint producer;
struct rcv_desc *pdesc;
struct netxen_rx_buffer *buffer;
@@ -1242,41 +1426,36 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
int index = 0;
netxen_ctx_msg msg = 0;
dma_addr_t dma;
+ struct list_head *head;
- rcv_desc = &recv_ctx->rcv_desc[ringid];
+ rds_ring = &recv_ctx->rds_rings[ringid];
+
+ producer = rds_ring->producer;
+ index = rds_ring->begin_alloc;
+ head = &rds_ring->free_list;
- producer = rcv_desc->producer;
- index = rcv_desc->begin_alloc;
- buffer = &rcv_desc->rx_buf_arr[index];
/* We can start writing rx descriptors into the phantom memory. */
- while (buffer->state == NETXEN_BUFFER_FREE) {
- skb = dev_alloc_skb(rcv_desc->skb_size);
+ while (!list_empty(head)) {
+
+ skb = dev_alloc_skb(rds_ring->skb_size);
if (unlikely(!skb)) {
- /*
- * TODO
- * We need to schedule the posting of buffers to the pegs.
- */
- rcv_desc->begin_alloc = index;
- DPRINTK(ERR, "netxen_post_rx_buffers: "
- " allocated only %d buffers\n", count);
+ rds_ring->begin_alloc = index;
break;
}
+ buffer = list_entry(head->next, struct netxen_rx_buffer, list);
+ list_del(&buffer->list);
+
count++; /* now there should be no failure */
- pdesc = &rcv_desc->desc_head[producer];
+ pdesc = &rds_ring->desc_head[producer];
-#if defined(XGB_DEBUG)
- *(unsigned long *)(skb->head) = 0xc0debabe;
- if (skb_is_nonlinear(skb)) {
- printk("Allocated SKB @%p is nonlinear\n");
- }
-#endif
- skb_reserve(skb, 2);
+ if (!adapter->ahw.cut_through)
+ skb_reserve(skb, 2);
/* This will be setup when we receive the
* buffer after it has been filled FSL TBD TBD
* skb->dev = netdev;
*/
- dma = pci_map_single(pdev, skb->data, rcv_desc->dma_size,
+ dma = pci_map_single(pdev, skb->data, rds_ring->dma_size,
PCI_DMA_FROMDEVICE);
pdesc->addr_buffer = cpu_to_le64(dma);
buffer->skb = skb;
@@ -1284,112 +1463,101 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
buffer->dma = dma;
/* make a rcv descriptor */
pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
- pdesc->buffer_length = cpu_to_le32(rcv_desc->dma_size);
+ pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
DPRINTK(INFO, "done writing descripter\n");
producer =
- get_next_index(producer, rcv_desc->max_rx_desc_count);
- index = get_next_index(index, rcv_desc->max_rx_desc_count);
- buffer = &rcv_desc->rx_buf_arr[index];
+ get_next_index(producer, rds_ring->max_rx_desc_count);
+ index = get_next_index(index, rds_ring->max_rx_desc_count);
}
/* if we did allocate buffers, then write the count to Phantom */
if (count) {
- rcv_desc->begin_alloc = index;
- rcv_desc->rcv_pending += count;
- rcv_desc->producer = producer;
+ rds_ring->begin_alloc = index;
+ rds_ring->producer = producer;
/* Window = 1 */
- writel((producer - 1) &
- (rcv_desc->max_rx_desc_count - 1),
- NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers[
- adapter->portnum].
- rcv_desc_crb[ringid].
- crb_rcv_producer_offset));
+ adapter->pci_write_normalize(adapter,
+ rds_ring->crb_rcv_producer,
+ (producer-1) & (rds_ring->max_rx_desc_count-1));
+
+ if (adapter->fw_major < 4) {
/*
* Write a doorbell msg to tell phanmon of change in
* receive ring producer
+ * Only for firmware version < 4.0.0
*/
netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID);
netxen_set_msg_privid(msg);
netxen_set_msg_count(msg,
((producer -
- 1) & (rcv_desc->
+ 1) & (rds_ring->
max_rx_desc_count - 1)));
netxen_set_msg_ctxid(msg, adapter->portnum);
netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid));
writel(msg,
DB_NORMALIZE(adapter,
NETXEN_RCV_PRODUCER_OFFSET));
+ }
}
}
static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
uint32_t ctx, uint32_t ringid)
{
- struct pci_dev *pdev = adapter->ahw.pdev;
+ struct pci_dev *pdev = adapter->pdev;
struct sk_buff *skb;
struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]);
- struct netxen_rcv_desc_ctx *rcv_desc = NULL;
+ struct nx_host_rds_ring *rds_ring = NULL;
u32 producer;
struct rcv_desc *pdesc;
struct netxen_rx_buffer *buffer;
int count = 0;
int index = 0;
+ struct list_head *head;
- rcv_desc = &recv_ctx->rcv_desc[ringid];
+ rds_ring = &recv_ctx->rds_rings[ringid];
- producer = rcv_desc->producer;
- index = rcv_desc->begin_alloc;
- buffer = &rcv_desc->rx_buf_arr[index];
+ producer = rds_ring->producer;
+ index = rds_ring->begin_alloc;
+ head = &rds_ring->free_list;
/* We can start writing rx descriptors into the phantom memory. */
- while (buffer->state == NETXEN_BUFFER_FREE) {
- skb = dev_alloc_skb(rcv_desc->skb_size);
+ while (!list_empty(head)) {
+
+ skb = dev_alloc_skb(rds_ring->skb_size);
if (unlikely(!skb)) {
- /*
- * We need to schedule the posting of buffers to the pegs.
- */
- rcv_desc->begin_alloc = index;
- DPRINTK(ERR, "netxen_post_rx_buffers_nodb: "
- " allocated only %d buffers\n", count);
+ rds_ring->begin_alloc = index;
break;
}
+
+ buffer = list_entry(head->next, struct netxen_rx_buffer, list);
+ list_del(&buffer->list);
+
count++; /* now there should be no failure */
- pdesc = &rcv_desc->desc_head[producer];
- skb_reserve(skb, 2);
- /*
- * This will be setup when we receive the
- * buffer after it has been filled
- * skb->dev = netdev;
- */
+ pdesc = &rds_ring->desc_head[producer];
+ if (!adapter->ahw.cut_through)
+ skb_reserve(skb, 2);
buffer->skb = skb;
buffer->state = NETXEN_BUFFER_BUSY;
buffer->dma = pci_map_single(pdev, skb->data,
- rcv_desc->dma_size,
+ rds_ring->dma_size,
PCI_DMA_FROMDEVICE);
/* make a rcv descriptor */
pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
- pdesc->buffer_length = cpu_to_le32(rcv_desc->dma_size);
+ pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
pdesc->addr_buffer = cpu_to_le64(buffer->dma);
- DPRINTK(INFO, "done writing descripter\n");
producer =
- get_next_index(producer, rcv_desc->max_rx_desc_count);
- index = get_next_index(index, rcv_desc->max_rx_desc_count);
- buffer = &rcv_desc->rx_buf_arr[index];
+ get_next_index(producer, rds_ring->max_rx_desc_count);
+ index = get_next_index(index, rds_ring->max_rx_desc_count);
+ buffer = &rds_ring->rx_buf_arr[index];
}
/* if we did allocate buffers, then write the count to Phantom */
if (count) {
- rcv_desc->begin_alloc = index;
- rcv_desc->rcv_pending += count;
- rcv_desc->producer = producer;
+ rds_ring->begin_alloc = index;
+ rds_ring->producer = producer;
/* Window = 1 */
- writel((producer - 1) &
- (rcv_desc->max_rx_desc_count - 1),
- NETXEN_CRB_NORMALIZE(adapter,
- recv_crb_registers[
- adapter->portnum].
- rcv_desc_crb[ringid].
- crb_rcv_producer_offset));
+ adapter->pci_write_normalize(adapter,
+ rds_ring->crb_rcv_producer,
+ (producer-1) & (rds_ring->max_rx_desc_count-1));
wmb();
}
}
diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c
deleted file mode 100644
index 96cec41f901..00000000000
--- a/drivers/net/netxen/netxen_nic_isr.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2003 - 2006 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,
- * 3965 Freedom Circle, Fourth floor,
- * Santa Clara, CA 95054
- */
-
-#include <linux/netdevice.h>
-#include <linux/delay.h>
-
-#include "netxen_nic.h"
-#include "netxen_nic_hw.h"
-#include "netxen_nic_phan_reg.h"
-
-/*
- * netxen_nic_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- */
-struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
-{
- struct netxen_adapter *adapter = netdev_priv(netdev);
- struct net_device_stats *stats = &adapter->net_stats;
-
- memset(stats, 0, sizeof(*stats));
-
- /* total packets received */
- stats->rx_packets = adapter->stats.no_rcv;
- /* total packets transmitted */
- stats->tx_packets = adapter->stats.xmitedframes +
- adapter->stats.xmitfinished;
- /* total bytes received */
- stats->rx_bytes = adapter->stats.rxbytes;
- /* total bytes transmitted */
- stats->tx_bytes = adapter->stats.txbytes;
- /* bad packets received */
- stats->rx_errors = adapter->stats.rcvdbadskb;
- /* packet transmit problems */
- stats->tx_errors = adapter->stats.nocmddescriptor;
- /* no space in linux buffers */
- stats->rx_dropped = adapter->stats.rxdropped;
- /* no space available in linux */
- stats->tx_dropped = adapter->stats.txdropped;
-
- return stats;
-}
-
-static void netxen_indicate_link_status(struct netxen_adapter *adapter,
- u32 link)
-{
- struct net_device *netdev = adapter->netdev;
-
- if (link)
- netif_carrier_on(netdev);
- else
- netif_carrier_off(netdev);
-}
-
-#if 0
-void netxen_handle_port_int(struct netxen_adapter *adapter, u32 enable)
-{
- __u32 int_src;
-
- /* This should clear the interrupt source */
- if (adapter->phy_read)
- adapter->phy_read(adapter,
- NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS,
- &int_src);
- if (int_src == 0) {
- DPRINTK(INFO, "No phy interrupts for port #%d\n", portno);
- return;
- }
- if (adapter->disable_phy_interrupts)
- adapter->disable_phy_interrupts(adapter);
-
- if (netxen_get_phy_int_jabber(int_src))
- DPRINTK(INFO, "Jabber interrupt \n");
-
- if (netxen_get_phy_int_polarity_changed(int_src))
- DPRINTK(INFO, "POLARITY CHANGED int \n");
-
- if (netxen_get_phy_int_energy_detect(int_src))
- DPRINTK(INFO, "ENERGY DETECT INT \n");
-
- if (netxen_get_phy_int_downshift(int_src))
- DPRINTK(INFO, "DOWNSHIFT INT \n");
- /* write it down later.. */
- if ((netxen_get_phy_int_speed_changed(int_src))
- || (netxen_get_phy_int_link_status_changed(int_src))) {
- __u32 status;
-
- DPRINTK(INFO, "SPEED CHANGED OR LINK STATUS CHANGED \n");
-
- if (adapter->phy_read
- && adapter->phy_read(adapter,
- NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
- &status) == 0) {
- if (netxen_get_phy_int_link_status_changed(int_src)) {
- if (netxen_get_phy_link(status)) {
- printk(KERN_INFO "%s: %s Link UP\n",
- netxen_nic_driver_name,
- adapter->netdev->name);
-
- } else {
- printk(KERN_INFO "%s: %s Link DOWN\n",
- netxen_nic_driver_name,
- adapter->netdev->name);
- }
- netxen_indicate_link_status(adapter,
- netxen_get_phy_link
- (status));
- }
- }
- }
- if (adapter->enable_phy_interrupts)
- adapter->enable_phy_interrupts(adapter);
-}
-#endif /* 0 */
-
-static void netxen_nic_isr_other(struct netxen_adapter *adapter)
-{
- int portno = adapter->portnum;
- u32 val, linkup, qg_linksup;
-
- /* verify the offset */
- val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
- val = val >> adapter->physical_port;
- if (val == adapter->ahw.qg_linksup)
- return;
-
- qg_linksup = adapter->ahw.qg_linksup;
- adapter->ahw.qg_linksup = val;
- DPRINTK(INFO, "link update 0x%08x\n", val);
-
- linkup = val & 1;
-
- if (linkup != (qg_linksup & 1)) {
- printk(KERN_INFO "%s: %s PORT %d link %s\n",
- adapter->netdev->name,
- netxen_nic_driver_name, portno,
- ((linkup == 0) ? "down" : "up"));
- netxen_indicate_link_status(adapter, linkup);
- if (linkup)
- netxen_nic_set_link_parameters(adapter);
-
- }
-}
-
-void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter)
-{
- netxen_nic_isr_other(adapter);
-}
-
-#if 0
-int netxen_nic_link_ok(struct netxen_adapter *adapter)
-{
- switch (adapter->ahw.board_type) {
- case NETXEN_NIC_GBE:
- return ((adapter->ahw.qg_linksup) & 1);
-
- case NETXEN_NIC_XGBE:
- return ((adapter->ahw.xg_linkup) & 1);
-
- default:
- printk(KERN_ERR"%s: Function: %s, Unknown board type\n",
- netxen_nic_driver_name, __FUNCTION__);
- break;
- }
-
- return 0;
-}
-#endif /* 0 */
-
-void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
-{
- struct net_device *netdev = adapter->netdev;
- u32 val;
-
- /* WINDOW = 1 */
- val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
- val >>= (adapter->physical_port * 8);
- val &= 0xff;
-
- if (adapter->ahw.xg_linkup == 1 && val != XG_LINK_UP) {
- printk(KERN_INFO "%s: %s NIC Link is down\n",
- netxen_nic_driver_name, netdev->name);
- adapter->ahw.xg_linkup = 0;
- if (netif_running(netdev)) {
- netif_carrier_off(netdev);
- netif_stop_queue(netdev);
- }
- } else if (adapter->ahw.xg_linkup == 0 && val == XG_LINK_UP) {
- printk(KERN_INFO "%s: %s NIC Link is up\n",
- netxen_nic_driver_name, netdev->name);
- adapter->ahw.xg_linkup = 1;
- netif_carrier_on(netdev);
- netif_wake_queue(netdev);
- }
-}
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 63cd67b931e..91d209a8f6c 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -49,13 +49,18 @@ char netxen_nic_driver_name[] = "netxen_nic";
static char netxen_nic_driver_string[] = "NetXen Network Driver version "
NETXEN_NIC_LINUX_VERSIONID;
-#define NETXEN_NETDEV_WEIGHT 120
-#define NETXEN_ADAPTER_UP_MAGIC 777
-#define NETXEN_NIC_PEG_TUNE 0
+static int port_mode = NETXEN_PORT_MODE_AUTO_NEG;
+
+/* Default to restricted 1G auto-neg mode */
+static int wol_port_mode = 5;
+
+static int use_msi = 1;
+
+static int use_msi_x = 1;
/* Local functions to NetXen NIC driver */
static int __devinit netxen_nic_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent);
+ const struct pci_device_id *ent);
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);
@@ -83,6 +88,7 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = {
ENTRY(0x0005),
ENTRY(0x0024),
ENTRY(0x0025),
+ ENTRY(0x0100),
{0,}
};
@@ -108,95 +114,61 @@ static struct workqueue_struct *netxen_workq;
static void netxen_watchdog(unsigned long);
-static void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
- uint32_t crb_producer)
+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
+};
+
+void
+netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
+ uint32_t crb_producer)
{
- switch (adapter->portnum) {
- case 0:
- writel(crb_producer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_PRODUCER_OFFSET));
- return;
- case 1:
- writel(crb_producer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_PRODUCER_OFFSET_1));
- return;
- case 2:
- writel(crb_producer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_PRODUCER_OFFSET_2));
- return;
- case 3:
- writel(crb_producer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_PRODUCER_OFFSET_3));
- return;
- default:
- printk(KERN_WARNING "We tried to update "
- "CRB_CMD_PRODUCER_OFFSET for invalid "
- "PCI function id %d\n",
- adapter->portnum);
- return;
- }
+ adapter->pci_write_normalize(adapter,
+ adapter->crb_addr_cmd_producer, crb_producer);
}
-static void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
- u32 crb_consumer)
+static uint32_t crb_cmd_consumer[4] = {
+ CRB_CMD_CONSUMER_OFFSET, CRB_CMD_CONSUMER_OFFSET_1,
+ CRB_CMD_CONSUMER_OFFSET_2, CRB_CMD_CONSUMER_OFFSET_3
+};
+
+static inline void
+netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
+ u32 crb_consumer)
{
- switch (adapter->portnum) {
- case 0:
- writel(crb_consumer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_CONSUMER_OFFSET));
- return;
- case 1:
- writel(crb_consumer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_CONSUMER_OFFSET_1));
- return;
- case 2:
- writel(crb_consumer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_CONSUMER_OFFSET_2));
- return;
- case 3:
- writel(crb_consumer, NETXEN_CRB_NORMALIZE
- (adapter, CRB_CMD_CONSUMER_OFFSET_3));
- return;
- default:
- printk(KERN_WARNING "We tried to update "
- "CRB_CMD_PRODUCER_OFFSET for invalid "
- "PCI function id %d\n",
- adapter->portnum);
- return;
- }
+ adapter->pci_write_normalize(adapter,
+ adapter->crb_addr_cmd_consumer, crb_consumer);
}
-#define ADAPTER_LIST_SIZE 12
-
-static uint32_t msi_tgt_status[4] = {
+static uint32_t msi_tgt_status[8] = {
ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
- ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3
+ ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
+ ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
+ ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
};
-static uint32_t sw_int_mask[4] = {
- CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
- CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
-};
+static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
static void netxen_nic_disable_int(struct netxen_adapter *adapter)
{
u32 mask = 0x7ff;
int retries = 32;
- int port = adapter->portnum;
int pci_fn = adapter->ahw.pci_func;
if (adapter->msi_mode != MSI_MODE_MULTIFUNC)
- writel(0x0, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
+ adapter->pci_write_normalize(adapter,
+ adapter->crb_intr_mask, 0);
if (adapter->intr_scheme != -1 &&
adapter->intr_scheme != INTR_SCHEME_PERPORT)
- writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+ adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask);
- if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ if (!NETXEN_IS_MSI_FAMILY(adapter)) {
do {
- writel(0xffffffff,
- PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_STATUS));
- mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR));
+ adapter->pci_write_immediate(adapter,
+ ISR_INT_TARGET_STATUS, 0xffffffff);
+ mask = adapter->pci_read_immediate(adapter,
+ ISR_INT_VECTOR);
if (!(mask & 0x80))
break;
udelay(10);
@@ -208,8 +180,8 @@ static void netxen_nic_disable_int(struct netxen_adapter *adapter)
}
} else {
if (adapter->msi_mode == MSI_MODE_MULTIFUNC) {
- writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter,
- msi_tgt_status[pci_fn]));
+ adapter->pci_write_immediate(adapter,
+ msi_tgt_status[pci_fn], 0xffffffff);
}
}
}
@@ -217,7 +189,6 @@ static void netxen_nic_disable_int(struct netxen_adapter *adapter)
static void netxen_nic_enable_int(struct netxen_adapter *adapter)
{
u32 mask;
- int port = adapter->portnum;
DPRINTK(1, INFO, "Entered ISR Enable \n");
@@ -235,24 +206,299 @@ static void netxen_nic_enable_int(struct netxen_adapter *adapter)
break;
}
- writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+ adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask);
}
- writel(0x1, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
+ adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0x1);
- if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ if (!NETXEN_IS_MSI_FAMILY(adapter)) {
mask = 0xbff;
if (adapter->intr_scheme != -1 &&
adapter->intr_scheme != INTR_SCHEME_PERPORT) {
- writel(0X0, NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ adapter->pci_write_normalize(adapter,
+ CRB_INT_VECTOR, 0);
}
- writel(mask,
- PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK));
+ adapter->pci_write_immediate(adapter,
+ ISR_INT_TARGET_MASK, mask);
}
DPRINTK(1, INFO, "Done with enable Int\n");
}
+static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id)
+{
+ struct pci_dev *pdev = adapter->pdev;
+ int err;
+ uint64_t mask;
+
+#ifdef CONFIG_IA64
+ adapter->dma_mask = DMA_32BIT_MASK;
+#else
+ if (revision_id >= NX_P3_B0) {
+ /* should go to DMA_64BIT_MASK */
+ adapter->dma_mask = DMA_39BIT_MASK;
+ mask = DMA_39BIT_MASK;
+ } else if (revision_id == NX_P3_A2) {
+ adapter->dma_mask = DMA_39BIT_MASK;
+ mask = DMA_39BIT_MASK;
+ } else if (revision_id == NX_P2_C1) {
+ adapter->dma_mask = DMA_35BIT_MASK;
+ mask = DMA_35BIT_MASK;
+ } else {
+ adapter->dma_mask = DMA_32BIT_MASK;
+ mask = DMA_32BIT_MASK;
+ goto set_32_bit_mask;
+ }
+
+ /*
+ * Consistent DMA mask is set to 32 bit because it cannot be set to
+ * 35 bits. For P3 also leave it at 32 bits for now. Only the rings
+ * come off this pool.
+ */
+ if (pci_set_dma_mask(pdev, mask) == 0 &&
+ pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) == 0) {
+ adapter->pci_using_dac = 1;
+ return 0;
+ }
+#endif /* CONFIG_IA64 */
+
+set_32_bit_mask:
+ err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (!err)
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ DPRINTK(ERR, "No usable DMA configuration, aborting:%d\n", err);
+ return err;
+ }
+
+ adapter->pci_using_dac = 0;
+ return 0;
+}
+
+static void netxen_check_options(struct netxen_adapter *adapter)
+{
+ switch (adapter->ahw.boardcfg.board_type) {
+ case NETXEN_BRDTYPE_P3_HMEZ:
+ case NETXEN_BRDTYPE_P3_XG_LOM:
+ case NETXEN_BRDTYPE_P3_10G_CX4:
+ case NETXEN_BRDTYPE_P3_10G_CX4_LP:
+ case NETXEN_BRDTYPE_P3_IMEZ:
+ case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
+ case NETXEN_BRDTYPE_P3_10G_XFP:
+ case NETXEN_BRDTYPE_P3_10000_BASE_T:
+ adapter->msix_supported = !!use_msi_x;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
+ break;
+
+ case NETXEN_BRDTYPE_P2_SB31_10G:
+ case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
+ case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
+ case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
+ adapter->msix_supported = 0;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
+ break;
+
+ case NETXEN_BRDTYPE_P3_REF_QG:
+ case NETXEN_BRDTYPE_P3_4_GB:
+ case NETXEN_BRDTYPE_P3_4_GB_MM:
+ case NETXEN_BRDTYPE_P2_SB35_4G:
+ case NETXEN_BRDTYPE_P2_SB31_2G:
+ adapter->msix_supported = 0;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
+ break;
+
+ default:
+ adapter->msix_supported = 0;
+ adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
+
+ printk(KERN_WARNING "Unknown board type(0x%x)\n",
+ adapter->ahw.boardcfg.board_type);
+ break;
+ }
+
+ adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS_HOST;
+ adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
+ adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS;
+
+ adapter->max_possible_rss_rings = 1;
+ return;
+}
+
+static int
+netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot)
+{
+ int ret = 0;
+
+ if (first_boot == 0x55555555) {
+ /* This is the first boot after power up */
+
+ /* PCI bus master workaround */
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(0x4), &first_boot, 4);
+ if (!(first_boot & 0x4)) {
+ first_boot |= 0x4;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PCIE_REG(0x4), &first_boot, 4);
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(0x4), &first_boot, 4);
+ }
+
+ /* This is the first boot after power up */
+ adapter->hw_read_wx(adapter,
+ NETXEN_ROMUSB_GLB_SW_RESET, &first_boot, 4);
+ if (first_boot != 0x80000f) {
+ /* clear the register for future unloads/loads */
+ adapter->pci_write_normalize(adapter,
+ NETXEN_CAM_RAM(0x1fc), 0);
+ ret = -1;
+ }
+
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ /* Start P2 boot loader */
+ adapter->pci_write_normalize(adapter,
+ NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC);
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1);
+ }
+ }
+ return ret;
+}
+
+static void netxen_set_port_mode(struct netxen_adapter *adapter)
+{
+ u32 val, data;
+
+ val = adapter->ahw.boardcfg.board_type;
+ if ((val == NETXEN_BRDTYPE_P3_HMEZ) ||
+ (val == NETXEN_BRDTYPE_P3_XG_LOM)) {
+ if (port_mode == NETXEN_PORT_MODE_802_3_AP) {
+ data = NETXEN_PORT_MODE_802_3_AP;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ } else if (port_mode == NETXEN_PORT_MODE_XG) {
+ data = NETXEN_PORT_MODE_XG;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ } else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_1G) {
+ data = NETXEN_PORT_MODE_AUTO_NEG_1G;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ } else if (port_mode == NETXEN_PORT_MODE_AUTO_NEG_XG) {
+ data = NETXEN_PORT_MODE_AUTO_NEG_XG;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ } else {
+ data = NETXEN_PORT_MODE_AUTO_NEG;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PORT_MODE_ADDR, &data, 4);
+ }
+
+ if ((wol_port_mode != NETXEN_PORT_MODE_802_3_AP) &&
+ (wol_port_mode != NETXEN_PORT_MODE_XG) &&
+ (wol_port_mode != NETXEN_PORT_MODE_AUTO_NEG_1G) &&
+ (wol_port_mode != NETXEN_PORT_MODE_AUTO_NEG_XG)) {
+ wol_port_mode = NETXEN_PORT_MODE_AUTO_NEG;
+ }
+ adapter->hw_write_wx(adapter, NETXEN_WOL_PORT_MODE,
+ &wol_port_mode, 4);
+ }
+}
+
+#define PCI_CAP_ID_GEN 0x10
+
+static void netxen_pcie_strap_init(struct netxen_adapter *adapter)
+{
+ u32 pdevfuncsave;
+ u32 c8c9value = 0;
+ u32 chicken = 0;
+ u32 control = 0;
+ int i, pos;
+ struct pci_dev *pdev;
+
+ pdev = pci_get_device(0x1166, 0x0140, NULL);
+ if (pdev) {
+ pci_dev_put(pdev);
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), &chicken, 4);
+ chicken |= 0x4000;
+ adapter->hw_write_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_TGT_SPLIT_CHICKEN), &chicken, 4);
+ }
+
+ pdev = adapter->pdev;
+
+ adapter->hw_read_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_CHICKEN3), &chicken, 4);
+ /* clear chicken3.25:24 */
+ chicken &= 0xFCFFFFFF;
+ /*
+ * if gen1 and B0, set F1020 - if gen 2, do nothing
+ * if gen2 set to F1000
+ */
+ pos = pci_find_capability(pdev, PCI_CAP_ID_GEN);
+ if (pos == 0xC0) {
+ pci_read_config_dword(pdev, pos + 0x10, &control);
+ if ((control & 0x000F0000) != 0x00020000) {
+ /* set chicken3.24 if gen1 */
+ chicken |= 0x01000000;
+ }
+ printk(KERN_INFO "%s Gen2 strapping detected\n",
+ netxen_nic_driver_name);
+ c8c9value = 0xF1000;
+ } else {
+ /* set chicken3.24 if gen1 */
+ chicken |= 0x01000000;
+ printk(KERN_INFO "%s Gen1 strapping detected\n",
+ netxen_nic_driver_name);
+ if (adapter->ahw.revision_id == NX_P3_B0)
+ c8c9value = 0xF1020;
+ else
+ c8c9value = 0;
+
+ }
+ adapter->hw_write_wx(adapter,
+ NETXEN_PCIE_REG(PCIE_CHICKEN3), &chicken, 4);
+
+ if (!c8c9value)
+ return;
+
+ pdevfuncsave = pdev->devfn;
+ if (pdevfuncsave & 0x07)
+ return;
+
+ for (i = 0; i < 8; i++) {
+ pci_read_config_dword(pdev, pos + 8, &control);
+ pci_read_config_dword(pdev, pos + 8, &control);
+ pci_write_config_dword(pdev, pos + 8, c8c9value);
+ pdev->devfn++;
+ }
+ pdev->devfn = pdevfuncsave;
+}
+
+static void netxen_set_msix_bit(struct pci_dev *pdev, int enable)
+{
+ u32 control;
+ int pos;
+
+ pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+ if (pos) {
+ pci_read_config_dword(pdev, pos, &control);
+ if (enable)
+ control |= PCI_MSIX_FLAGS_ENABLE;
+ else
+ control = 0;
+ pci_write_config_dword(pdev, pos, control);
+ }
+}
+
+static void netxen_init_msix_entries(struct netxen_adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < MSIX_ENTRIES_PER_ADAPTER; i++)
+ adapter->msix_entries[i].entry = i;
+}
+
/*
* netxen_nic_probe()
*
@@ -278,28 +524,28 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
u8 __iomem *db_ptr = NULL;
- unsigned long mem_base, mem_len, db_base, db_len;
- int pci_using_dac, i = 0, err;
- int ring;
- struct netxen_recv_context *recv_ctx = NULL;
- struct netxen_rcv_desc_ctx *rcv_desc = NULL;
- struct netxen_cmd_buffer *cmd_buf_arr = NULL;
+ unsigned long mem_base, mem_len, db_base, db_len, pci_len0 = 0;
+ int i = 0, err;
+ int first_driver, first_boot;
__le64 mac_addr[FLASH_NUM_PORTS + 1];
- int valid_mac = 0;
u32 val;
int pci_func_id = PCI_FUNC(pdev->devfn);
DECLARE_MAC_BUF(mac);
+ struct netxen_legacy_intr_set *legacy_intrp;
+ uint8_t revision_id;
if (pci_func_id == 0)
- printk(KERN_INFO "%s \n", netxen_nic_driver_string);
+ printk(KERN_INFO "%s\n", netxen_nic_driver_string);
if (pdev->class != 0x020000) {
printk(KERN_DEBUG "NetXen function %d, class %x will not "
"be enabled.\n",pci_func_id, pdev->class);
return -ENODEV;
}
+
if ((err = pci_enable_device(pdev)))
return err;
+
if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
err = -ENODEV;
goto err_out_disable_pdev;
@@ -309,18 +555,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_disable_pdev;
pci_set_master(pdev);
- if (pdev->revision == NX_P2_C1 &&
- (pci_set_dma_mask(pdev, DMA_35BIT_MASK) == 0) &&
- (pci_set_consistent_dma_mask(pdev, DMA_35BIT_MASK) == 0)) {
- pci_using_dac = 1;
- } else {
- if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
- (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)))
- goto err_out_free_res;
-
- pci_using_dac = 0;
- }
-
netdev = alloc_etherdev(sizeof(struct netxen_adapter));
if(!netdev) {
@@ -333,13 +567,35 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
SET_NETDEV_DEV(netdev, &pdev->dev);
adapter = netdev->priv;
-
- adapter->ahw.pdev = pdev;
+ adapter->netdev = netdev;
+ adapter->pdev = pdev;
adapter->ahw.pci_func = pci_func_id;
+ revision_id = pdev->revision;
+ adapter->ahw.revision_id = revision_id;
+
+ err = nx_set_dma_mask(adapter, revision_id);
+ if (err)
+ goto err_out_free_netdev;
+
+ rwlock_init(&adapter->adapter_lock);
+ adapter->ahw.qdr_sn_window = -1;
+ adapter->ahw.ddr_mn_window = -1;
+
/* remap phys address */
mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
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_read_normalize = netxen_nic_pci_read_normalize_128M;
+ adapter->pci_write_normalize = netxen_nic_pci_write_normalize_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) {
@@ -356,27 +612,48 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
SECOND_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE);
first_page_group_start = 0;
first_page_group_end = 0;
+ } 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_read_normalize = netxen_nic_pci_read_normalize_2M;
+ adapter->pci_write_normalize =
+ netxen_nic_pci_write_normalize_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 = ioremap(mem_base, mem_len);
+ pci_len0 = mem_len;
+ first_page_group_start = 0;
+ first_page_group_end = 0;
+
+ adapter->ahw.ddr_mn_window = 0;
+ adapter->ahw.qdr_sn_window = 0;
+
+ adapter->ahw.mn_win_crb = 0x100000 + PCIX_MN_WINDOW +
+ (pci_func_id * 0x20);
+ adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW;
+ if (pci_func_id < 4)
+ adapter->ahw.ms_win_crb += (pci_func_id * 0x20);
+ else
+ adapter->ahw.ms_win_crb +=
+ 0xA0 + ((pci_func_id - 4) * 0x10);
} else {
err = -EIO;
goto err_out_free_netdev;
}
- if ((!mem_ptr0 && mem_len == NETXEN_PCI_128MB_SIZE) ||
- !mem_ptr1 || !mem_ptr2) {
- DPRINTK(ERR,
- "Cannot remap adapter memory aborting.:"
- "0 -> %p, 1 -> %p, 2 -> %p\n",
- mem_ptr0, mem_ptr1, mem_ptr2);
+ dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
- err = -EIO;
- goto err_out_iounmap;
- }
db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */
db_len = pci_resource_len(pdev, 4);
if (db_len == 0) {
printk(KERN_ERR "%s: doorbell is disabled\n",
- netxen_nic_driver_name);
+ netxen_nic_driver_name);
err = -EIO;
goto err_out_iounmap;
}
@@ -386,13 +663,14 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES);
if (!db_ptr) {
printk(KERN_ERR "%s: Failed to allocate doorbell map.",
- netxen_nic_driver_name);
+ netxen_nic_driver_name);
err = -EIO;
goto err_out_iounmap;
}
DPRINTK(INFO, "doorbell ioremaped at %p\n", db_ptr);
adapter->ahw.pci_base0 = mem_ptr0;
+ adapter->ahw.pci_len0 = pci_len0;
adapter->ahw.first_page_group_start = first_page_group_start;
adapter->ahw.first_page_group_end = first_page_group_end;
adapter->ahw.pci_base1 = mem_ptr1;
@@ -400,11 +678,18 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->ahw.db_base = db_ptr;
adapter->ahw.db_len = db_len;
- adapter->netdev = netdev;
- adapter->pdev = pdev;
-
netif_napi_add(netdev, &adapter->napi,
- netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
+ netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
+
+ if (revision_id >= NX_P3_B0)
+ legacy_intrp = &legacy_intr[pci_func_id];
+ 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;
/* this will be read from FW later */
adapter->intr_scheme = -1;
@@ -414,12 +699,23 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->portnum = pci_func_id;
adapter->status &= ~NETXEN_NETDEV_STATUS;
adapter->rx_csum = 1;
+ adapter->mc_enabled = 0;
+ if (NX_IS_REVISION_P3(revision_id)) {
+ adapter->max_mc_count = 38;
+ adapter->max_rds_rings = 2;
+ } else {
+ adapter->max_mc_count = 16;
+ adapter->max_rds_rings = 3;
+ }
netdev->open = netxen_nic_open;
netdev->stop = netxen_nic_close;
netdev->hard_start_xmit = netxen_nic_xmit_frame;
netdev->get_stats = netxen_nic_get_stats;
- netdev->set_multicast_list = netxen_nic_set_multi;
+ if (NX_IS_REVISION_P3(revision_id))
+ netdev->set_multicast_list = netxen_p3_nic_set_multi;
+ else
+ netdev->set_multicast_list = netxen_p2_nic_set_multi;
netdev->set_mac_address = netxen_nic_set_mac;
netdev->change_mtu = netxen_nic_change_mtu;
netdev->tx_timeout = netxen_tx_timeout;
@@ -435,18 +731,14 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->features = NETIF_F_SG;
netdev->features |= NETIF_F_IP_CSUM;
netdev->features |= NETIF_F_TSO;
+ if (NX_IS_REVISION_P3(revision_id)) {
+ netdev->features |= NETIF_F_IPV6_CSUM;
+ netdev->features |= NETIF_F_TSO6;
+ }
- if (pci_using_dac)
+ if (adapter->pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
- if (pci_enable_msi(pdev))
- adapter->flags &= ~NETXEN_NIC_MSI_ENABLED;
- else
- adapter->flags |= NETXEN_NIC_MSI_ENABLED;
-
- netdev->irq = pdev->irq;
- INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task);
-
/*
* Set the CRB window to invalid. If any register in window 0 is
* accessed it should set the window to 0 and then reset it to 1.
@@ -455,87 +747,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (netxen_nic_get_board_info(adapter) != 0) {
printk("%s: Error getting board config info.\n",
- netxen_nic_driver_name);
+ netxen_nic_driver_name);
err = -EIO;
goto err_out_iounmap;
}
- /*
- * Adapter in our case is quad port so initialize it before
- * initializing the ports
- */
-
netxen_initialize_adapter_ops(adapter);
- adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS_HOST;
- if ((adapter->ahw.boardcfg.board_type == NETXEN_BRDTYPE_P2_SB35_4G) ||
- (adapter->ahw.boardcfg.board_type ==
- NETXEN_BRDTYPE_P2_SB31_2G))
- adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
- else
- adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS;
- adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
- adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS;
-
- cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE);
- if (cmd_buf_arr == NULL) {
- printk(KERN_ERR
- "%s: Could not allocate cmd_buf_arr memory:%d\n",
- netxen_nic_driver_name, (int)TX_RINGSIZE);
- err = -ENOMEM;
- goto err_out_free_adapter;
- }
- memset(cmd_buf_arr, 0, TX_RINGSIZE);
- adapter->cmd_buf_arr = cmd_buf_arr;
-
- for (i = 0; i < MAX_RCV_CTX; ++i) {
- recv_ctx = &adapter->recv_ctx[i];
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
- switch (RCV_DESC_TYPE(ring)) {
- case RCV_DESC_NORMAL:
- rcv_desc->max_rx_desc_count =
- adapter->max_rx_desc_count;
- rcv_desc->flags = RCV_DESC_NORMAL;
- rcv_desc->dma_size = RX_DMA_MAP_LEN;
- rcv_desc->skb_size = MAX_RX_BUFFER_LENGTH;
- break;
-
- case RCV_DESC_JUMBO:
- rcv_desc->max_rx_desc_count =
- adapter->max_jumbo_rx_desc_count;
- rcv_desc->flags = RCV_DESC_JUMBO;
- rcv_desc->dma_size = RX_JUMBO_DMA_MAP_LEN;
- rcv_desc->skb_size = MAX_RX_JUMBO_BUFFER_LENGTH;
- break;
-
- case RCV_RING_LRO:
- rcv_desc->max_rx_desc_count =
- adapter->max_lro_rx_desc_count;
- rcv_desc->flags = RCV_DESC_LRO;
- rcv_desc->dma_size = RX_LRO_DMA_MAP_LEN;
- rcv_desc->skb_size = MAX_RX_LRO_BUFFER_LENGTH;
- break;
-
- }
- rcv_desc->rx_buf_arr = (struct netxen_rx_buffer *)
- vmalloc(RCV_BUFFSIZE);
-
- if (rcv_desc->rx_buf_arr == NULL) {
- printk(KERN_ERR "%s: Could not allocate "
- "rcv_desc->rx_buf_arr memory:%d\n",
- netxen_nic_driver_name,
- (int)RCV_BUFFSIZE);
- err = -ENOMEM;
- goto err_out_free_rx_buffer;
- }
- memset(rcv_desc->rx_buf_arr, 0, RCV_BUFFSIZE);
- }
-
- }
-
- netxen_initialize_adapter_sw(adapter); /* initialize the buffers in adapter */
-
/* Mezz cards have PCI function 0,2,3 enabled */
switch (adapter->ahw.boardcfg.board_type) {
case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
@@ -547,90 +765,71 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
break;
}
- init_timer(&adapter->watchdog_timer);
- adapter->ahw.xg_linkup = 0;
- adapter->watchdog_timer.function = &netxen_watchdog;
- adapter->watchdog_timer.data = (unsigned long)adapter;
- INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
- adapter->ahw.pdev = pdev;
- adapter->ahw.revision_id = pdev->revision;
-
- /* make sure Window == 1 */
- netxen_nic_pci_change_crbwindow(adapter, 1);
+ /*
+ * This call will setup various max rx/tx counts.
+ * It must be done before any buffer/ring allocations.
+ */
+ netxen_check_options(adapter);
+ first_driver = 0;
+ if (NX_IS_REVISION_P3(revision_id)) {
+ if (adapter->ahw.pci_func == 0)
+ first_driver = 1;
+ } else {
+ if (adapter->portnum == 0)
+ first_driver = 1;
+ }
+ adapter->crb_addr_cmd_producer = crb_cmd_producer[adapter->portnum];
+ adapter->crb_addr_cmd_consumer = crb_cmd_consumer[adapter->portnum];
netxen_nic_update_cmd_producer(adapter, 0);
netxen_nic_update_cmd_consumer(adapter, 0);
- writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO));
- if (netxen_is_flash_supported(adapter) == 0 &&
- netxen_get_flash_mac_addr(adapter, mac_addr) == 0)
- valid_mac = 1;
- else
- valid_mac = 0;
-
- if (valid_mac) {
- unsigned char *p = (unsigned char *)&mac_addr[adapter->portnum];
- netdev->dev_addr[0] = *(p + 5);
- netdev->dev_addr[1] = *(p + 4);
- netdev->dev_addr[2] = *(p + 3);
- netdev->dev_addr[3] = *(p + 2);
- netdev->dev_addr[4] = *(p + 1);
- netdev->dev_addr[5] = *(p + 0);
+ if (first_driver) {
+ first_boot = adapter->pci_read_normalize(adapter,
+ NETXEN_CAM_RAM(0x1fc));
- memcpy(netdev->perm_addr, netdev->dev_addr,
- netdev->addr_len);
- if (!is_valid_ether_addr(netdev->perm_addr)) {
- printk(KERN_ERR "%s: Bad MAC address %s.\n",
- netxen_nic_driver_name,
- print_mac(mac, netdev->dev_addr));
- } else {
- if (adapter->macaddr_set)
- adapter->macaddr_set(adapter,
- netdev->dev_addr);
+ err = netxen_check_hw_init(adapter, first_boot);
+ if (err) {
+ printk(KERN_ERR "%s: error in init HW init sequence\n",
+ netxen_nic_driver_name);
+ goto err_out_iounmap;
}
- }
- if (adapter->portnum == 0) {
- err = netxen_initialize_adapter_offload(adapter);
- if (err)
- goto err_out_free_rx_buffer;
- val = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_CAM_RAM(0x1fc)));
- if (val == 0x55555555) {
- /* This is the first boot after power up */
- netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
- if (!(val & 0x4)) {
- val |= 0x4;
- netxen_nic_write_w0(adapter, NETXEN_PCIE_REG(0x4), val);
- netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(0x4), &val);
- if (!(val & 0x4))
- printk(KERN_ERR "%s: failed to set MSI bit in PCI-e reg\n",
- netxen_nic_driver_name);
- }
- val = readl(NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_ROMUSB_GLB_SW_RESET));
- printk(KERN_INFO"NetXen: read 0x%08x for reset reg.\n",val);
- if (val != 0x80000f) {
- /* clear the register for future unloads/loads */
- writel(0, NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_CAM_RAM(0x1fc)));
- printk(KERN_ERR "ERROR in NetXen HW init sequence.\n");
- err = -ENODEV;
- goto err_out_free_dev;
- }
- } else {
- writel(0, NETXEN_CRB_NORMALIZE(adapter,
- CRB_CMDPEG_STATE));
+ if (NX_IS_REVISION_P3(revision_id))
+ netxen_set_port_mode(adapter);
+
+ if (first_boot != 0x55555555) {
+ adapter->pci_write_normalize(adapter,
+ CRB_CMDPEG_STATE, 0);
netxen_pinit_from_rom(adapter, 0);
msleep(1);
netxen_load_firmware(adapter);
- netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
}
- /* clear the register for future unloads/loads */
- writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
- dev_info(&pdev->dev, "cmdpeg state: 0x%0x\n",
- readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
+ if (NX_IS_REVISION_P3(revision_id))
+ netxen_pcie_strap_init(adapter);
+
+ if (NX_IS_REVISION_P2(revision_id)) {
+
+ /* Initialize multicast addr pool owners */
+ val = 0x7654;
+ if (adapter->ahw.board_type == NETXEN_NIC_XGBE)
+ val |= 0x0f000000;
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_MAC_ADDR_CNTL_REG, val);
+
+ }
+
+ if ((first_boot == 0x55555555) &&
+ (NX_IS_REVISION_P2(revision_id))) {
+ /* Unlock the HW, prompting the boot sequence */
+ adapter->pci_write_normalize(adapter,
+ NETXEN_ROMUSB_GLB_PEGTUNE_DONE, 1);
+ }
+
+ err = netxen_initialize_adapter_offload(adapter);
+ if (err)
+ goto err_out_iounmap;
/*
* Tell the hardware our version number.
@@ -638,24 +837,101 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
i = (_NETXEN_NIC_LINUX_MAJOR << 16)
| ((_NETXEN_NIC_LINUX_MINOR << 8))
| (_NETXEN_NIC_LINUX_SUBVERSION);
- writel(i, NETXEN_CRB_NORMALIZE(adapter, CRB_DRIVER_VERSION));
+ adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, i);
- /* Unlock the HW, prompting the boot sequence */
- writel(1,
- NETXEN_CRB_NORMALIZE(adapter,
- NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
/* Handshake with the card before we register the devices. */
netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
+
+ } /* first_driver */
+
+ netxen_nic_flash_print(adapter);
+
+ if (NX_IS_REVISION_P3(revision_id)) {
+ adapter->hw_read_wx(adapter,
+ NETXEN_MIU_MN_CONTROL, &val, 4);
+ adapter->ahw.cut_through = (val & 0x4) ? 1 : 0;
+ dev_info(&pdev->dev, "firmware running in %s mode\n",
+ adapter->ahw.cut_through ? "cut through" : "legacy");
}
/*
* See if the firmware gave us a virtual-physical port mapping.
*/
adapter->physical_port = adapter->portnum;
- i = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_V2P(adapter->portnum)));
+ i = adapter->pci_read_normalize(adapter, CRB_V2P(adapter->portnum));
if (i != 0x55555555)
adapter->physical_port = i;
+ adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED);
+
+ netxen_set_msix_bit(pdev, 0);
+
+ if (NX_IS_REVISION_P3(revision_id)) {
+ if ((mem_len != NETXEN_PCI_128MB_SIZE) &&
+ mem_len != NETXEN_PCI_2MB_SIZE)
+ adapter->msix_supported = 0;
+ }
+
+ if (adapter->msix_supported) {
+
+ netxen_init_msix_entries(adapter);
+
+ if (pci_enable_msix(pdev, adapter->msix_entries,
+ MSIX_ENTRIES_PER_ADAPTER))
+ goto request_msi;
+
+ adapter->flags |= NETXEN_NIC_MSIX_ENABLED;
+ netxen_set_msix_bit(pdev, 1);
+ dev_info(&pdev->dev, "using msi-x interrupts\n");
+
+ } else {
+request_msi:
+ if (use_msi && !pci_enable_msi(pdev)) {
+ adapter->flags |= NETXEN_NIC_MSI_ENABLED;
+ dev_info(&pdev->dev, "using msi interrupts\n");
+ } else
+ dev_info(&pdev->dev, "using legacy interrupts\n");
+ }
+
+ if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+ netdev->irq = adapter->msix_entries[0].vector;
+ else
+ netdev->irq = pdev->irq;
+
+ err = netxen_receive_peg_ready(adapter);
+ if (err)
+ goto err_out_disable_msi;
+
+ init_timer(&adapter->watchdog_timer);
+ adapter->ahw.linkup = 0;
+ 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);
+
+ if (netxen_is_flash_supported(adapter) == 0 &&
+ netxen_get_flash_mac_addr(adapter, mac_addr) == 0) {
+ unsigned char *p;
+
+ p = (unsigned char *)&mac_addr[adapter->portnum];
+ netdev->dev_addr[0] = *(p + 5);
+ netdev->dev_addr[1] = *(p + 4);
+ netdev->dev_addr[2] = *(p + 3);
+ netdev->dev_addr[3] = *(p + 2);
+ netdev->dev_addr[4] = *(p + 1);
+ netdev->dev_addr[5] = *(p + 0);
+
+ memcpy(netdev->perm_addr, netdev->dev_addr,
+ netdev->addr_len);
+ if (!is_valid_ether_addr(netdev->perm_addr)) {
+ printk(KERN_ERR "%s: Bad MAC address %s.\n",
+ netxen_nic_driver_name,
+ print_mac(mac, netdev->dev_addr));
+ } else {
+ adapter->macaddr_set(adapter, netdev->dev_addr);
+ }
+ }
+
netif_carrier_off(netdev);
netif_stop_queue(netdev);
@@ -664,41 +940,37 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
" aborting\n", netxen_nic_driver_name,
adapter->portnum);
err = -EIO;
- goto err_out_free_dev;
+ goto err_out_disable_msi;
}
- netxen_nic_flash_print(adapter);
pci_set_drvdata(pdev, adapter);
- return 0;
-
-err_out_free_dev:
- if (adapter->portnum == 0)
- netxen_free_adapter_offload(adapter);
-
-err_out_free_rx_buffer:
- for (i = 0; i < MAX_RCV_CTX; ++i) {
- recv_ctx = &adapter->recv_ctx[i];
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
- if (rcv_desc->rx_buf_arr != NULL) {
- vfree(rcv_desc->rx_buf_arr);
- rcv_desc->rx_buf_arr = NULL;
- }
- }
+ switch (adapter->ahw.board_type) {
+ case NETXEN_NIC_GBE:
+ dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n",
+ adapter->netdev->name);
+ break;
+ case NETXEN_NIC_XGBE:
+ dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n",
+ adapter->netdev->name);
+ break;
}
- vfree(cmd_buf_arr);
-err_out_free_adapter:
+ return 0;
+
+err_out_disable_msi:
+ if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+ pci_disable_msix(pdev);
if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
pci_disable_msi(pdev);
- pci_set_drvdata(pdev, NULL);
+ if (first_driver)
+ netxen_free_adapter_offload(adapter);
+err_out_iounmap:
if (db_ptr)
iounmap(db_ptr);
-err_out_iounmap:
if (mem_ptr0)
iounmap(mem_ptr0);
if (mem_ptr1)
@@ -713,6 +985,7 @@ err_out_free_res:
pci_release_regions(pdev);
err_out_disable_pdev:
+ pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
return err;
}
@@ -721,11 +994,6 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
{
struct netxen_adapter *adapter;
struct net_device *netdev;
- struct netxen_rx_buffer *buffer;
- struct netxen_recv_context *recv_ctx;
- struct netxen_rcv_desc_ctx *rcv_desc;
- int i, ctxid, ring;
- static int init_firmware_done = 0;
adapter = pci_get_drvdata(pdev);
if (adapter == NULL)
@@ -736,36 +1004,18 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
unregister_netdev(netdev);
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
- init_firmware_done++;
netxen_free_hw_resources(adapter);
+ netxen_free_sw_resources(adapter);
}
- for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) {
- recv_ctx = &adapter->recv_ctx[ctxid];
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
- rcv_desc = &recv_ctx->rcv_desc[ring];
- for (i = 0; i < rcv_desc->max_rx_desc_count; ++i) {
- buffer = &(rcv_desc->rx_buf_arr[i]);
- if (buffer->state == NETXEN_BUFFER_FREE)
- continue;
- pci_unmap_single(pdev, buffer->dma,
- rcv_desc->dma_size,
- PCI_DMA_FROMDEVICE);
- if (buffer->skb != NULL)
- dev_kfree_skb_any(buffer->skb);
- }
- vfree(rcv_desc->rx_buf_arr);
- }
- }
-
- vfree(adapter->cmd_buf_arr);
-
if (adapter->portnum == 0)
netxen_free_adapter_offload(adapter);
if (adapter->irq)
free_irq(adapter->irq, adapter);
+ if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+ pci_disable_msix(pdev);
if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
pci_disable_msi(pdev);
@@ -803,51 +1053,69 @@ static int netxen_nic_open(struct net_device *netdev)
return -EIO;
}
- /* setup all the resources for the Phantom... */
- /* this include the descriptors for rcv, tx, and status */
- netxen_nic_clear_stats(adapter);
- err = netxen_nic_hw_resources(adapter);
+ err = netxen_alloc_sw_resources(adapter);
if (err) {
- printk(KERN_ERR "Error in setting hw resources:%d\n",
- err);
+ printk(KERN_ERR "%s: Error in setting sw resources\n",
+ netdev->name);
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",
+ netdev->name);
+ goto err_out_free_sw;
+ }
+
+ if (adapter->fw_major < 4) {
+ adapter->crb_addr_cmd_producer =
+ crb_cmd_producer[adapter->portnum];
+ adapter->crb_addr_cmd_consumer =
+ crb_cmd_consumer[adapter->portnum];
+ }
+
+ netxen_nic_update_cmd_producer(adapter, 0);
+ netxen_nic_update_cmd_consumer(adapter, 0);
+
for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
- for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++)
+ for (ring = 0; ring < adapter->max_rds_rings; ring++)
netxen_post_rx_buffers(adapter, ctx, ring);
}
- adapter->irq = adapter->ahw.pdev->irq;
- if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
+ if (NETXEN_IS_MSI_FAMILY(adapter))
handler = netxen_msi_intr;
else {
flags |= IRQF_SHARED;
handler = netxen_intr;
}
+ adapter->irq = netdev->irq;
err = request_irq(adapter->irq, handler,
flags, netdev->name, adapter);
if (err) {
printk(KERN_ERR "request_irq failed with: %d\n", err);
- netxen_free_hw_resources(adapter);
- return err;
+ goto err_out_free_hw;
}
adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
}
+
/* Done here again so that even if phantom sw overwrote it,
* we set it */
- if (adapter->init_port
- && adapter->init_port(adapter, adapter->portnum) != 0) {
+ err = adapter->init_port(adapter, adapter->physical_port);
+ if (err) {
printk(KERN_ERR "%s: Failed to initialize port %d\n",
netxen_nic_driver_name, adapter->portnum);
- return -EIO;
+ goto err_out_free_irq;
}
- if (adapter->macaddr_set)
- adapter->macaddr_set(adapter, netdev->dev_addr);
+ adapter->macaddr_set(adapter, netdev->dev_addr);
netxen_nic_set_link_parameters(adapter);
- netxen_nic_set_multi(netdev);
- if (adapter->set_mtu)
+ netdev->set_multicast_list(netdev);
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ nx_fw_cmd_set_mtu(adapter, netdev->mtu);
+ else
adapter->set_mtu(adapter, netdev->mtu);
mod_timer(&adapter->watchdog_timer, jiffies);
@@ -858,6 +1126,14 @@ static int netxen_nic_open(struct net_device *netdev)
netif_start_queue(netdev);
return 0;
+
+err_out_free_irq:
+ free_irq(adapter->irq, adapter);
+err_out_free_hw:
+ netxen_free_hw_resources(adapter);
+err_out_free_sw:
+ netxen_free_sw_resources(adapter);
+ return err;
}
/*
@@ -866,9 +1142,6 @@ static int netxen_nic_open(struct net_device *netdev)
static int netxen_nic_close(struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
- int i, j;
- struct netxen_cmd_buffer *cmd_buff;
- struct netxen_skb_frag *buffrag;
netif_carrier_off(netdev);
netif_stop_queue(netdev);
@@ -879,30 +1152,8 @@ static int netxen_nic_close(struct net_device *netdev)
netxen_nic_disable_int(adapter);
- cmd_buff = adapter->cmd_buf_arr;
- for (i = 0; i < adapter->max_tx_desc_count; i++) {
- buffrag = cmd_buff->frag_array;
- if (buffrag->dma) {
- pci_unmap_single(adapter->pdev, buffrag->dma,
- buffrag->length, PCI_DMA_TODEVICE);
- buffrag->dma = 0ULL;
- }
- for (j = 0; j < cmd_buff->frag_count; j++) {
- buffrag++;
- if (buffrag->dma) {
- pci_unmap_page(adapter->pdev, buffrag->dma,
- buffrag->length,
- PCI_DMA_TODEVICE);
- buffrag->dma = 0ULL;
- }
- }
- /* Free the skb we received in netxen_nic_xmit_frame */
- if (cmd_buff->skb) {
- dev_kfree_skb_any(cmd_buff->skb);
- cmd_buff->skb = NULL;
- }
- cmd_buff++;
- }
+ netxen_release_tx_buffers(adapter);
+
if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) {
FLUSH_SCHEDULED_WORK();
del_timer_sync(&adapter->watchdog_timer);
@@ -911,6 +1162,31 @@ static int netxen_nic_close(struct net_device *netdev)
return 0;
}
+void netxen_tso_check(struct netxen_adapter *adapter,
+ struct cmd_desc_type0 *desc, struct sk_buff *skb)
+{
+ if (desc->mss) {
+ desc->total_hdr_length = (sizeof(struct ethhdr) +
+ ip_hdrlen(skb) + tcp_hdrlen(skb));
+
+ if ((NX_IS_REVISION_P3(adapter->ahw.revision_id)) &&
+ (skb->protocol == htons(ETH_P_IPV6)))
+ netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO6);
+ else
+ netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
+
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+ netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
+ else if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+ netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
+ else
+ return;
+ }
+ desc->tcp_hdr_offset = skb_transport_offset(skb);
+ desc->ip_hdr_offset = skb_network_offset(skb);
+}
+
static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
{
struct netxen_adapter *adapter = netdev_priv(netdev);
@@ -932,7 +1208,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* There 4 fragments per descriptor */
no_of_desc = (frag_count + 3) >> 2;
- if (netdev->features & NETIF_F_TSO) {
+ if (netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) {
if (skb_shinfo(skb)->gso_size > 0) {
no_of_desc++;
@@ -959,7 +1235,8 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
/* Take skb->data itself */
pbuf = &adapter->cmd_buf_arr[producer];
- if ((netdev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size > 0) {
+ if ((netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
+ skb_shinfo(skb)->gso_size > 0) {
pbuf->mss = skb_shinfo(skb)->gso_size;
hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
} else {
@@ -1086,6 +1363,89 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}
+static int netxen_nic_check_temp(struct netxen_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ uint32_t temp, temp_state, temp_val;
+ int rv = 0;
+
+ temp = adapter->pci_read_normalize(adapter, CRB_TEMP_STATE);
+
+ temp_state = nx_get_temp_state(temp);
+ temp_val = nx_get_temp_val(temp);
+
+ if (temp_state == NX_TEMP_PANIC) {
+ printk(KERN_ALERT
+ "%s: Device temperature %d degrees C exceeds"
+ " maximum allowed. Hardware has been shut down.\n",
+ netxen_nic_driver_name, temp_val);
+
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ rv = 1;
+ } else if (temp_state == NX_TEMP_WARN) {
+ if (adapter->temp == NX_TEMP_NORMAL) {
+ printk(KERN_ALERT
+ "%s: Device temperature %d degrees C "
+ "exceeds operating range."
+ " Immediate action needed.\n",
+ netxen_nic_driver_name, temp_val);
+ }
+ } else {
+ if (adapter->temp == NX_TEMP_WARN) {
+ printk(KERN_INFO
+ "%s: Device temperature is now %d degrees C"
+ " in normal range.\n", netxen_nic_driver_name,
+ temp_val);
+ }
+ }
+ adapter->temp = temp_state;
+ return rv;
+}
+
+static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ u32 val, port, linkup;
+
+ port = adapter->physical_port;
+
+ if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
+ val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
+ linkup = (val >> port) & 1;
+ } else {
+ if (adapter->fw_major < 4) {
+ val = adapter->pci_read_normalize(adapter,
+ CRB_XG_STATE);
+ val = (val >> port*8) & 0xff;
+ linkup = (val == XG_LINK_UP);
+ } else {
+ val = adapter->pci_read_normalize(adapter,
+ CRB_XG_STATE_P3);
+ val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
+ linkup = (val == XG_LINK_UP_P3);
+ }
+ }
+
+ if (adapter->ahw.linkup && !linkup) {
+ printk(KERN_INFO "%s: %s NIC Link is down\n",
+ netxen_nic_driver_name, netdev->name);
+ adapter->ahw.linkup = 0;
+ if (netif_running(netdev)) {
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+ } else if (!adapter->ahw.linkup && linkup) {
+ printk(KERN_INFO "%s: %s NIC Link is up\n",
+ netxen_nic_driver_name, netdev->name);
+ adapter->ahw.linkup = 1;
+ if (netif_running(netdev)) {
+ netif_carrier_on(netdev);
+ netif_wake_queue(netdev);
+ }
+ }
+}
+
static void netxen_watchdog(unsigned long v)
{
struct netxen_adapter *adapter = (struct netxen_adapter *)v;
@@ -1093,6 +1453,19 @@ static void netxen_watchdog(unsigned long v)
SCHEDULE_WORK(&adapter->watchdog_task);
}
+void netxen_watchdog_task(struct work_struct *work)
+{
+ struct netxen_adapter *adapter =
+ container_of(work, struct netxen_adapter, watchdog_task);
+
+ if ((adapter->portnum == 0) && netxen_nic_check_temp(adapter))
+ return;
+
+ netxen_nic_handle_phy_intr(adapter);
+
+ mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+}
+
static void netxen_tx_timeout(struct net_device *netdev)
{
struct netxen_adapter *adapter = (struct netxen_adapter *)
@@ -1118,6 +1491,38 @@ static void netxen_tx_timeout_task(struct work_struct *work)
netif_wake_queue(adapter->netdev);
}
+/*
+ * netxen_nic_get_stats - Get System Network Statistics
+ * @netdev: network interface device structure
+ */
+struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
+{
+ struct netxen_adapter *adapter = netdev_priv(netdev);
+ struct net_device_stats *stats = &adapter->net_stats;
+
+ memset(stats, 0, sizeof(*stats));
+
+ /* total packets received */
+ stats->rx_packets = adapter->stats.no_rcv;
+ /* total packets transmitted */
+ stats->tx_packets = adapter->stats.xmitedframes +
+ adapter->stats.xmitfinished;
+ /* total bytes received */
+ stats->rx_bytes = adapter->stats.rxbytes;
+ /* total bytes transmitted */
+ stats->tx_bytes = adapter->stats.txbytes;
+ /* bad packets received */
+ stats->rx_errors = adapter->stats.rcvdbadskb;
+ /* packet transmit problems */
+ stats->tx_errors = adapter->stats.nocmddescriptor;
+ /* no space in linux buffers */
+ stats->rx_dropped = adapter->stats.rxdropped;
+ /* no space available in linux */
+ stats->tx_dropped = adapter->stats.txdropped;
+
+ return stats;
+}
+
static inline void
netxen_handle_int(struct netxen_adapter *adapter)
{
@@ -1125,20 +1530,20 @@ netxen_handle_int(struct netxen_adapter *adapter)
napi_schedule(&adapter->napi);
}
-irqreturn_t netxen_intr(int irq, void *data)
+static irqreturn_t netxen_intr(int irq, void *data)
{
struct netxen_adapter *adapter = data;
u32 our_int = 0;
- our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ our_int = adapter->pci_read_normalize(adapter, CRB_INT_VECTOR);
/* not our interrupt */
if ((our_int & (0x80 << adapter->portnum)) == 0)
return IRQ_NONE;
if (adapter->intr_scheme == INTR_SCHEME_PERPORT) {
/* claim interrupt */
- writel(our_int & ~((u32)(0x80 << adapter->portnum)),
- NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+ adapter->pci_write_normalize(adapter, CRB_INT_VECTOR,
+ our_int & ~((u32)(0x80 << adapter->portnum)));
}
netxen_handle_int(adapter);
@@ -1146,7 +1551,7 @@ irqreturn_t netxen_intr(int irq, void *data)
return IRQ_HANDLED;
}
-irqreturn_t netxen_msi_intr(int irq, void *data)
+static irqreturn_t netxen_msi_intr(int irq, void *data)
{
struct netxen_adapter *adapter = data;
@@ -1220,10 +1625,6 @@ module_init(netxen_init_module);
static void __exit netxen_exit_module(void)
{
- /*
- * Wait for some time to allow the dma to drain, if any.
- */
- msleep(100);
pci_unregister_driver(&netxen_driver);
destroy_workqueue(netxen_workq);
}
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index a3bc7cc67a6..4cb8f4a1cf4 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -46,9 +46,8 @@ static int phy_lock(struct netxen_adapter *adapter)
int done = 0, timeout = 0;
while (!done) {
- done =
- readl(pci_base_offset
- (adapter, NETXEN_PCIE_REG(PCIE_SEM3_LOCK)));
+ done = netxen_nic_reg_read(adapter,
+ NETXEN_PCIE_REG(PCIE_SEM3_LOCK));
if (done == 1)
break;
if (timeout >= phy_lock_timeout) {
@@ -63,14 +62,14 @@ static int phy_lock(struct netxen_adapter *adapter)
}
}
- writel(PHY_LOCK_DRIVER,
- NETXEN_CRB_NORMALIZE(adapter, NETXEN_PHY_LOCK_ID));
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_PHY_LOCK_ID, PHY_LOCK_DRIVER);
return 0;
}
static int phy_unlock(struct netxen_adapter *adapter)
{
- readl(pci_base_offset(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK)));
+ adapter->pci_read_immediate(adapter, NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK));
return 0;
}
@@ -109,7 +108,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
* so it cannot be in reset
*/
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
&mac_cfg0, 4))
return -EIO;
if (netxen_gb_get_soft_reset(mac_cfg0)) {
@@ -119,7 +118,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
netxen_gb_rx_reset_pb(temp);
netxen_gb_tx_reset_mac(temp);
netxen_gb_rx_reset_mac(temp);
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(0),
&temp, 4))
return -EIO;
@@ -129,22 +128,22 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
address = 0;
netxen_gb_mii_mgmt_reg_addr(address, reg);
netxen_gb_mii_mgmt_phy_addr(address, phy);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
&address, 4))
return -EIO;
command = 0; /* turn off any prior activity */
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
&command, 4))
return -EIO;
/* send read command */
netxen_gb_mii_mgmt_set_read_cycle(command);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
&command, 4))
return -EIO;
status = 0;
do {
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
&status, 4))
return -EIO;
@@ -154,7 +153,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
&& (timeout++ < NETXEN_NIU_PHY_WAITMAX));
if (timeout < NETXEN_NIU_PHY_WAITMAX) {
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_NIU_GB_MII_MGMT_STATUS(0),
readval, 4))
return -EIO;
@@ -163,7 +162,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long reg,
result = -1;
if (restore)
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(0),
&mac_cfg0, 4))
return -EIO;
@@ -201,7 +200,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
* cannot be in reset
*/
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0),
&mac_cfg0, 4))
return -EIO;
if (netxen_gb_get_soft_reset(mac_cfg0)) {
@@ -212,7 +211,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
netxen_gb_tx_reset_mac(temp);
netxen_gb_rx_reset_mac(temp);
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(0),
&temp, 4))
return -EIO;
@@ -220,24 +219,24 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
}
command = 0; /* turn off any prior activity */
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
&command, 4))
return -EIO;
address = 0;
netxen_gb_mii_mgmt_reg_addr(address, reg);
netxen_gb_mii_mgmt_phy_addr(address, phy);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0),
&address, 4))
return -EIO;
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0),
&val, 4))
return -EIO;
status = 0;
do {
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
&status, 4))
return -EIO;
@@ -252,7 +251,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long reg,
/* restore the state of port 0 MAC in case we tampered with it */
if (restore)
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_0(0),
&mac_cfg0, 4))
return -EIO;
@@ -401,14 +400,16 @@ 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 (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);
@@ -456,12 +457,12 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port)
{
- u32 portnum = adapter->physical_port;
-
- netxen_crb_writelit_adapter(adapter,
- NETXEN_NIU_XGE_CONFIG_1+(0x10000*portnum), 0x1447);
- netxen_crb_writelit_adapter(adapter,
- NETXEN_NIU_XGE_CONFIG_0+(0x10000*portnum), 0x5);
+ if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447);
+ netxen_crb_writelit_adapter(adapter,
+ NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5);
+ }
return 0;
}
@@ -581,10 +582,10 @@ static int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
if ((phy < 0) || (phy > 3))
return -EINVAL;
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy),
&stationhigh, 4))
return -EIO;
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
&stationlow, 4))
return -EIO;
((__le32 *)val)[1] = cpu_to_le32(stationhigh);
@@ -613,14 +614,14 @@ int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
temp[0] = temp[1] = 0;
memcpy(temp + 2, addr, 2);
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx
- (adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
+ if (adapter->hw_write_wx(adapter,
+ NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
return -EIO;
memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32));
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx
- (adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
+ if (adapter->hw_write_wx(adapter,
+ NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
return -2;
netxen_niu_macaddr_get(adapter,
@@ -654,7 +655,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
mac_cfg0 = 0;
netxen_gb_soft_reset(mac_cfg0);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
&mac_cfg0, 4))
return -EIO;
mac_cfg0 = 0;
@@ -666,7 +667,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
netxen_gb_tx_reset_mac(mac_cfg0);
netxen_gb_rx_reset_mac(mac_cfg0);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
&mac_cfg0, 4))
return -EIO;
mac_cfg1 = 0;
@@ -679,7 +680,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
if (mode == NETXEN_NIU_10_100_MB) {
netxen_gb_set_intfmode(mac_cfg1, 1);
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_1(port),
&mac_cfg1, 4))
return -EIO;
@@ -692,7 +693,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
} else if (mode == NETXEN_NIU_1000_MB) {
netxen_gb_set_intfmode(mac_cfg1, 2);
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_GB_MAC_CONFIG_1(port),
&mac_cfg1, 4))
return -EIO;
@@ -704,7 +705,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
}
mii_cfg = 0;
netxen_gb_set_mii_mgmt_clockselect(mii_cfg, 7);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port),
&mii_cfg, 4))
return -EIO;
mac_cfg0 = 0;
@@ -713,7 +714,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
netxen_gb_unset_rx_flowctl(mac_cfg0);
netxen_gb_unset_tx_flowctl(mac_cfg0);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
&mac_cfg0, 4))
return -EIO;
return 0;
@@ -730,7 +731,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter)
return -EINVAL;
mac_cfg0 = 0;
netxen_gb_soft_reset(mac_cfg0);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
&mac_cfg0, 4))
return -EIO;
return 0;
@@ -746,7 +747,7 @@ int netxen_niu_disable_xg_port(struct netxen_adapter *adapter)
return -EINVAL;
mac_cfg = 0;
- if (netxen_nic_hw_write_wx(adapter,
+ if (adapter->hw_write_wx(adapter,
NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), &mac_cfg, 4))
return -EIO;
return 0;
@@ -763,7 +764,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
return -EINVAL;
/* save previous contents */
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
&reg, 4))
return -EIO;
if (mode == NETXEN_NIU_PROMISC_MODE) {
@@ -801,7 +802,7 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter,
return -EIO;
}
}
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR,
&reg, 4))
return -EIO;
return 0;
@@ -826,13 +827,13 @@ int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
case 0:
memcpy(temp + 2, addr, 2);
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
&val, 4))
return -EIO;
memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
&val, 4))
return -EIO;
break;
@@ -840,13 +841,13 @@ int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter,
case 1:
memcpy(temp + 2, addr, 2);
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_1,
&val, 4))
return -EIO;
memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
val = le32_to_cpu(*(__le32 *)temp);
- if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI,
+ if (adapter->hw_write_wx(adapter, NETXEN_NIU_XG1_STATION_ADDR_0_HI,
&val, 4))
return -EIO;
break;
@@ -877,10 +878,10 @@ int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter,
if (phy != 0)
return -EINVAL;
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
&stationhigh, 4))
return -EIO;
- if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
+ if (adapter->hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
&stationlow, 4))
return -EIO;
((__le32 *)val)[1] = cpu_to_le32(stationhigh);
@@ -901,7 +902,7 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
if (port > NETXEN_NIU_MAX_XG_PORTS)
return -EINVAL;
- if (netxen_nic_hw_read_wx(adapter,
+ if (adapter->hw_read_wx(adapter,
NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), &reg, 4))
return -EIO;
if (mode == NETXEN_NIU_PROMISC_MODE)
@@ -909,6 +910,11 @@ int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
else
reg = (reg & ~0x2000UL);
+ if (mode == NETXEN_NIU_ALLMULTI_MODE)
+ reg = (reg | 0x1000UL);
+ else
+ reg = (reg & ~0x1000UL);
+
netxen_crb_writelit_adapter(adapter,
NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg);
diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h
index a566b50f36f..3bfa51b62a4 100644
--- a/drivers/net/netxen/netxen_nic_phan_reg.h
+++ b/drivers/net/netxen/netxen_nic_phan_reg.h
@@ -42,8 +42,11 @@
#define CRB_CMD_CONSUMER_OFFSET NETXEN_NIC_REG(0x0c)
#define CRB_PAUSE_ADDR_LO NETXEN_NIC_REG(0x10) /* C0 EPG BUG */
#define CRB_PAUSE_ADDR_HI NETXEN_NIC_REG(0x14)
-#define CRB_HOST_CMD_ADDR_HI NETXEN_NIC_REG(0x18) /* host add:cmd ring */
-#define CRB_HOST_CMD_ADDR_LO NETXEN_NIC_REG(0x1c)
+#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) /* 4 regs for perf */
#define CRB_CMD_DMA_LOOP NETXEN_NIC_REG(0x24)
#define CRB_RCV_INTR_LOOP NETXEN_NIC_REG(0x28)
@@ -73,8 +76,8 @@
#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_AGENT_GO NETXEN_NIC_REG(0x98) /* NIC pkt gen agent */
+#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)
@@ -97,7 +100,9 @@
#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)
@@ -147,29 +152,15 @@
#define nx_get_temp_state(x) ((x) & 0xffff)
#define nx_encode_temp(val, state) (((val) << 16) | (state))
-/* CRB registers per Rcv Descriptor ring */
-struct netxen_rcv_desc_crb {
- u32 crb_rcv_producer_offset __attribute__ ((aligned(512)));
- u32 crb_rcv_consumer_offset;
- u32 crb_globalrcv_ring;
- u32 crb_rcv_ring_size;
-};
-
/*
* CRB registers used by the receive peg logic.
*/
struct netxen_recv_crb {
- struct netxen_rcv_desc_crb rcv_desc_crb[NUM_RCV_DESC_RINGS];
- u32 crb_rcvstatus_ring;
- u32 crb_rcv_status_producer;
- u32 crb_rcv_status_consumer;
- u32 crb_rcvpeg_state;
- u32 crb_status_ring_size;
+ u32 crb_rcv_producer[NUM_RCV_DESC_RINGS];
+ u32 crb_sts_consumer;
};
-extern struct netxen_recv_crb recv_crb_registers[];
-
/*
* Temperature control.
*/