diff options
Diffstat (limited to 'drivers/net/netxen')
-rw-r--r-- | drivers/net/netxen/Makefile | 9 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic.h | 171 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_ctx.c | 201 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_ethtool.c | 181 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hdr.h | 21 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 595 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.h | 63 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 916 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 1162 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_niu.c | 230 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_phan_reg.h | 10 |
11 files changed, 1556 insertions, 2003 deletions
diff --git a/drivers/net/netxen/Makefile b/drivers/net/netxen/Makefile index 8e7c4c910d2a..cf01a9130c91 100644 --- a/drivers/net/netxen/Makefile +++ b/drivers/net/netxen/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 2003 - 2006 NetXen, Inc. +# Copyright (C) 2003 - 2009 NetXen, Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or @@ -21,11 +21,10 @@ # # Contact Information: # info@netxen.com -# NetXen, -# 3965 Freedom Circle, Fourth floor, -# Santa Clara, CA 95054 +# NetXen Inc, +# 18922 Forge Drive +# Cupertino, CA 95014-0701 # -# Makefile for the NetXen NIC Driver # diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 1ff066b2281a..c40815169f35 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 - 2006 NetXen, Inc. + * Copyright (C) 2003 - 2009 NetXen, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -22,9 +22,10 @@ * * Contact Information: * info@netxen.com - * NetXen, - * 3965 Freedom Circle, Fourth floor, - * Santa Clara, CA 95054 + * NetXen Inc, + * 18922 Forge Drive + * Cupertino, CA 95014-0701 + * */ #ifndef _NETXEN_NIC_H_ @@ -65,8 +66,8 @@ #define _NETXEN_NIC_LINUX_MAJOR 4 #define _NETXEN_NIC_LINUX_MINOR 0 -#define _NETXEN_NIC_LINUX_SUBVERSION 11 -#define NETXEN_NIC_LINUX_VERSIONID "4.0.11" +#define _NETXEN_NIC_LINUX_SUBVERSION 30 +#define NETXEN_NIC_LINUX_VERSIONID "4.0.30" #define NETXEN_VERSION_CODE(a, b, c) (((a) << 16) + ((b) << 8) + (c)) @@ -77,19 +78,19 @@ #define PHAN_VENDOR_ID 0x4040 -#define RCV_DESC_RINGSIZE \ - (sizeof(struct rcv_desc) * adapter->max_rx_desc_count) -#define STATUS_DESC_RINGSIZE \ - (sizeof(struct status_desc)* adapter->max_rx_desc_count) -#define LRO_DESC_RINGSIZE \ - (sizeof(rcvDesc_t) * adapter->max_lro_rx_desc_count) -#define TX_RINGSIZE \ - (sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count) -#define RCV_BUFFSIZE \ - (sizeof(struct netxen_rx_buffer) * rds_ring->max_rx_desc_count) +#define RCV_DESC_RINGSIZE(rds_ring) \ + (sizeof(struct rcv_desc) * (rds_ring)->num_desc) +#define RCV_BUFF_RINGSIZE(rds_ring) \ + (sizeof(struct netxen_rx_buffer) * rds_ring->num_desc) +#define STATUS_DESC_RINGSIZE(sds_ring) \ + (sizeof(struct status_desc) * (sds_ring)->num_desc) +#define TX_BUFF_RINGSIZE(adapter) \ + (sizeof(struct netxen_cmd_buffer) * adapter->num_txd) +#define TX_DESC_RINGSIZE(adapter) \ + (sizeof(struct cmd_desc_type0) * adapter->num_txd) + #define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a))) -#define NETXEN_NETDEV_STATUS 0x1 #define NETXEN_RCV_PRODUCER_OFFSET 0 #define NETXEN_RCV_PEG_DB_ID 2 #define NETXEN_HOST_DUMMY_DMA_SIZE 1024 @@ -188,22 +189,12 @@ /* Host writes the following to notify that it has done the init-handshake */ #define PHAN_INITIALIZE_ACK 0xf00f -#define NUM_RCV_DESC_RINGS 3 /* No of Rcv Descriptor contexts */ - -/* descriptor types */ -#define RCV_DESC_NORMAL 0x01 -#define RCV_DESC_JUMBO 0x02 -#define RCV_DESC_LRO 0x04 -#define RCV_DESC_NORMAL_CTXID 0 -#define RCV_DESC_JUMBO_CTXID 1 -#define RCV_DESC_LRO_CTXID 2 +#define NUM_RCV_DESC_RINGS 3 +#define NUM_STS_DESC_RINGS 4 -#define RCV_DESC_TYPE(ID) \ - ((ID == RCV_DESC_JUMBO_CTXID) \ - ? RCV_DESC_JUMBO \ - : ((ID == RCV_DESC_LRO_CTXID) \ - ? RCV_DESC_LRO : \ - (RCV_DESC_NORMAL))) +#define RCV_RING_NORMAL 0 +#define RCV_RING_JUMBO 1 +#define RCV_RING_LRO 2 #define MAX_CMD_DESCRIPTORS 4096 #define MAX_RCV_DESCRIPTORS 16384 @@ -357,10 +348,7 @@ struct cmd_desc_type0 { __le64 addr_buffer1; }; - __le16 buffer1_length; - __le16 buffer2_length; - __le16 buffer3_length; - __le16 buffer4_length; + __le16 buffer_length[4]; union { struct { @@ -391,11 +379,8 @@ struct rcv_desc { #define STATUS_CKSUM_OK (2) /* owner bits of status_desc */ -#define STATUS_OWNER_HOST (0x1) -#define STATUS_OWNER_PHANTOM (0x2) - -#define NETXEN_PROT_IP (1) -#define NETXEN_PROT_UNKNOWN (0) +#define STATUS_OWNER_HOST (0x1ULL << 56) +#define STATUS_OWNER_PHANTOM (0x2ULL << 56) /* Note: sizeof(status_desc) should always be a mutliple of 2 */ @@ -421,15 +406,6 @@ struct rcv_desc { #define netxen_get_sts_opcode(sts_data) \ (((sts_data) >> 58) & 0x03F) -#define netxen_get_sts_owner(status_desc) \ - ((le64_to_cpu((status_desc)->status_desc_data) >> 56) & 0x03) -#define netxen_set_sts_owner(status_desc, val) { \ - (status_desc)->status_desc_data = \ - ((status_desc)->status_desc_data & \ - ~cpu_to_le64(0x3ULL << 56)) | \ - cpu_to_le64((u64)((val) & 0x3) << 56); \ -} - 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 pkt_offset @@ -712,6 +688,15 @@ typedef enum { NETXEN_FIXED_START = 0x3F0000 /* backup of crbinit */ } netxen_flash_map_t; +#define NX_FW_VERSION_OFFSET (NETXEN_USER_START+0x408) +#define NX_FW_SIZE_OFFSET (NETXEN_USER_START+0x40c) +#define NX_BIOS_VERSION_OFFSET (NETXEN_USER_START+0x83c) +#define NX_FW_MAGIC_OFFSET (NETXEN_BRDCFG_START+0x128) +#define NX_FW_MIN_SIZE (0x3fffff) +#define NX_P2_MN_ROMIMAGE 0 +#define NX_P3_CT_ROMIMAGE 1 +#define NX_P3_MN_ROMIMAGE 2 + #define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */ #define NETXEN_FLASH_START (NETXEN_CRBINIT_START) @@ -739,7 +724,7 @@ extern char netxen_nic_driver_name[]; #endif /* Number of status descriptors to handle per interrupt */ -#define MAX_STATUS_HANDLE (128) +#define MAX_STATUS_HANDLE (64) /* * netxen_skb_frag{} is to contain mapping info for each SG list. This @@ -783,9 +768,6 @@ struct netxen_rx_buffer { u64 dma; u16 ref_handle; u16 state; - u32 lro_expected_frags; - u32 lro_current_frags; - u32 lro_length; }; /* Board types */ @@ -800,21 +782,19 @@ struct netxen_hardware_context { void __iomem *pci_base0; void __iomem *pci_base1; void __iomem *pci_base2; - unsigned long first_page_group_end; - 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 cut_through; u8 revision_id; - u16 board_type; - struct netxen_board_info boardcfg; + u16 port_type; + int board_type; u32 linkup; /* Address of cmd ring in Phantom */ struct cmd_desc_type0 *cmd_desc_head; @@ -823,8 +803,6 @@ struct netxen_hardware_context { int pci_func; }; -#define RCV_RING_LRO RCV_DESC_LRO - #define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */ #define ETHERNET_FCS_SIZE 4 @@ -850,16 +828,36 @@ struct netxen_adapter_stats { * be one Rcv Descriptor for normal packets, one for jumbo and may be others. */ struct nx_host_rds_ring { - u32 flags; u32 producer; - dma_addr_t phys_addr; - u32 crb_rcv_producer; /* reg offset */ - struct rcv_desc *desc_head; /* address of rx ring in Phantom */ - u32 max_rx_desc_count; + u32 crb_rcv_producer; + u32 num_desc; u32 dma_size; u32 skb_size; - struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */ + u32 flags; + struct rcv_desc *desc_head; + struct netxen_rx_buffer *rx_buf_arr; struct list_head free_list; + spinlock_t lock; + dma_addr_t phys_addr; +}; + +struct nx_host_sds_ring { + u32 consumer; + u32 crb_sts_consumer; + u32 crb_intr_mask; + u32 num_desc; + + struct status_desc *desc_head; + struct netxen_adapter *adapter; + struct napi_struct napi; + struct list_head free_list[NUM_RCV_DESC_RINGS]; + + u16 clean_tx; + u16 post_rxd; + int irq; + + dma_addr_t phys_addr; + char name[IFNAMSIZ+4]; }; /* @@ -874,10 +872,7 @@ struct netxen_recv_context { 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 status_desc *rcv_status_desc_head; + struct nx_host_sds_ring sds_rings[NUM_STS_DESC_RINGS]; }; /* New HW context creation */ @@ -1203,13 +1198,13 @@ typedef struct { #define NETXEN_IS_MSI_FAMILY(adapter) \ ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED)) -#define MSIX_ENTRIES_PER_ADAPTER 1 +#define MSIX_ENTRIES_PER_ADAPTER NUM_STS_DESC_RINGS #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_NETDEV_WEIGHT 128 #define NETXEN_ADAPTER_UP_MAGIC 777 #define NETXEN_NIC_PEG_TUNE 0 @@ -1224,7 +1219,6 @@ struct netxen_adapter { struct net_device *netdev; struct pci_dev *pdev; int pci_using_dac; - struct napi_struct napi; struct net_device_stats net_stats; int mtu; int portnum; @@ -1236,7 +1230,6 @@ struct netxen_adapter { 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; @@ -1246,20 +1239,20 @@ struct netxen_adapter { 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; + spinlock_t tx_clean_lock; - u32 max_tx_desc_count; - u32 max_rx_desc_count; - u32 max_jumbo_rx_desc_count; - u32 max_lro_rx_desc_count; + u32 num_txd; + u32 num_rxd; + u32 num_jumbo_rxd; + u32 num_lro_rxd; int max_rds_rings; + int max_sds_rings; u32 flags; u32 irq; @@ -1267,9 +1260,9 @@ struct netxen_adapter { u32 temp; u32 fw_major; + u32 fw_version; - u8 msix_supported; - u8 max_possible_rss_rings; + int msix_supported; struct msix_entry msix_entries[MSIX_ENTRIES_PER_ADAPTER]; struct netxen_adapter_stats stats; @@ -1279,7 +1272,6 @@ struct netxen_adapter { u16 state; u16 link_autoneg; int rx_csum; - int status; struct netxen_cmd_buffer *cmd_buf_arr; /* Command buffers for xmit */ @@ -1287,7 +1279,7 @@ struct netxen_adapter { * Receive instances. These can be either one per port, * or one per peg, etc. */ - struct netxen_recv_context recv_ctx[MAX_RCV_CTX]; + struct netxen_recv_context recv_ctx; int is_up; struct netxen_dummy_dma dummy_dma; @@ -1398,6 +1390,8 @@ 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); +void netxen_nic_get_firmware_info(struct netxen_adapter *adapter); +int netxen_nic_wol_supported(struct netxen_adapter *adapter); int netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off, void *data, int len); @@ -1471,15 +1465,16 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter); int netxen_init_firmware(struct netxen_adapter *adapter); void netxen_nic_clear_stats(struct netxen_adapter *adapter); void netxen_watchdog_task(struct work_struct *work); -void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, - u32 ringid); +void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, + struct nx_host_rds_ring *rds_ring); int netxen_process_cmd_ring(struct netxen_adapter *adapter); -u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max); +int netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max); void netxen_p2_nic_set_multi(struct net_device *netdev); void netxen_p3_nic_set_multi(struct net_device *netdev); void netxen_p3_free_mac_list(struct netxen_adapter *adapter); int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32); int netxen_config_intr_coalesce(struct netxen_adapter *adapter); +int netxen_config_rss(struct netxen_adapter *adapter, int enable); int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu); int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c index 746bdb470418..9234473bc08a 100644 --- a/drivers/net/netxen/netxen_nic_ctx.c +++ b/drivers/net/netxen/netxen_nic_ctx.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 - 2008 NetXen, Inc. + * Copyright (C) 2003 - 2009 NetXen, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -22,9 +22,9 @@ * * Contact Information: * info@netxen.com - * NetXen, - * 3965 Freedom Circle, Fourth floor, - * Santa Clara, CA 95054 + * NetXen Inc, + * 18922 Forge Drive + * Cupertino, CA 95014-0701 * */ @@ -141,7 +141,7 @@ int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu) { u32 rcode = NX_RCODE_SUCCESS; - struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0]; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE) rcode = netxen_issue_cmd(adapter, @@ -169,6 +169,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) nx_cardrsp_rds_ring_t *prsp_rds; nx_cardrsp_sds_ring_t *prsp_sds; struct nx_host_rds_ring *rds_ring; + struct nx_host_sds_ring *sds_ring; dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; u64 phys_addr; @@ -179,11 +180,10 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) int err; - struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0]; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; - /* only one sds ring for now */ nrds_rings = adapter->max_rds_rings; - nsds_rings = 1; + nsds_rings = adapter->max_sds_rings; rq_size = SIZEOF_HOSTRQ_RX(nx_hostrq_rx_ctx_t, nrds_rings, nsds_rings); @@ -231,7 +231,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) 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_size = cpu_to_le32(rds_ring->num_desc); prq_rds[i].ring_kind = cpu_to_le32(i); prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size); } @@ -239,11 +239,14 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + le32_to_cpu(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_le16(0); + for (i = 0; i < nsds_rings; i++) { + + sds_ring = &recv_ctx->sds_rings[i]; + + prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr); + prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc); + prq_sds[i].msi_index = cpu_to_le16(i); + } phys_addr = hostrq_phys_addr; err = netxen_issue_cmd(adapter, @@ -272,11 +275,16 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) prsp_sds = ((nx_cardrsp_sds_ring_t *) &prsp->data[le32_to_cpu(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); + for (i = 0; i < le16_to_cpu(prsp->num_sds_rings); i++) { + sds_ring = &recv_ctx->sds_rings[i]; + + reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); + sds_ring->crb_sts_consumer = NETXEN_NIC_REG(reg - 0x200); + + reg = le32_to_cpu(prsp_sds[i].interrupt_crb); + sds_ring->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); @@ -292,7 +300,7 @@ out_free_rq: static void nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter) { - struct netxen_recv_context *recv_ctx = &adapter->recv_ctx[0]; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; if (netxen_issue_cmd(adapter, adapter->ahw.pci_func, @@ -362,7 +370,7 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) 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); + prq_cds->ring_size = cpu_to_le32(adapter->num_txd); phys_addr = rq_phys_addr; err = netxen_issue_cmd(adapter, @@ -488,30 +496,28 @@ netxen_init_old_ctx(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; - int ctx, ring; + struct nx_host_sds_ring *sds_ring; + int 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); + cpu_to_le32(adapter->num_txd); - for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { - recv_ctx = &adapter->recv_ctx[ctx]; + recv_ctx = &adapter->recv_ctx; - for (ring = 0; ring < adapter->max_rds_rings; ring++) { - rds_ring = &recv_ctx->rds_rings[ring]; + 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->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->num_desc); } + sds_ring = &recv_ctx->sds_rings[0]; + adapter->ctx_desc->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr); + adapter->ctx_desc->sts_ring_size = cpu_to_le32(sds_ring->num_desc); adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_LO(func_id), lower32(adapter->ctx_desc_phys_addr)); @@ -533,9 +539,13 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) u32 state = 0; void *addr; int err = 0; - int ctx, ring; + int ring; struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; + struct nx_host_sds_ring *sds_ring; + + struct pci_dev *pdev = adapter->pdev; + struct net_device *netdev = adapter->netdev; err = netxen_receive_peg_ready(adapter); if (err) { @@ -544,12 +554,12 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) return err; } - addr = pci_alloc_consistent(adapter->pdev, + addr = pci_alloc_consistent(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"); + dev_err(&pdev->dev, "failed to allocate hw context\n"); return -ENOMEM; } memset(addr, 0, sizeof(struct netxen_ring_ctx)); @@ -562,61 +572,57 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) (__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, + addr = pci_alloc_consistent(pdev, + TX_DESC_RINGSIZE(adapter), &hw->cmd_desc_phys_addr); if (addr == NULL) { - printk(KERN_ERR "%s failed to allocate tx desc ring\n", - netxen_nic_driver_name); + dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n", + netdev->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]; - } + recv_ctx = &adapter->recv_ctx; - /* status desc ring */ + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; addr = pci_alloc_consistent(adapter->pdev, - STATUS_DESC_RINGSIZE, - &recv_ctx->rcv_status_desc_phys_addr); + RCV_DESC_RINGSIZE(rds_ring), + &rds_ring->phys_addr); if (addr == NULL) { - printk(KERN_ERR "%s failed to allocate sts desc ring\n", - netxen_nic_driver_name); + dev_err(&pdev->dev, + "%s: failed to allocate rds ring [%d]\n", + netdev->name, ring); err = -ENOMEM; goto err_out_free; } - recv_ctx->rcv_status_desc_head = (struct status_desc *)addr; + rds_ring->desc_head = (struct rcv_desc *)addr; if (adapter->fw_major < 4) - recv_ctx->crb_sts_consumer = + rds_ring->crb_rcv_producer = recv_crb_registers[adapter->portnum]. - crb_sts_consumer; + crb_rcv_producer[ring]; } + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + + addr = pci_alloc_consistent(adapter->pdev, + STATUS_DESC_RINGSIZE(sds_ring), + &sds_ring->phys_addr); + if (addr == NULL) { + dev_err(&pdev->dev, + "%s: failed to allocate sds ring [%d]\n", + netdev->name, ring); + err = -ENOMEM; + goto err_out_free; + } + sds_ring->desc_head = (struct status_desc *)addr; + } + + if (adapter->fw_major >= 4) { adapter->intr_scheme = INTR_SCHEME_PERPORT; adapter->msi_mode = MSI_MODE_MULTIFUNC; @@ -628,12 +634,16 @@ int netxen_alloc_hw_resources(struct netxen_adapter *adapter) if (err) goto err_out_free; } else { + sds_ring = &recv_ctx->sds_rings[0]; + sds_ring->crb_sts_consumer = + recv_crb_registers[adapter->portnum].crb_sts_consumer; 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]; + recv_ctx->sds_rings[0].crb_intr_mask = + sw_int_mask[adapter->portnum]; err = netxen_init_old_ctx(adapter); if (err) { @@ -654,7 +664,8 @@ 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; + struct nx_host_sds_ring *sds_ring; + int ring; if (adapter->fw_major >= 4) { nx_fw_cmd_destroy_tx_ctx(adapter); @@ -673,32 +684,34 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) if (adapter->ahw.cmd_desc_head != NULL) { pci_free_consistent(adapter->pdev, sizeof(struct cmd_desc_type0) * - adapter->max_tx_desc_count, + adapter->num_txd, 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; - } + recv_ctx = &adapter->recv_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), + rds_ring->desc_head, + rds_ring->phys_addr); + rds_ring->desc_head = NULL; } + } + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; - if (recv_ctx->rcv_status_desc_head != NULL) { + if (sds_ring->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; + STATUS_DESC_RINGSIZE(sds_ring), + sds_ring->desc_head, + sds_ring->phys_addr); + sds_ring->desc_head = NULL; } } } diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 0894a7be0225..a677ff895184 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 - 2006 NetXen, Inc. + * Copyright (C) 2003 - 2009 NetXen, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -22,12 +22,9 @@ * * Contact Information: * info@netxen.com - * NetXen, - * 3965 Freedom Circle, Fourth floor, - * Santa Clara, CA 95054 - * - * - * ethtool support for netxen nic + * NetXen Inc, + * 18922 Forge Drive + * Cupertino, CA 95014-0701 * */ @@ -118,10 +115,9 @@ static int netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct netxen_adapter *adapter = netdev_priv(dev); - struct netxen_board_info *boardinfo = &adapter->ahw.boardcfg; /* read which mode */ - if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | @@ -140,7 +136,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->duplex = adapter->link_duplex; ecmd->autoneg = adapter->link_autoneg; - } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { u32 val; adapter->hw_read_wx(adapter, NETXEN_PORT_MODE_ADDR, &val, 4); @@ -172,7 +168,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->phy_address = adapter->physical_port; ecmd->transceiver = XCVR_EXTERNAL; - switch ((netxen_brdtype_t) boardinfo->board_type) { + switch ((netxen_brdtype_t)adapter->ahw.board_type) { case NETXEN_BRDTYPE_P2_SB35_4G: case NETXEN_BRDTYPE_P2_SB31_2G: case NETXEN_BRDTYPE_P3_REF_QG: @@ -188,7 +184,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->supported |= SUPPORTED_TP; ecmd->advertising |= ADVERTISED_TP; ecmd->port = PORT_TP; - ecmd->autoneg = (boardinfo->board_type == + ecmd->autoneg = (adapter->ahw.board_type == NETXEN_BRDTYPE_P2_SB31_10G_CX4) ? (AUTONEG_DISABLE) : (adapter->link_autoneg); break; @@ -215,7 +211,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->autoneg = AUTONEG_DISABLE; break; case NETXEN_BRDTYPE_P3_10G_TP: - if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { ecmd->autoneg = AUTONEG_DISABLE; ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP); ecmd->advertising |= @@ -231,7 +227,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) break; default: printk(KERN_ERR "netxen-nic: Unsupported board model %d\n", - (netxen_brdtype_t) boardinfo->board_type); + (netxen_brdtype_t)adapter->ahw.board_type); return -EIO; } @@ -245,7 +241,7 @@ netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) __u32 status; /* read which mode */ - if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { /* autonegotiation */ if (adapter->phy_write && adapter->phy_write(adapter, @@ -433,7 +429,7 @@ static u32 netxen_nic_test_link(struct net_device *dev) int val; /* read which mode */ - if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { if (adapter->phy_read && adapter->phy_read(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, @@ -443,7 +439,7 @@ static u32 netxen_nic_test_link(struct net_device *dev) val = netxen_get_phy_link(status); return !val; } - } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { val = adapter->pci_read_normalize(adapter, CRB_XG_STATE); return (val == XG_LINK_UP) ? 0 : 1; } @@ -473,95 +469,20 @@ 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) -{ - struct netxen_adapter *adapter = netdev_priv(dev); - int offset = eeprom->offset; - static int flash_start; - static int ready_to_flash; - int ret; - - if (flash_start == 0) { - netxen_halt_pegs(adapter); - ret = netxen_flash_unlock(adapter); - if (ret < 0) { - printk(KERN_ERR "%s: Flash unlock failed.\n", - netxen_nic_driver_name); - return ret; - } - printk(KERN_INFO "%s: flash unlocked. \n", - netxen_nic_driver_name); - ret = netxen_flash_erase_secondary(adapter); - if (ret != FLASH_SUCCESS) { - printk(KERN_ERR "%s: Flash erase failed.\n", - netxen_nic_driver_name); - return ret; - } - printk(KERN_INFO "%s: secondary flash erased successfully.\n", - netxen_nic_driver_name); - flash_start = 1; - return 0; - } - - if (offset == NETXEN_BOOTLD_START) { - ret = netxen_flash_erase_primary(adapter); - if (ret != FLASH_SUCCESS) { - printk(KERN_ERR "%s: Flash erase failed.\n", - netxen_nic_driver_name); - return ret; - } - - ret = netxen_rom_se(adapter, NETXEN_USER_START); - if (ret != FLASH_SUCCESS) - return ret; - ret = netxen_rom_se(adapter, NETXEN_FIXED_START); - if (ret != FLASH_SUCCESS) - return ret; - - printk(KERN_INFO "%s: primary flash erased successfully\n", - netxen_nic_driver_name); - - ret = netxen_backup_crbinit(adapter); - if (ret != FLASH_SUCCESS) { - printk(KERN_ERR "%s: CRBinit backup failed.\n", - netxen_nic_driver_name); - return ret; - } - printk(KERN_INFO "%s: CRBinit backup done.\n", - netxen_nic_driver_name); - ready_to_flash = 1; - } - - if (!ready_to_flash) { - printk(KERN_ERR "%s: Invalid write sequence, returning...\n", - netxen_nic_driver_name); - return -EINVAL; - } - - 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) { struct netxen_adapter *adapter = netdev_priv(dev); - int i; ring->rx_pending = 0; ring->rx_jumbo_pending = 0; - for (i = 0; i < MAX_RCV_CTX; ++i) { - ring->rx_pending += adapter->recv_ctx[i]. - rds_rings[RCV_DESC_NORMAL_CTXID].max_rx_desc_count; - ring->rx_jumbo_pending += adapter->recv_ctx[i]. - rds_rings[RCV_DESC_JUMBO_CTXID].max_rx_desc_count; - } - ring->tx_pending = adapter->max_tx_desc_count; + ring->rx_pending += adapter->recv_ctx. + rds_rings[RCV_RING_NORMAL].num_desc; + ring->rx_jumbo_pending += adapter->recv_ctx. + rds_rings[RCV_RING_JUMBO].num_desc; + ring->tx_pending = adapter->num_txd; - if (adapter->ahw.board_type == NETXEN_NIC_GBE) + if (adapter->ahw.port_type == NETXEN_NIC_GBE) ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G; else ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G; @@ -579,7 +500,7 @@ netxen_nic_get_pauseparam(struct net_device *dev, __u32 val; int port = adapter->physical_port; - if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) return; /* get flow control settings */ @@ -602,7 +523,7 @@ netxen_nic_get_pauseparam(struct net_device *dev, pause->tx_pause = !(netxen_gb_get_gb3_mask(val)); break; } - } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) return; pause->rx_pause = 1; @@ -613,7 +534,7 @@ netxen_nic_get_pauseparam(struct net_device *dev, pause->tx_pause = !(netxen_xg_get_xg1_mask(val)); } else { printk(KERN_ERR"%s: Unknown board type: %x\n", - netxen_nic_driver_name, adapter->ahw.board_type); + netxen_nic_driver_name, adapter->ahw.port_type); } } @@ -625,7 +546,7 @@ netxen_nic_set_pauseparam(struct net_device *dev, __u32 val; int port = adapter->physical_port; /* read mode */ - if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) return -EIO; /* set flow control */ @@ -669,7 +590,7 @@ netxen_nic_set_pauseparam(struct net_device *dev, break; } netxen_nic_write_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, val); - } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) return -EIO; netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val); @@ -688,7 +609,7 @@ netxen_nic_set_pauseparam(struct net_device *dev, } else { printk(KERN_ERR "%s: Unknown board type: %x\n", netxen_nic_driver_name, - adapter->ahw.board_type); + adapter->ahw.port_type); } return 0; } @@ -810,6 +731,53 @@ static int netxen_nic_set_tso(struct net_device *dev, u32 data) return 0; } +static void +netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct netxen_adapter *adapter = netdev_priv(dev); + u32 wol_cfg = 0; + + wol->supported = 0; + wol->wolopts = 0; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return; + + wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV); + if (wol_cfg & (1UL << adapter->portnum)) + wol->supported |= WAKE_MAGIC; + + wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG); + if (wol_cfg & (1UL << adapter->portnum)) + wol->wolopts |= WAKE_MAGIC; +} + +static int +netxen_nic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct netxen_adapter *adapter = netdev_priv(dev); + u32 wol_cfg = 0; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return -EOPNOTSUPP; + + if (wol->wolopts & ~WAKE_MAGIC) + return -EOPNOTSUPP; + + wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV); + if (!(wol_cfg & (1 << adapter->portnum))) + return -EOPNOTSUPP; + + wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG); + if (wol->wolopts & WAKE_MAGIC) + wol_cfg |= 1UL << adapter->portnum; + else + wol_cfg &= ~(1UL << adapter->portnum); + netxen_nic_reg_write(adapter, NETXEN_WOL_CONFIG, wol_cfg); + + 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 @@ -906,9 +874,6 @@ 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, @@ -916,6 +881,8 @@ struct ethtool_ops netxen_nic_ethtool_ops = { .set_sg = ethtool_op_set_sg, .get_tso = netxen_nic_get_tso, .set_tso = netxen_nic_set_tso, + .get_wol = netxen_nic_get_wol, + .set_wol = netxen_nic_set_wol, .self_test = netxen_nic_diag_test, .get_strings = netxen_nic_get_strings, .get_ethtool_stats = netxen_nic_get_ethtool_stats, diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index e80f9e3e5973..016c62129c76 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 - 2006 NetXen, Inc. + * Copyright (C) 2003 - 2009 NetXen, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -22,9 +22,10 @@ * * Contact Information: * info@netxen.com - * NetXen, - * 3965 Freedom Circle, Fourth floor, - * Santa Clara, CA 95054 + * NetXen Inc, + * 18922 Forge Drive + * Cupertino, CA 95014-0701 + * */ #ifndef __NETXEN_NIC_HDR_H_ @@ -362,12 +363,6 @@ enum { #define NETXEN_HW_CRB_HUB_AGT_ADR_LPC \ ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_LPC_CRB_AGT_ADR) -/* - * MAX_RCV_CTX : The number of receive contexts that are available on - * the phantom. - */ -#define MAX_RCV_CTX 1 - #define NETXEN_SRE_INT_STATUS (NETXEN_CRB_SRE + 0x00034) #define NETXEN_SRE_PBI_ACTIVE_STATUS (NETXEN_CRB_SRE + 0x01014) #define NETXEN_SRE_L1RE_CTL (NETXEN_CRB_SRE + 0x03000) @@ -858,6 +853,12 @@ enum { #define NETXEN_PORT_MODE_ADDR (NETXEN_CAM_RAM(0x24)) #define NETXEN_WOL_PORT_MODE (NETXEN_CAM_RAM(0x198)) +#define NETXEN_WOL_CONFIG_NV (NETXEN_CAM_RAM(0x184)) +#define NETXEN_WOL_CONFIG (NETXEN_CAM_RAM(0x188)) + +#define NX_PEG_TUNE_MN_PRESENT 0x1 +#define NX_PEG_TUNE_CAPABILITY (NETXEN_CAM_RAM(0x02c)) + #define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14) #define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC))) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 7fea77088108..5026811c04ce 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 - 2006 NetXen, Inc. + * Copyright (C) 2003 - 2009 NetXen, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -22,12 +22,9 @@ * * Contact Information: * info@netxen.com - * NetXen, - * 3965 Freedom Circle, Fourth floor, - * Santa Clara, CA 95054 - * - * - * Source file for NIC routines to access the Phantom hardware + * NetXen Inc, + * 18922 Forge Drive + * Cupertino, CA 95014-0701 * */ @@ -35,7 +32,7 @@ #include "netxen_nic_hw.h" #include "netxen_nic_phan_reg.h" - +#include <linux/firmware.h> #include <net/ip.h> #define MASK(n) ((1ULL<<(n))-1) @@ -518,7 +515,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter, &cmd_desc_arr[i], sizeof(struct cmd_desc_type0)); producer = get_next_index(producer, - adapter->max_tx_desc_count); + adapter->num_txd); i++; } while (i != nr_elements); @@ -673,6 +670,53 @@ int netxen_config_intr_coalesce(struct netxen_adapter *adapter) return rv; } +#define RSS_HASHTYPE_IP_TCP 0x3 + +int netxen_config_rss(struct netxen_adapter *adapter, int enable) +{ + nx_nic_req_t req; + u64 word; + int i, rv; + + u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL, + 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL, + 0x255b0ec26d5a56daULL }; + + + memset(&req, 0, sizeof(nx_nic_req_t)); + req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); + + word = NX_NIC_H2C_OPCODE_CONFIG_RSS | ((u64)adapter->portnum << 16); + req.req_hdr = cpu_to_le64(word); + + /* + * RSS request: + * bits 3-0: hash_method + * 5-4: hash_type_ipv4 + * 7-6: hash_type_ipv6 + * 8: enable + * 9: use indirection table + * 47-10: reserved + * 63-48: indirection table mask + */ + word = ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) | + ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) | + ((u64)(enable & 0x1) << 8) | + ((0x7ULL) << 48); + req.words[0] = cpu_to_le64(word); + for (i = 0; i < 5; i++) + req.words[i+1] = cpu_to_le64(key[i]); + + + rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); + if (rv != 0) { + printk(KERN_ERR "%s: could not configure RSS\n", + adapter->netdev->name); + } + + return rv; +} + /* * netxen_nic_change_mtu - Change the Maximum Transfer Unit * @returns 0 on success, negative on failure @@ -709,9 +753,8 @@ int netxen_nic_change_mtu(struct net_device *netdev, int mtu) static int netxen_get_flash_block(struct netxen_adapter *adapter, int base, int size, __le32 * buf) { - int i, addr; + int i, v, addr; __le32 *ptr32; - u32 v; addr = base; ptr32 = buf; @@ -914,13 +957,12 @@ 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)); + writel(adapter->crb_win, (adapter->ahw.pci_base0 + CRB_WINDOW_2M)); /* * 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)); + win_read = readl(adapter->ahw.pci_base0 + CRB_WINDOW_2M); if (win_read != adapter->crb_win) { printk(KERN_ERR "%s: Written crbwin (0x%x) != " "Read crbwin (0x%x), off=0x%lx\n", @@ -930,24 +972,69 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off) (ulong)adapter->ahw.pci_base0; } -int netxen_load_firmware(struct netxen_adapter *adapter) +static int +netxen_do_load_firmware(struct netxen_adapter *adapter, const char *fwname, + const struct firmware *fw) { - int i; - u32 data, size = 0; - u32 flashaddr = NETXEN_BOOTLD_START; + u64 *ptr64; + u32 i, flashaddr, size; + struct pci_dev *pdev = adapter->pdev; - size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START)/4; + if (fw) + dev_info(&pdev->dev, "loading firmware from file %s\n", fwname); + else + dev_info(&pdev->dev, "loading firmware from flash\n"); 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++) { - if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) - return -EIO; + if (fw) { + __le64 data; - adapter->pci_mem_write(adapter, flashaddr, &data, 4); - flashaddr += 4; + size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8; + + ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START]; + flashaddr = NETXEN_BOOTLD_START; + + for (i = 0; i < size; i++) { + data = cpu_to_le64(ptr64[i]); + adapter->pci_mem_write(adapter, flashaddr, &data, 8); + flashaddr += 8; + } + + size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET]; + size = (__force u32)cpu_to_le32(size) / 8; + + ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START]; + flashaddr = NETXEN_IMAGE_START; + + for (i = 0; i < size; i++) { + data = cpu_to_le64(ptr64[i]); + + if (adapter->pci_mem_write(adapter, + flashaddr, &data, 8)) + return -EIO; + + flashaddr += 8; + } + } else { + u32 data; + + size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4; + flashaddr = NETXEN_BOOTLD_START; + + for (i = 0; i < size; i++) { + if (netxen_rom_fast_read(adapter, + flashaddr, (int *)&data) != 0) + return -EIO; + + if (adapter->pci_mem_write(adapter, + flashaddr, &data, 4)) + return -EIO; + + flashaddr += 4; + } } msleep(1); @@ -964,12 +1051,135 @@ int netxen_load_firmware(struct netxen_adapter *adapter) return 0; } +static int +netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname, + const struct firmware *fw) +{ + __le32 val; + u32 major, minor, build, ver, min_ver, bios; + struct pci_dev *pdev = adapter->pdev; + + if (fw->size < NX_FW_MIN_SIZE) + return -EINVAL; + + val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]); + if ((__force u32)val != NETXEN_BDINFO_MAGIC) + return -EINVAL; + + val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); + major = (__force u32)val & 0xff; + minor = ((__force u32)val >> 8) & 0xff; + build = (__force u32)val >> 16; + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + min_ver = NETXEN_VERSION_CODE(4, 0, 216); + else + min_ver = NETXEN_VERSION_CODE(3, 4, 216); + + ver = NETXEN_VERSION_CODE(major, minor, build); + + if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { + dev_err(&pdev->dev, + "%s: firmware version %d.%d.%d unsupported\n", + fwname, major, minor, build); + return -EINVAL; + } + + val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]); + netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios); + if ((__force u32)val != bios) { + dev_err(&pdev->dev, "%s: firmware bios is incompatible\n", + fwname); + return -EINVAL; + } + + /* check if flashed firmware is newer */ + if (netxen_rom_fast_read(adapter, + NX_FW_VERSION_OFFSET, (int *)&val)) + return -EIO; + major = (__force u32)val & 0xff; + minor = ((__force u32)val >> 8) & 0xff; + build = (__force u32)val >> 16; + if (NETXEN_VERSION_CODE(major, minor, build) > ver) + return -EINVAL; + + netxen_nic_reg_write(adapter, NETXEN_CAM_RAM(0x1fc), + NETXEN_BDINFO_MAGIC); + return 0; +} + +static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" }; + +int netxen_load_firmware(struct netxen_adapter *adapter) +{ + u32 capability, flashed_ver; + const struct firmware *fw; + int fw_type; + struct pci_dev *pdev = adapter->pdev; + int rc = 0; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + fw_type = NX_P2_MN_ROMIMAGE; + goto request_fw; + } else { + fw_type = NX_P3_CT_ROMIMAGE; + goto request_fw; + } + +request_mn: + capability = 0; + + netxen_rom_fast_read(adapter, + NX_FW_VERSION_OFFSET, (int *)&flashed_ver); + if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { + adapter->hw_read_wx(adapter, + NX_PEG_TUNE_CAPABILITY, &capability, 4); + if (capability & NX_PEG_TUNE_MN_PRESENT) { + fw_type = NX_P3_MN_ROMIMAGE; + goto request_fw; + } + } + +request_fw: + rc = request_firmware(&fw, fw_name[fw_type], &pdev->dev); + if (rc != 0) { + if (fw_type == NX_P3_CT_ROMIMAGE) { + msleep(1); + goto request_mn; + } + + fw = NULL; + goto load_fw; + } + + rc = netxen_validate_firmware(adapter, fw_name[fw_type], fw); + if (rc != 0) { + release_firmware(fw); + + if (fw_type == NX_P3_CT_ROMIMAGE) { + msleep(1); + goto request_mn; + } + + fw = NULL; + } + +load_fw: + rc = netxen_do_load_firmware(adapter, fw_name[fw_type], fw); + + if (fw) + release_firmware(fw); + return rc; +} + int netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, void *data, int len) { void __iomem *addr; + BUG_ON(len != 4); + if (ADDR_IN_WINDOW1(off)) { addr = NETXEN_CRB_NORMALIZE(adapter, off); } else { /* Window 0 */ @@ -977,37 +1187,13 @@ netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, netxen_nic_pci_change_crbwindow_128M(adapter, 0); } - DPRINTK(INFO, "writing to base %lx offset %llx addr %p" - " data %llx len %d\n", - pci_base(adapter, off), off, addr, - *(unsigned long long *)data, len); if (!addr) { netxen_nic_pci_change_crbwindow_128M(adapter, 1); return 1; } - switch (len) { - case 1: - writeb(*(u8 *) data, addr); - break; - case 2: - writew(*(u16 *) data, addr); - break; - case 4: - writel(*(u32 *) data, addr); - break; - case 8: - writeq(*(u64 *) data, addr); - break; - default: - DPRINTK(INFO, - "writing data %lx to offset %llx, num words=%d\n", - *(unsigned long *)data, off, (len >> 3)); + writel(*(u32 *) data, addr); - netxen_nic_hw_block_write64((u64 __iomem *) data, addr, - (len >> 3)); - break; - } if (!ADDR_IN_WINDOW1(off)) netxen_nic_pci_change_crbwindow_128M(adapter, 1); @@ -1020,6 +1206,8 @@ netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, { void __iomem *addr; + BUG_ON(len != 4); + if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ addr = NETXEN_CRB_NORMALIZE(adapter, off); } else { /* Window 0 */ @@ -1027,31 +1215,12 @@ netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, 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_128M(adapter, 1); return 1; } - switch (len) { - case 1: - *(u8 *) data = readb(addr); - break; - case 2: - *(u16 *) data = readw(addr); - break; - case 4: - *(u32 *) data = readl(addr); - break; - case 8: - *(u64 *) data = readq(addr); - break; - default: - netxen_nic_hw_block_read64((u64 __iomem *) data, addr, - (len >> 3)); - break; - } - DPRINTK(INFO, "read %lx\n", *(unsigned long *)data); + + *(u32 *)data = readl(addr); if (!ADDR_IN_WINDOW1(off)) netxen_nic_pci_change_crbwindow_128M(adapter, 1); @@ -1066,6 +1235,8 @@ netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, unsigned long flags = 0; int rv; + BUG_ON(len != 4); + rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len); if (rv == -1) { @@ -1079,34 +1250,12 @@ netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, write_lock_irqsave(&adapter->adapter_lock, flags); crb_win_lock(adapter); netxen_nic_pci_set_crbwindow_2M(adapter, &off); - } - - 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) { + writel(*(uint32_t *)data, (void __iomem *)off); crb_win_unlock(adapter); write_unlock_irqrestore(&adapter->adapter_lock, flags); - } + } else + writel(*(uint32_t *)data, (void __iomem *)off); + return 0; } @@ -1118,6 +1267,8 @@ netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, unsigned long flags = 0; int rv; + BUG_ON(len != 4); + rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off, len); if (rv == -1) { @@ -1131,33 +1282,11 @@ netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, 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) { + *(uint32_t *)data = readl((void __iomem *)off); crb_win_unlock(adapter); write_unlock_irqrestore(&adapter->adapter_lock, flags); - } + } else + *(uint32_t *)data = readl((void __iomem *)off); return 0; } @@ -1419,10 +1548,9 @@ static int netxen_nic_pci_mem_read_direct(struct netxen_adapter *adapter, u64 off, void *data, int size) { unsigned long flags; - void *addr; + void __iomem *addr, *mem_ptr = NULL; int ret = 0; u64 start; - uint8_t *mem_ptr = NULL; unsigned long mem_base; unsigned long mem_page; @@ -1442,7 +1570,7 @@ static int netxen_nic_pci_mem_read_direct(struct netxen_adapter *adapter, return -1; } - addr = (void *)(pci_base_offset(adapter, start)); + addr = pci_base_offset(adapter, start); if (!addr) { write_unlock_irqrestore(&adapter->adapter_lock, flags); mem_base = pci_resource_start(adapter->pdev, 0); @@ -1481,7 +1609,6 @@ static int netxen_nic_pci_mem_read_direct(struct netxen_adapter *adapter, break; } write_unlock_irqrestore(&adapter->adapter_lock, flags); - DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data); if (mem_ptr) iounmap(mem_ptr); @@ -1493,10 +1620,9 @@ netxen_nic_pci_mem_write_direct(struct netxen_adapter *adapter, u64 off, void *data, int size) { unsigned long flags; - void *addr; + void __iomem *addr, *mem_ptr = NULL; int ret = 0; u64 start; - uint8_t *mem_ptr = NULL; unsigned long mem_base; unsigned long mem_page; @@ -1516,7 +1642,7 @@ netxen_nic_pci_mem_write_direct(struct netxen_adapter *adapter, u64 off, return -1; } - addr = (void *)(pci_base_offset(adapter, start)); + addr = pci_base_offset(adapter, start); if (!addr) { write_unlock_irqrestore(&adapter->adapter_lock, flags); mem_base = pci_resource_start(adapter->pdev, 0); @@ -1553,8 +1679,6 @@ netxen_nic_pci_mem_write_direct(struct netxen_adapter *adapter, u64 off, 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; @@ -1566,10 +1690,11 @@ int netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, u64 off, void *data, int size) { - unsigned long flags, mem_crb; + unsigned long flags; int i, j, ret = 0, loop, sz[2], off0; uint32_t temp; uint64_t off8, tmpw, word[2] = {0, 0}; + void __iomem *mem_crb; /* * If not MN, go check for MS or invalid. @@ -1583,7 +1708,7 @@ netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, 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); + mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET); if ((size != 8) || (off0 != 0)) { for (i = 0; i < loop; i++) { @@ -1621,28 +1746,29 @@ netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, for (i = 0; i < loop; i++) { writel((uint32_t)(off8 + (i << 3)), - (void *)(mem_crb+MIU_TEST_AGT_ADDR_LO)); + (mem_crb+MIU_TEST_AGT_ADDR_LO)); writel(0, - (void *)(mem_crb+MIU_TEST_AGT_ADDR_HI)); + (mem_crb+MIU_TEST_AGT_ADDR_HI)); writel(word[i] & 0xffffffff, - (void *)(mem_crb+MIU_TEST_AGT_WRDATA_LO)); + (mem_crb+MIU_TEST_AGT_WRDATA_LO)); writel((word[i] >> 32) & 0xffffffff, - (void *)(mem_crb+MIU_TEST_AGT_WRDATA_HI)); + (mem_crb+MIU_TEST_AGT_WRDATA_HI)); writel(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE, - (void *)(mem_crb+MIU_TEST_AGT_CTRL)); + (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)); + (mem_crb+MIU_TEST_AGT_CTRL)); for (j = 0; j < MAX_CTL_CHECK; j++) { temp = readl( - (void *)(mem_crb+MIU_TEST_AGT_CTRL)); + (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); + if (printk_ratelimit()) + dev_err(&adapter->pdev->dev, + "failed to write through agent\n"); ret = -1; break; } @@ -1657,10 +1783,11 @@ int netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, u64 off, void *data, int size) { - unsigned long flags, mem_crb; + unsigned long flags; int i, j = 0, k, start, end, loop, sz[2], off0[2]; uint32_t temp; uint64_t off8, val, word[2] = {0, 0}; + void __iomem *mem_crb; /* @@ -1675,31 +1802,32 @@ netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, 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); + mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET); write_lock_irqsave(&adapter->adapter_lock, flags); netxen_nic_pci_change_crbwindow_128M(adapter, 0); for (i = 0; i < loop; i++) { writel((uint32_t)(off8 + (i << 3)), - (void *)(mem_crb+MIU_TEST_AGT_ADDR_LO)); + (mem_crb+MIU_TEST_AGT_ADDR_LO)); writel(0, - (void *)(mem_crb+MIU_TEST_AGT_ADDR_HI)); + (mem_crb+MIU_TEST_AGT_ADDR_HI)); writel(MIU_TA_CTL_ENABLE, - (void *)(mem_crb+MIU_TEST_AGT_CTRL)); + (mem_crb+MIU_TEST_AGT_CTRL)); writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE, - (void *)(mem_crb+MIU_TEST_AGT_CTRL)); + (mem_crb+MIU_TEST_AGT_CTRL)); for (j = 0; j < MAX_CTL_CHECK; j++) { temp = readl( - (void *)(mem_crb+MIU_TEST_AGT_CTRL)); + (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); + if (printk_ratelimit()) + dev_err(&adapter->pdev->dev, + "failed to read through agent\n"); break; } @@ -1707,7 +1835,7 @@ netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, end = (off0[i] + sz[i] - 1) >> 2; for (k = start; k <= end; k++) { word[i] |= ((uint64_t) readl( - (void *)(mem_crb + + (mem_crb + MIU_TEST_AGT_RDDATA(k))) << (32*k)); } } @@ -1739,7 +1867,6 @@ netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, *(uint64_t *)data = val; break; } - DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data); return 0; } @@ -1835,8 +1962,9 @@ netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, } if (j >= MAX_CTL_CHECK) { - printk(KERN_ERR "%s: Fail to write through agent\n", - netxen_nic_driver_name); + if (printk_ratelimit()) + dev_err(&adapter->pdev->dev, + "failed to write through agent\n"); ret = -1; break; } @@ -1905,8 +2033,9 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, } if (j >= MAX_CTL_CHECK) { - printk(KERN_ERR "%s: Fail to read through agent\n", - netxen_nic_driver_name); + if (printk_ratelimit()) + dev_err(&adapter->pdev->dev, + "failed to read through agent\n"); break; } @@ -1948,7 +2077,6 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, *(uint64_t *)data = val; break; } - DPRINTK(1, INFO, "read %llx\n", *(unsigned long long *)data); return 0; } @@ -1983,62 +2111,46 @@ u32 netxen_nic_pci_read_normalize_2M(struct netxen_adapter *adapter, u64 off) return temp; } -#if 0 -int -netxen_nic_erase_pxe(struct netxen_adapter *adapter) -{ - if (netxen_rom_fast_write(adapter, NETXEN_PXE_START, 0) == -1) { - printk(KERN_ERR "%s: erase pxe failed\n", - netxen_nic_driver_name); - return -1; - } - return 0; -} -#endif /* 0 */ - int netxen_nic_get_board_info(struct netxen_adapter *adapter) { - int rv = 0; - int addr = NETXEN_BRDCFG_START; - struct netxen_board_info *boardinfo; - int index; - u32 *ptr32; - - boardinfo = &adapter->ahw.boardcfg; - ptr32 = (u32 *) boardinfo; - - for (index = 0; index < sizeof(struct netxen_board_info) / sizeof(u32); - index++) { - if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) { - return -EIO; - } - ptr32++; - addr += sizeof(u32); - } - if (boardinfo->magic != NETXEN_BDINFO_MAGIC) { - printk("%s: ERROR reading %s board config." - " Read %x, expected %x\n", netxen_nic_driver_name, - netxen_nic_driver_name, - boardinfo->magic, NETXEN_BDINFO_MAGIC); - rv = -1; - } - if (boardinfo->header_version != NETXEN_BDINFO_VERSION) { - printk("%s: Unknown board config version." - " Read %x, expected %x\n", netxen_nic_driver_name, - boardinfo->header_version, NETXEN_BDINFO_VERSION); - rv = -1; + int offset, board_type, magic, header_version; + struct pci_dev *pdev = adapter->pdev; + + offset = NETXEN_BRDCFG_START + + offsetof(struct netxen_board_info, magic); + if (netxen_rom_fast_read(adapter, offset, &magic)) + return -EIO; + + offset = NETXEN_BRDCFG_START + + offsetof(struct netxen_board_info, header_version); + if (netxen_rom_fast_read(adapter, offset, &header_version)) + return -EIO; + + if (magic != NETXEN_BDINFO_MAGIC || + header_version != NETXEN_BDINFO_VERSION) { + dev_err(&pdev->dev, + "invalid board config, magic=%08x, version=%08x\n", + magic, header_version); + return -EIO; } - if (boardinfo->board_type == NETXEN_BRDTYPE_P3_4_GB_MM) { + offset = NETXEN_BRDCFG_START + + offsetof(struct netxen_board_info, board_type); + if (netxen_rom_fast_read(adapter, offset, &board_type)) + return -EIO; + + adapter->ahw.board_type = board_type; + + if (board_type == NETXEN_BRDTYPE_P3_4_GB_MM) { u32 gpio = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_PAD_GPIO_I); if ((gpio & 0x8000) == 0) - boardinfo->board_type = NETXEN_BRDTYPE_P3_10G_TP; + board_type = NETXEN_BRDTYPE_P3_10G_TP; } - switch ((netxen_brdtype_t) boardinfo->board_type) { + switch ((netxen_brdtype_t)board_type) { case NETXEN_BRDTYPE_P2_SB35_4G: - adapter->ahw.board_type = NETXEN_NIC_GBE; + adapter->ahw.port_type = NETXEN_NIC_GBE; break; case NETXEN_BRDTYPE_P2_SB31_10G: case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ: @@ -2054,7 +2166,7 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) case NETXEN_BRDTYPE_P3_10G_SFP_QT: case NETXEN_BRDTYPE_P3_10G_XFP: case NETXEN_BRDTYPE_P3_10000_BASE_T: - adapter->ahw.board_type = NETXEN_NIC_XGBE; + adapter->ahw.port_type = NETXEN_NIC_XGBE; break; case NETXEN_BRDTYPE_P1_BD: case NETXEN_BRDTYPE_P1_SB: @@ -2063,20 +2175,19 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter) 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; + adapter->ahw.port_type = NETXEN_NIC_GBE; break; case NETXEN_BRDTYPE_P3_10G_TP: - adapter->ahw.board_type = (adapter->portnum < 2) ? + adapter->ahw.port_type = (adapter->portnum < 2) ? NETXEN_NIC_XGBE : NETXEN_NIC_GBE; break; default: - printk("%s: Unknown(%x)\n", netxen_nic_driver_name, - boardinfo->board_type); - rv = -ENODEV; + dev_err(&pdev->dev, "unknown board type %x\n", board_type); + adapter->ahw.port_type = NETXEN_NIC_XGBE; break; } - return rv; + return 0; } /* NIU access sections */ @@ -2122,7 +2233,7 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) return; } - if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + if (adapter->ahw.port_type == NETXEN_NIC_GBE) { adapter->hw_read_wx(adapter, NETXEN_PORT_MODE_ADDR, &port_mode, 4); if (port_mode == NETXEN_PORT_MODE_802_3_AP) { @@ -2177,32 +2288,27 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) } } -void netxen_nic_flash_print(struct netxen_adapter *adapter) +void netxen_nic_get_firmware_info(struct netxen_adapter *adapter) { - u32 fw_major = 0; - u32 fw_minor = 0; - u32 fw_build = 0; + u32 fw_major, fw_minor, fw_build; char brd_name[NETXEN_MAX_SHORT_NAME]; char serial_num[32]; - int i, addr; - __le32 *ptr32; - - struct netxen_board_info *board_info = &(adapter->ahw.boardcfg); + int i, addr, val; + int *ptr32; + struct pci_dev *pdev = adapter->pdev; adapter->driver_mismatch = 0; - ptr32 = (u32 *)&serial_num; + ptr32 = (int *)&serial_num; addr = NETXEN_USER_START + offsetof(struct netxen_new_user_info, serial_num); for (i = 0; i < 8; i++) { - if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) { - printk("%s: ERROR reading %s board userarea.\n", - netxen_nic_driver_name, - netxen_nic_driver_name); + if (netxen_rom_fast_read(adapter, addr, &val) == -1) { + dev_err(&pdev->dev, "error reading board info\n"); adapter->driver_mismatch = 1; return; } - ptr32++; + ptr32[i] = cpu_to_le32(val); addr += sizeof(u32); } @@ -2211,23 +2317,48 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter) adapter->hw_read_wx(adapter, NETXEN_FW_VERSION_SUB, &fw_build, 4); adapter->fw_major = fw_major; + adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build); if (adapter->portnum == 0) { - get_brd_name_by_type(board_info->board_type, brd_name); + get_brd_name_by_type(adapter->ahw.board_type, brd_name); printk(KERN_INFO "NetXen %s Board S/N %s Chip rev 0x%x\n", brd_name, serial_num, adapter->ahw.revision_id); - printk(KERN_INFO "NetXen Firmware version %d.%d.%d\n", - fw_major, fw_minor, fw_build); } - if (NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build) < - NETXEN_VERSION_CODE(3, 4, 216)) { + if (adapter->fw_version < NETXEN_VERSION_CODE(3, 4, 216)) { adapter->driver_mismatch = 1; - printk(KERN_ERR "%s: firmware version %d.%d.%d unsupported\n", - netxen_nic_driver_name, + dev_warn(&pdev->dev, "firmware version %d.%d.%d unsupported\n", fw_major, fw_minor, fw_build); return; } + + dev_info(&pdev->dev, "firmware version %d.%d.%d\n", + fw_major, fw_minor, fw_build); + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + adapter->hw_read_wx(adapter, + NETXEN_MIU_MN_CONTROL, &i, 4); + adapter->ahw.cut_through = (i & 0x4) ? 1 : 0; + dev_info(&pdev->dev, "firmware running in %s mode\n", + adapter->ahw.cut_through ? "cut-through" : "legacy"); + } } +int +netxen_nic_wol_supported(struct netxen_adapter *adapter) +{ + u32 wol_cfg; + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return 0; + + wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG_NV); + if (wol_cfg & (1UL << adapter->portnum)) { + wol_cfg = netxen_nic_reg_read(adapter, NETXEN_WOL_CONFIG); + if (wol_cfg & (1 << adapter->portnum)) + return 1; + } + + return 0; +} diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h index aae737dc77a8..04b47a7993cd 100644 --- a/drivers/net/netxen/netxen_nic_hw.h +++ b/drivers/net/netxen/netxen_nic_hw.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 - 2006 NetXen, Inc. + * Copyright (C) 2003 - 2009 NetXen, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -22,12 +22,9 @@ * * Contact Information: * info@netxen.com - * NetXen, - * 3965 Freedom Circle, Fourth floor, - * Santa Clara, CA 95054 - * - * - * Structures, enums, and macros for the MAC + * NetXen Inc, + * 18922 Forge Drive + * Cupertino, CA 95014-0701 * */ @@ -54,37 +51,12 @@ static inline void writeq(u64 val, void __iomem * addr) } #endif -static inline void netxen_nic_hw_block_write64(u64 __iomem * data_ptr, - u64 __iomem * addr, - int num_words) -{ - int num; - for (num = 0; num < num_words; num++) { - writeq(readq((void __iomem *)data_ptr), addr); - addr++; - data_ptr++; - } -} - -static inline void netxen_nic_hw_block_read64(u64 __iomem * data_ptr, - u64 __iomem * addr, int num_words) -{ - int num; - for (num = 0; num < num_words; num++) { - writeq(readq((void __iomem *)addr), data_ptr); - addr++; - data_ptr++; - } - -} - struct netxen_adapter; #define NETXEN_PCI_MAPSIZE_BYTES (NETXEN_PCI_MAPSIZE << 20) struct netxen_port; void netxen_nic_set_link_parameters(struct netxen_adapter *adapter); -void netxen_nic_flash_print(struct netxen_adapter *adapter); typedef u8 netxen_ethernet_macaddr_t[6]; @@ -148,33 +120,6 @@ typedef enum { #define netxen_gb_get_soft_reset(config_word) \ _netxen_crb_get_bit((config_word), 31) -/* - * NIU GB MAC Config Register 1 (applies to GB0, GB1, GB2, GB3) - * - * Bit 0 : duplex => 1:full duplex mode, 0:half duplex - * Bit 1 : crc_enable => 1:append CRC to xmit frames, 0:dont append - * Bit 2 : padshort => 1:pad short frames and add CRC, 0:dont pad - * Bit 4 : checklength => 1:check framelen with actual,0:dont check - * Bit 5 : hugeframes => 1:allow oversize xmit frames, 0:dont allow - * Bits 8-9 : intfmode => 01:nibble (10/100), 10:byte (1000) - * Bits 12-15 : preamblelen => preamble field length in bytes, default 7 - */ - -#define netxen_gb_set_duplex(config_word) \ - ((config_word) |= 1 << 0) -#define netxen_gb_set_crc_enable(config_word) \ - ((config_word) |= 1 << 1) -#define netxen_gb_set_padshort(config_word) \ - ((config_word) |= 1 << 2) -#define netxen_gb_set_checklength(config_word) \ - ((config_word) |= 1 << 4) -#define netxen_gb_set_hugeframes(config_word) \ - ((config_word) |= 1 << 5) -#define netxen_gb_set_preamblelen(config_word, val) \ - ((config_word) |= ((val) << 12) & 0xF000) -#define netxen_gb_set_intfmode(config_word, val) \ - ((config_word) |= ((val) << 8) & 0x300) - #define netxen_gb_get_stationaddress_low(config_word) ((config_word) >> 16) #define netxen_gb_set_mii_mgmt_clockselect(config_word, val) \ diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index ffd37bea1628..0759c35f16ac 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 - 2006 NetXen, Inc. + * Copyright (C) 2003 - 2009 NetXen, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -22,12 +22,9 @@ * * Contact Information: * info@netxen.com - * NetXen, - * 3965 Freedom Circle, Fourth floor, - * Santa Clara, CA 95054 - * - * - * Source file for NIC routines to initialize the Phantom Hardware + * NetXen Inc, + * 18922 Forge Drive + * Cupertino, CA 95014-0701 * */ @@ -52,17 +49,9 @@ static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM]; #define NETXEN_NIC_XDMA_RESET 0x8000ff -static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, - uint32_t ctx, uint32_t ringid); - -#if 0 -static void netxen_nic_locked_write_reg(struct netxen_adapter *adapter, - unsigned long off, int *data) -{ - void __iomem *addr = pci_base_offset(adapter, off); - writel(*data, addr); -} -#endif /* 0 */ +static void +netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, + struct nx_host_rds_ring *rds_ring); static void crb_addr_transform_setup(void) { @@ -160,23 +149,21 @@ 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); - } + int i, ring; + + recv_ctx = &adapter->recv_ctx; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; + for (i = 0; i < rds_ring->num_desc; ++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); } } } @@ -188,7 +175,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) int i, j; cmd_buf = adapter->cmd_buf_arr; - for (i = 0; i < adapter->max_tx_desc_count; i++) { + for (i = 0; i < adapter->num_txd; i++) { buffrag = cmd_buf->frag_array; if (buffrag->dma) { pci_unmap_single(adapter->pdev, buffrag->dma, @@ -204,7 +191,6 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) 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; @@ -217,18 +203,17 @@ 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; - } + int ring; + + recv_ctx = &adapter->recv_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; } } + if (adapter->cmd_buf_arr) vfree(adapter->cmd_buf_arr); return; @@ -238,90 +223,97 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) { struct netxen_recv_context *recv_ctx; struct nx_host_rds_ring *rds_ring; + struct nx_host_sds_ring *sds_ring; struct netxen_rx_buffer *rx_buf; - int ctx, ring, i, num_rx_bufs; + int ring, i, num_rx_bufs; struct netxen_cmd_buffer *cmd_buf_arr; struct net_device *netdev = adapter->netdev; - cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE); + cmd_buf_arr = + (struct netxen_cmd_buffer *)vmalloc(TX_BUFF_RINGSIZE(adapter)); 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); + memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(adapter)); 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; + recv_ctx = &adapter->recv_ctx; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &recv_ctx->rds_rings[ring]; + switch (ring) { + case RCV_RING_NORMAL: + rds_ring->num_desc = adapter->num_rxd; + if (adapter->ahw.cut_through) { + rds_ring->dma_size = + NX_CT_DEFAULT_RX_BUF_LEN; rds_ring->skb_size = - rds_ring->dma_size + NET_IP_ALIGN; - break; + 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_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; + case RCV_RING_JUMBO: + rds_ring->num_desc = adapter->num_jumbo_rxd; + 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; - } - 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); - /* - * 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; - rx_buf++; - } + case RCV_RING_LRO: + rds_ring->num_desc = adapter->num_lro_rxd; + rds_ring->dma_size = RX_LRO_DMA_MAP_LEN; + rds_ring->skb_size = MAX_RX_LRO_BUFFER_LENGTH; + break; + + } + rds_ring->rx_buf_arr = (struct netxen_rx_buffer *) + vmalloc(RCV_BUFF_RINGSIZE(rds_ring)); + 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_BUFF_RINGSIZE(rds_ring)); + INIT_LIST_HEAD(&rds_ring->free_list); + /* + * Now go through all of them, set reference handles + * and put them in the queues. + */ + num_rx_bufs = rds_ring->num_desc; + 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; + rx_buf++; } + spin_lock_init(&rds_ring->lock); + } + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + sds_ring->irq = adapter->msix_entries[ring].vector; + sds_ring->clean_tx = (ring == 0); + sds_ring->post_rxd = (ring == 0); + sds_ring->adapter = adapter; + sds_ring->num_desc = adapter->num_rxd; + + for (i = 0; i < NUM_RCV_DESC_RINGS; i++) + INIT_LIST_HEAD(&sds_ring->free_list[i]); } return 0; @@ -333,7 +325,7 @@ err_out: void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) { - switch (adapter->ahw.board_type) { + switch (adapter->ahw.port_type) { case NETXEN_NIC_GBE: adapter->enable_phy_interrupts = netxen_niu_gbe_enable_phy_interrupts; @@ -399,9 +391,6 @@ 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) { @@ -452,38 +441,6 @@ 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 */ - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, - M25P_INSTR_WREN); - if (netxen_wait_rom_done(adapter)) { - return -1; - } - return 0; -} - -static unsigned int netxen_rdcrbreg(struct netxen_adapter *adapter, - unsigned int addr) -{ - unsigned int data = 0xdeaddead; - data = netxen_nic_reg_read(adapter, addr); - return data; -} - -static int netxen_do_rom_rdsr(struct netxen_adapter *adapter) -{ - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, - M25P_INSTR_RDSR); - if (netxen_wait_rom_done(adapter)) { - return -1; - } - return netxen_rdcrbreg(adapter, NETXEN_ROMUSB_ROM_RDATA); -} -#endif - static void netxen_rom_unlock(struct netxen_adapter *adapter) { u32 val; @@ -493,44 +450,6 @@ static void netxen_rom_unlock(struct netxen_adapter *adapter) } -#if 0 -static int netxen_rom_wip_poll(struct netxen_adapter *adapter) -{ - long timeout = 0; - long wip = 1; - int val; - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); - while (wip != 0) { - val = netxen_do_rom_rdsr(adapter); - wip = val & 1; - timeout++; - if (timeout > rom_max_timeout) { - return -1; - } - } - return 0; -} - -static int do_rom_fast_write(struct netxen_adapter *adapter, int addr, - int data) -{ - if (netxen_rom_wren(adapter)) { - return -1; - } - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_WDATA, data); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, - M25P_INSTR_PP); - if (netxen_wait_rom_done(adapter)) { - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); - return -1; - } - - return netxen_rom_wip_poll(adapter); -} -#endif - static int do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { @@ -597,284 +516,6 @@ int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) return ret; } -#if 0 -int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data) -{ - int ret = 0; - - if (rom_lock(adapter) != 0) { - return -1; - } - ret = do_rom_fast_write(adapter, addr, data); - netxen_rom_unlock(adapter); - return ret; -} - -static int do_rom_fast_write_words(struct netxen_adapter *adapter, - int addr, u8 *bytes, size_t size) -{ - int addridx = addr; - int ret = 0; - - while (addridx < (addr + size)) { - int last_attempt = 0; - int timeout = 0; - int data; - - data = le32_to_cpu((*(__le32*)bytes)); - ret = do_rom_fast_write(adapter, addridx, data); - if (ret < 0) - return ret; - - while(1) { - int data1; - - ret = do_rom_fast_read(adapter, addridx, &data1); - if (ret < 0) - return ret; - - if (data1 == data) - break; - - if (timeout++ >= rom_write_timeout) { - if (last_attempt++ < 4) { - ret = do_rom_fast_write(adapter, - addridx, data); - if (ret < 0) - return ret; - } - else { - printk(KERN_INFO "Data write did not " - "succeed at address 0x%x\n", addridx); - break; - } - } - } - - bytes += 4; - addridx += 4; - } - - return ret; -} - -int netxen_rom_fast_write_words(struct netxen_adapter *adapter, int addr, - u8 *bytes, size_t size) -{ - int ret = 0; - - ret = rom_lock(adapter); - if (ret < 0) - return ret; - - ret = do_rom_fast_write_words(adapter, addr, bytes, size); - netxen_rom_unlock(adapter); - - return ret; -} - -static int netxen_rom_wrsr(struct netxen_adapter *adapter, int data) -{ - int ret; - - ret = netxen_rom_wren(adapter); - if (ret < 0) - return ret; - - netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_ROM_WDATA, data); - netxen_crb_writelit_adapter(adapter, - NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0x1); - - ret = netxen_wait_rom_done(adapter); - if (ret < 0) - return ret; - - return netxen_rom_wip_poll(adapter); -} - -static int netxen_rom_rdsr(struct netxen_adapter *adapter) -{ - int ret; - - ret = rom_lock(adapter); - if (ret < 0) - return ret; - - ret = netxen_do_rom_rdsr(adapter); - netxen_rom_unlock(adapter); - return ret; -} - -int netxen_backup_crbinit(struct netxen_adapter *adapter) -{ - int ret = FLASH_SUCCESS; - int val; - char *buffer = kmalloc(NETXEN_FLASH_SECTOR_SIZE, GFP_KERNEL); - - if (!buffer) - return -ENOMEM; - /* unlock sector 63 */ - val = netxen_rom_rdsr(adapter); - val = val & 0xe3; - ret = netxen_rom_wrsr(adapter, val); - if (ret != FLASH_SUCCESS) - goto out_kfree; - - ret = netxen_rom_wip_poll(adapter); - if (ret != FLASH_SUCCESS) - goto out_kfree; - - /* copy sector 0 to sector 63 */ - ret = netxen_rom_fast_read_words(adapter, NETXEN_CRBINIT_START, - buffer, NETXEN_FLASH_SECTOR_SIZE); - if (ret != FLASH_SUCCESS) - goto out_kfree; - - ret = netxen_rom_fast_write_words(adapter, NETXEN_FIXED_START, - buffer, NETXEN_FLASH_SECTOR_SIZE); - if (ret != FLASH_SUCCESS) - goto out_kfree; - - /* lock sector 63 */ - val = netxen_rom_rdsr(adapter); - if (!(val & 0x8)) { - val |= (0x1 << 2); - /* lock sector 63 */ - if (netxen_rom_wrsr(adapter, val) == 0) { - ret = netxen_rom_wip_poll(adapter); - if (ret != FLASH_SUCCESS) - goto out_kfree; - - /* lock SR writes */ - ret = netxen_rom_wip_poll(adapter); - if (ret != FLASH_SUCCESS) - goto out_kfree; - } - } - -out_kfree: - kfree(buffer); - return ret; -} - -static int netxen_do_rom_se(struct netxen_adapter *adapter, int addr) -{ - netxen_rom_wren(adapter); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, - M25P_INSTR_SE); - if (netxen_wait_rom_done(adapter)) { - netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); - return -1; - } - return netxen_rom_wip_poll(adapter); -} - -static void check_erased_flash(struct netxen_adapter *adapter, int addr) -{ - int i; - int val; - int count = 0, erased_errors = 0; - int range; - - range = (addr == NETXEN_USER_START) ? - NETXEN_FIXED_START : addr + NETXEN_FLASH_SECTOR_SIZE; - - for (i = addr; i < range; i += 4) { - netxen_rom_fast_read(adapter, i, &val); - if (val != 0xffffffff) - erased_errors++; - count++; - } - - if (erased_errors) - printk(KERN_INFO "0x%x out of 0x%x words fail to be erased " - "for sector address: %x\n", erased_errors, count, addr); -} - -int netxen_rom_se(struct netxen_adapter *adapter, int addr) -{ - int ret = 0; - if (rom_lock(adapter) != 0) { - return -1; - } - ret = netxen_do_rom_se(adapter, addr); - netxen_rom_unlock(adapter); - msleep(30); - check_erased_flash(adapter, addr); - - return ret; -} - -static int netxen_flash_erase_sections(struct netxen_adapter *adapter, - int start, int end) -{ - int ret = FLASH_SUCCESS; - int i; - - for (i = start; i < end; i++) { - ret = netxen_rom_se(adapter, i * NETXEN_FLASH_SECTOR_SIZE); - if (ret) - break; - ret = netxen_rom_wip_poll(adapter); - if (ret < 0) - return ret; - } - - return ret; -} - -int -netxen_flash_erase_secondary(struct netxen_adapter *adapter) -{ - int ret = FLASH_SUCCESS; - int start, end; - - start = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE; - end = NETXEN_USER_START / NETXEN_FLASH_SECTOR_SIZE; - ret = netxen_flash_erase_sections(adapter, start, end); - - return ret; -} - -int -netxen_flash_erase_primary(struct netxen_adapter *adapter) -{ - int ret = FLASH_SUCCESS; - int start, end; - - start = NETXEN_PRIMARY_START / NETXEN_FLASH_SECTOR_SIZE; - end = NETXEN_SECONDARY_START / NETXEN_FLASH_SECTOR_SIZE; - ret = netxen_flash_erase_sections(adapter, start, end); - - return ret; -} - -void netxen_halt_pegs(struct netxen_adapter *adapter) -{ - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x3c, 1); - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x3c, 1); - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x3c, 1); - netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x3c, 1); -} - -int netxen_flash_unlock(struct netxen_adapter *adapter) -{ - int ret = 0; - - ret = netxen_rom_wrsr(adapter, 0); - if (ret < 0) - return ret; - - ret = netxen_rom_wren(adapter); - if (ret < 0) - return ret; - - return ret; -} -#endif /* 0 */ - #define NETXEN_BOARDTYPE 0x4008 #define NETXEN_BOARDNUM 0x400c #define NETXEN_CHIPNUM 0x4010 @@ -1168,6 +809,40 @@ int netxen_receive_peg_ready(struct netxen_adapter *adapter) return 0; } +static int +netxen_alloc_rx_skb(struct netxen_adapter *adapter, + struct nx_host_rds_ring *rds_ring, + struct netxen_rx_buffer *buffer) +{ + struct sk_buff *skb; + dma_addr_t dma; + struct pci_dev *pdev = adapter->pdev; + + buffer->skb = dev_alloc_skb(rds_ring->skb_size); + if (!buffer->skb) + return 1; + + skb = buffer->skb; + + if (!adapter->ahw.cut_through) + skb_reserve(skb, 2); + + dma = pci_map_single(pdev, skb->data, + rds_ring->dma_size, PCI_DMA_FROMDEVICE); + + if (pci_dma_mapping_error(pdev, dma)) { + dev_kfree_skb_any(skb); + buffer->skb = NULL; + return 1; + } + + buffer->skb = skb; + buffer->dma = dma; + buffer->state = NETXEN_BUFFER_BUSY; + + return 0; +} + static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter, struct nx_host_rds_ring *rds_ring, u16 index, u16 cksum) { @@ -1192,164 +867,121 @@ static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter, 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; } -/* - * netxen_process_rcv() send the received packet to the protocol stack. - * and if the number of receives exceeds RX_BUFFERS_REFILL, then we - * 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 *frag_desc) +static struct netxen_rx_buffer * +netxen_process_rcv(struct netxen_adapter *adapter, + int ring, int index, int length, int cksum, int pkt_offset) { struct net_device *netdev = adapter->netdev; - u64 sts_data = le64_to_cpu(desc->status_desc_data); - int index = netxen_get_sts_refhandle(sts_data); - struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]); + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; struct netxen_rx_buffer *buffer; struct sk_buff *skb; - u32 length = netxen_get_sts_totallength(sts_data); - u32 desc_ctx; - u16 pkt_offset = 0, cksum; - struct nx_host_rds_ring *rds_ring; + struct nx_host_rds_ring *rds_ring = &recv_ctx->rds_rings[ring]; - desc_ctx = netxen_get_sts_type(sts_data); - if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) { - printk("%s: %s Bad Rcv descriptor ring\n", - netxen_nic_driver_name, netdev->name); - return; - } + if (unlikely(index > rds_ring->num_desc)) + return NULL; - 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, rds_ring->max_rx_desc_count); - return; - } 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)) { - buffer->lro_expected_frags = - netxen_get_sts_desc_lro_cnt(desc); - buffer->lro_length = length; - } - if (buffer->lro_current_frags != buffer->lro_expected_frags) { - if (buffer->lro_expected_frags != 0) { - printk("LRO: (refhandle:%x) recv frag. " - "wait for last. flags: %x expected:%d " - "have:%d\n", index, - netxen_get_sts_desc_lro_last_frag(desc), - buffer->lro_expected_frags, - buffer->lro_current_frags); - } - return; - } - } - - cksum = netxen_get_sts_status(sts_data); skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum); if (!skb) - return; + return buffer; - if (desc_ctx == RCV_DESC_LRO_CTXID) { - /* True length was only available on the last pkt */ - skb_put(skb, buffer->lro_length); - } else { - if (length > rds_ring->skb_size) - skb_put(skb, rds_ring->skb_size); - 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); - } + + if (pkt_offset) + skb_pull(skb, pkt_offset); skb->protocol = eth_type_trans(skb, netdev); - /* - * rx buffer chaining is disabled, walk and free - * any spurious rx buffer chain. - */ - if (frag_desc) { - u16 i, nr_frags = desc->nr_frags; + netif_receive_skb(skb); - dev_kfree_skb_any(skb); - for (i = 0; i < nr_frags; i++) { - index = le16_to_cpu(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 { - netif_receive_skb(skb); + adapter->stats.no_rcv++; + adapter->stats.rxbytes += length; - adapter->stats.no_rcv++; - adapter->stats.rxbytes += length; - } + return buffer; } -/* Process Receive status ring */ -u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) +#define netxen_merge_rx_buffers(list, head) \ + do { list_splice_tail_init(list, head); } while (0); + +int +netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, 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, *frag_desc; - u32 consumer = recv_ctx->status_rx_consumer; - int count = 0, ring; + struct netxen_adapter *adapter = sds_ring->adapter; + + struct list_head *cur; + + struct status_desc *desc; + struct netxen_rx_buffer *rxbuf; + + u32 consumer = sds_ring->consumer; + + int count = 0; u64 sts_data; - u16 opcode; + int opcode, ring, index, length, cksum, pkt_offset; while (count < max) { - desc = &desc_head[consumer]; - if (!(netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)) { - DPRINTK(ERR, "desc %p ownedby %x\n", desc, - netxen_get_sts_owner(desc)); + desc = &sds_ring->desc_head[consumer]; + sts_data = le64_to_cpu(desc->status_desc_data); + + if (!(sts_data & STATUS_OWNER_HOST)) break; - } - sts_data = le64_to_cpu(desc->status_desc_data); + ring = netxen_get_sts_type(sts_data); + if (ring > RCV_RING_JUMBO) + continue; + 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); + index = netxen_get_sts_refhandle(sts_data); + length = netxen_get_sts_totallength(sts_data); + cksum = netxen_get_sts_status(sts_data); + pkt_offset = netxen_get_sts_pkt_offset(sts_data); + + rxbuf = netxen_process_rcv(adapter, ring, index, + length, cksum, pkt_offset); + + if (rxbuf) + list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); - netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM); + desc->status_desc_data = cpu_to_le64(STATUS_OWNER_PHANTOM); - consumer = get_next_index(consumer, - adapter->max_rx_desc_count); + consumer = get_next_index(consumer, sds_ring->num_desc); count++; } - 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; + for (ring = 0; ring < adapter->max_rds_rings; ring++) { + struct nx_host_rds_ring *rds_ring = + &adapter->recv_ctx.rds_rings[ring]; - /* Window = 1 */ + if (!list_empty(&sds_ring->free_list[ring])) { + list_for_each(cur, &sds_ring->free_list[ring]) { + rxbuf = list_entry(cur, + struct netxen_rx_buffer, list); + netxen_alloc_rx_skb(adapter, rds_ring, rxbuf); + } + spin_lock(&rds_ring->lock); + netxen_merge_rx_buffers(&sds_ring->free_list[ring], + &rds_ring->free_list); + spin_unlock(&rds_ring->lock); + } + + netxen_post_rx_buffers_nodb(adapter, rds_ring); + } + + if (count) { + sds_ring->consumer = consumer; adapter->pci_write_normalize(adapter, - recv_ctx->crb_sts_consumer, consumer); + sds_ring->crb_sts_consumer, consumer); } return count; @@ -1366,7 +998,11 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) struct netxen_skb_frag *frag; int done = 0; + if (!spin_trylock(&adapter->tx_clean_lock)) + return 1; + last_consumer = adapter->last_cmd_consumer; + barrier(); /* cmd_consumer can change underneath */ consumer = le32_to_cpu(*(adapter->cmd_consumer)); while (last_consumer != consumer) { @@ -1389,7 +1025,7 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) } last_consumer = get_next_index(last_consumer, - adapter->max_tx_desc_count); + adapter->num_txd); if (++count >= MAX_STATUS_HANDLE) break; } @@ -1417,75 +1053,55 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) * There is still a possible race condition and the host could miss an * interrupt. The card has to take care of this. */ + barrier(); /* cmd_consumer can change underneath */ consumer = le32_to_cpu(*(adapter->cmd_consumer)); done = (last_consumer == consumer); + spin_unlock(&adapter->tx_clean_lock); return (done); } -/* - * netxen_post_rx_buffers puts buffer in the Phantom memory - */ -void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) +void +netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, + struct nx_host_rds_ring *rds_ring) { - struct pci_dev *pdev = adapter->pdev; - struct sk_buff *skb; - struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]); - struct nx_host_rds_ring *rds_ring = NULL; - uint producer; struct rcv_desc *pdesc; struct netxen_rx_buffer *buffer; - int count = 0; + int producer, count = 0; netxen_ctx_msg msg = 0; - dma_addr_t dma; struct list_head *head; - rds_ring = &recv_ctx->rds_rings[ringid]; - producer = rds_ring->producer; - head = &rds_ring->free_list; - /* We can start writing rx descriptors into the phantom memory. */ + spin_lock(&rds_ring->lock); + head = &rds_ring->free_list; while (!list_empty(head)) { - skb = dev_alloc_skb(rds_ring->skb_size); - if (unlikely(!skb)) { - break; - } - - if (!adapter->ahw.cut_through) - skb_reserve(skb, 2); + buffer = list_entry(head->next, struct netxen_rx_buffer, list); - dma = pci_map_single(pdev, skb->data, - rds_ring->dma_size, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(pdev, dma)) { - dev_kfree_skb_any(skb); - break; + if (!buffer->skb) { + if (netxen_alloc_rx_skb(adapter, rds_ring, buffer)) + break; } count++; - buffer = list_entry(head->next, struct netxen_rx_buffer, list); list_del(&buffer->list); - buffer->skb = skb; - buffer->state = NETXEN_BUFFER_BUSY; - buffer->dma = dma; - /* make a rcv descriptor */ pdesc = &rds_ring->desc_head[producer]; - pdesc->addr_buffer = cpu_to_le64(dma); + pdesc->addr_buffer = cpu_to_le64(buffer->dma); pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); - producer = get_next_index(producer, rds_ring->max_rx_desc_count); + producer = get_next_index(producer, rds_ring->num_desc); } - /* if we did allocate buffers, then write the count to Phantom */ + spin_unlock(&rds_ring->lock); + if (count) { rds_ring->producer = producer; - /* Window = 1 */ adapter->pci_write_normalize(adapter, rds_ring->crb_rcv_producer, - (producer-1) & (rds_ring->max_rx_desc_count-1)); + (producer-1) & (rds_ring->num_desc-1)); if (adapter->fw_major < 4) { /* @@ -1496,9 +1112,8 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID); netxen_set_msg_privid(msg); netxen_set_msg_count(msg, - ((producer - - 1) & (rds_ring-> - max_rx_desc_count - 1))); + ((producer - 1) & + (rds_ring->num_desc - 1))); netxen_set_msg_ctxid(msg, adapter->portnum); netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid)); writel(msg, @@ -1508,68 +1123,49 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) } } -static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, - uint32_t ctx, uint32_t ringid) +static void +netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, + struct nx_host_rds_ring *rds_ring) { - struct pci_dev *pdev = adapter->pdev; - struct sk_buff *skb; - struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]); - struct nx_host_rds_ring *rds_ring = NULL; - u32 producer; struct rcv_desc *pdesc; struct netxen_rx_buffer *buffer; - int count = 0; + int producer, count = 0; struct list_head *head; - dma_addr_t dma; - - rds_ring = &recv_ctx->rds_rings[ringid]; producer = rds_ring->producer; + if (!spin_trylock(&rds_ring->lock)) + return; + head = &rds_ring->free_list; - /* We can start writing rx descriptors into the phantom memory. */ while (!list_empty(head)) { - skb = dev_alloc_skb(rds_ring->skb_size); - if (unlikely(!skb)) { - break; - } - - if (!adapter->ahw.cut_through) - skb_reserve(skb, 2); + buffer = list_entry(head->next, struct netxen_rx_buffer, list); - dma = pci_map_single(pdev, skb->data, - rds_ring->dma_size, PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(pdev, dma)) { - dev_kfree_skb_any(skb); - break; + if (!buffer->skb) { + if (netxen_alloc_rx_skb(adapter, rds_ring, buffer)) + break; } count++; - buffer = list_entry(head->next, struct netxen_rx_buffer, list); list_del(&buffer->list); - buffer->skb = skb; - buffer->state = NETXEN_BUFFER_BUSY; - buffer->dma = dma; - /* make a rcv descriptor */ pdesc = &rds_ring->desc_head[producer]; pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); pdesc->addr_buffer = cpu_to_le64(buffer->dma); - producer = get_next_index(producer, rds_ring->max_rx_desc_count); + producer = get_next_index(producer, rds_ring->num_desc); } - /* if we did allocate buffers, then write the count to Phantom */ if (count) { rds_ring->producer = producer; - /* Window = 1 */ adapter->pci_write_normalize(adapter, rds_ring->crb_rcv_producer, - (producer-1) & (rds_ring->max_rx_desc_count-1)); + (producer - 1) & (rds_ring->num_desc - 1)); wmb(); } + spin_unlock(&rds_ring->lock); } void netxen_nic_clear_stats(struct netxen_adapter *adapter) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index c172b6e24a96..1af47257ba82 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 - 2006 NetXen, Inc. + * Copyright (C) 2003 - 2009 NetXen, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -22,12 +22,9 @@ * * Contact Information: * info@netxen.com - * NetXen, - * 3965 Freedom Circle, Fourth floor, - * Santa Clara, CA 95054 - * - * - * Main source file for NetXen NIC Driver on Linux + * NetXen Inc, + * 18922 Forge Drive + * Cupertino, CA 95014-0701 * */ @@ -97,20 +94,6 @@ static struct pci_device_id netxen_pci_tbl[] __devinitdata = { MODULE_DEVICE_TABLE(pci, netxen_pci_tbl); -/* - * In netxen_nic_down(), we must wait for any pending callback requests into - * netxen_watchdog_task() to complete; eg otherwise the watchdog_timer could be - * reenabled right after it is deleted in netxen_nic_down(). - * FLUSH_SCHEDULED_WORK() does this synchronization. - * - * Normally, schedule_work()/flush_scheduled_work() could have worked, but - * netxen_nic_close() is invoked with kernel rtnl lock held. netif_carrier_off() - * call in netxen_nic_close() triggers a schedule_work(&linkwatch_work), and a - * subsequent call to flush_scheduled_work() in netxen_nic_down() would cause - * linkwatch_event() to be executed which also attempts to acquire the rtnl - * lock thus causing a deadlock. - */ - static struct workqueue_struct *netxen_workq; #define SCHEDULE_WORK(tp) queue_work(netxen_workq, tp) #define FLUSH_SCHEDULED_WORK() flush_workqueue(netxen_workq) @@ -152,130 +135,148 @@ static uint32_t msi_tgt_status[8] = { static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG; -static inline void netxen_nic_disable_int(struct netxen_adapter *adapter) +static inline void netxen_nic_disable_int(struct nx_host_sds_ring *sds_ring) { - adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0); + struct netxen_adapter *adapter = sds_ring->adapter; + + adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0); } -static inline void netxen_nic_enable_int(struct netxen_adapter *adapter) +static inline void netxen_nic_enable_int(struct nx_host_sds_ring *sds_ring) { - adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0x1); + struct netxen_adapter *adapter = sds_ring->adapter; + + adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0x1); if (!NETXEN_IS_MSI_FAMILY(adapter)) adapter->pci_write_immediate(adapter, adapter->legacy_intr.tgt_mask_reg, 0xfbff); } +static void +netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev) +{ + int ring; + struct nx_host_sds_ring *sds_ring; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + + if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) + adapter->max_sds_rings = (num_online_cpus() >= 4) ? 4 : 2; + else + adapter->max_sds_rings = 1; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + netif_napi_add(netdev, &sds_ring->napi, + netxen_nic_poll, NETXEN_NETDEV_WEIGHT); + } +} + +static void +netxen_napi_enable(struct netxen_adapter *adapter) +{ + int ring; + struct nx_host_sds_ring *sds_ring; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + napi_enable(&sds_ring->napi); + netxen_nic_enable_int(sds_ring); + } +} + +static void +netxen_napi_disable(struct netxen_adapter *adapter) +{ + int ring; + struct nx_host_sds_ring *sds_ring; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + netxen_nic_disable_int(sds_ring); + napi_disable(&sds_ring->napi); + } +} + 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; - } + uint64_t mask, cmask; + adapter->pci_using_dac = 0; + + mask = DMA_32BIT_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. */ + cmask = DMA_32BIT_MASK; + +#ifndef CONFIG_IA64 + if (revision_id >= NX_P3_B0) + mask = DMA_39BIT_MASK; + else if (revision_id == NX_P2_C1) + mask = DMA_35BIT_MASK; +#endif if (pci_set_dma_mask(pdev, mask) == 0 && - pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) == 0) { + pci_set_consistent_dma_mask(pdev, cmask) == 0) { adapter->pci_using_dac = 1; return 0; } -set_32_bit_mask: -#endif /* CONFIG_IA64 */ - 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; + return -EIO; +} + +/* Update addressable range if firmware supports it */ +static int +nx_update_dma_mask(struct netxen_adapter *adapter) +{ + int change, shift, err; + uint64_t mask, old_mask; + struct pci_dev *pdev = adapter->pdev; + + change = 0; + + shift = netxen_nic_reg_read(adapter, CRB_DMA_SHIFT); + if (shift >= 32) + return 0; + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id) && (shift > 9)) + change = 1; + else if ((adapter->ahw.revision_id == NX_P2_C1) && (shift <= 4)) + change = 1; + + if (change) { + old_mask = pdev->dma_mask; + mask = (1ULL<<(32+shift)) - 1; + + err = pci_set_dma_mask(pdev, mask); + if (err) + return pci_set_dma_mask(pdev, old_mask); } - 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_SFP_QT: - case NETXEN_BRDTYPE_P3_10G_SFP_CT: - 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; + if (adapter->ahw.port_type == NETXEN_NIC_XGBE) + adapter->num_rxd = MAX_RCV_DESCRIPTORS_10G; + else if (adapter->ahw.port_type == NETXEN_NIC_GBE) + adapter->num_rxd = MAX_RCV_DESCRIPTORS_1G; - 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: - adapter->msix_supported = !!use_msi_x; - adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; - break; - - 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; - - case NETXEN_BRDTYPE_P3_10G_TP: + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) adapter->msix_supported = !!use_msi_x; - if (adapter->ahw.board_type == NETXEN_NIC_XGBE) - adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G; - else - adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G; - break; - - default: + else 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->num_txd = MAX_CMD_DESCRIPTORS_HOST; + adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS; + adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS; - 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; } @@ -336,7 +337,7 @@ static void netxen_set_port_mode(struct netxen_adapter *adapter) { u32 val, data; - val = adapter->ahw.boardcfg.board_type; + val = adapter->ahw.board_type; if ((val == NETXEN_BRDTYPE_P3_HMEZ) || (val == NETXEN_BRDTYPE_P3_XG_LOM)) { if (port_mode == NETXEN_PORT_MODE_802_3_AP) { @@ -454,91 +455,91 @@ static const struct net_device_ops netxen_netdev_ops = { #endif }; -/* - * netxen_nic_probe() - * - * The Linux system will invoke this after identifying the vendor ID and - * device Id in the pci_tbl supported by this module. - * - * A quad port card has one operational PCI config space, (function 0), - * which is used to access all four ports. - * - * This routine will initialize the adapter, and setup the global parameters - * along with the port's specific structure. - */ -static int __devinit -netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static void +netxen_setup_intr(struct netxen_adapter *adapter) { - struct net_device *netdev = NULL; - struct netxen_adapter *adapter = NULL; - void __iomem *mem_ptr0 = NULL; - void __iomem *mem_ptr1 = NULL; - void __iomem *mem_ptr2 = NULL; - unsigned long first_page_group_end; - unsigned long first_page_group_start; + struct netxen_legacy_intr_set *legacy_intrp; + struct pci_dev *pdev = adapter->pdev; + adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED); + adapter->intr_scheme = -1; + adapter->msi_mode = -1; - u8 __iomem *db_ptr = NULL; - unsigned long mem_base, mem_len, db_base, db_len, pci_len0 = 0; - int i = 0, err; - int first_driver, first_boot; - u32 val; - int pci_func_id = PCI_FUNC(pdev->devfn); - struct netxen_legacy_intr_set *legacy_intrp; - uint8_t revision_id; + if (adapter->ahw.revision_id >= NX_P3_B0) + legacy_intrp = &legacy_intr[adapter->ahw.pci_func]; + else + legacy_intrp = &legacy_intr[0]; + adapter->legacy_intr.int_vec_bit = legacy_intrp->int_vec_bit; + adapter->legacy_intr.tgt_status_reg = legacy_intrp->tgt_status_reg; + adapter->legacy_intr.tgt_mask_reg = legacy_intrp->tgt_mask_reg; + adapter->legacy_intr.pci_int_reg = legacy_intrp->pci_int_reg; - if (pci_func_id == 0) - printk(KERN_INFO "%s\n", netxen_nic_driver_string); + netxen_set_msix_bit(pdev, 0); - 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 (adapter->msix_supported) { - if (pdev->revision >= NX_P3_A0 && pdev->revision < NX_P3_B1) { - printk(KERN_WARNING "NetXen chip revisions between 0x%x-0x%x" - "will not be enabled.\n", - NX_P3_A0, NX_P3_B1); - return -ENODEV; - } + netxen_init_msix_entries(adapter); + if (pci_enable_msix(pdev, adapter->msix_entries, + MSIX_ENTRIES_PER_ADAPTER)) + goto request_msi; - if ((err = pci_enable_device(pdev))) - return err; + adapter->flags |= NETXEN_NIC_MSIX_ENABLED; + netxen_set_msix_bit(pdev, 1); + dev_info(&pdev->dev, "using msi-x interrupts\n"); - if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { - err = -ENODEV; - goto err_out_disable_pdev; + } 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"); + adapter->msix_entries[0].vector = pdev->irq; } +} - if ((err = pci_request_regions(pdev, netxen_nic_driver_name))) - goto err_out_disable_pdev; - - pci_set_master(pdev); +static void +netxen_teardown_intr(struct netxen_adapter *adapter) +{ + if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) + pci_disable_msix(adapter->pdev); + if (adapter->flags & NETXEN_NIC_MSI_ENABLED) + pci_disable_msi(adapter->pdev); +} - netdev = alloc_etherdev(sizeof(struct netxen_adapter)); - if(!netdev) { - printk(KERN_ERR"%s: Failed to allocate memory for the " - "device block.Check system memory resource" - " usage.\n", netxen_nic_driver_name); - goto err_out_free_res; - } +static void +netxen_cleanup_pci_map(struct netxen_adapter *adapter) +{ + if (adapter->ahw.db_base != NULL) + iounmap(adapter->ahw.db_base); + if (adapter->ahw.pci_base0 != NULL) + iounmap(adapter->ahw.pci_base0); + if (adapter->ahw.pci_base1 != NULL) + iounmap(adapter->ahw.pci_base1); + if (adapter->ahw.pci_base2 != NULL) + iounmap(adapter->ahw.pci_base2); +} - SET_NETDEV_DEV(netdev, &pdev->dev); +static int +netxen_setup_pci_map(struct netxen_adapter *adapter) +{ + void __iomem *mem_ptr0 = NULL; + void __iomem *mem_ptr1 = NULL; + void __iomem *mem_ptr2 = NULL; + void __iomem *db_ptr = NULL; - adapter = netdev_priv(netdev); - adapter->netdev = netdev; - adapter->pdev = pdev; - adapter->ahw.pci_func = pci_func_id; + unsigned long mem_base, mem_len, db_base, db_len = 0, pci_len0 = 0; - revision_id = pdev->revision; - adapter->ahw.revision_id = revision_id; + struct pci_dev *pdev = adapter->pdev; + int pci_func = adapter->ahw.pci_func; - err = nx_set_dma_mask(adapter, revision_id); - if (err) - goto err_out_free_netdev; + int err = 0; - rwlock_init(&adapter->adapter_lock); + /* + * 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. + */ + adapter->curr_window = 255; adapter->ahw.qdr_sn_window = -1; adapter->ahw.ddr_mn_window = -1; @@ -564,14 +565,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) SECOND_PAGE_GROUP_SIZE); mem_ptr2 = ioremap(mem_base + THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE); - first_page_group_start = FIRST_PAGE_GROUP_START; - first_page_group_end = FIRST_PAGE_GROUP_END; } else if (mem_len == NETXEN_PCI_32MB_SIZE) { mem_ptr1 = ioremap(mem_base, SECOND_PAGE_GROUP_SIZE); mem_ptr2 = ioremap(mem_base + THIRD_PAGE_GROUP_START - 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; @@ -590,29 +587,33 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) dev_err(&pdev->dev, "failed to map PCI bar 0\n"); return -EIO; } - 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); + (pci_func * 0x20); adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW; - if (pci_func_id < 4) - adapter->ahw.ms_win_crb += (pci_func_id * 0x20); + if (pci_func < 4) + adapter->ahw.ms_win_crb += (pci_func * 0x20); else adapter->ahw.ms_win_crb += - 0xA0 + ((pci_func_id - 4) * 0x10); + 0xA0 + ((pci_func - 4) * 0x10); } else { - err = -EIO; - goto err_out_free_netdev; + return -EIO; } dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20)); + adapter->ahw.pci_base0 = mem_ptr0; + adapter->ahw.pci_len0 = pci_len0; + adapter->ahw.pci_base1 = mem_ptr1; + adapter->ahw.pci_base2 = mem_ptr2; + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + goto skip_doorbell; + db_base = pci_resource_start(pdev, 4); /* doorbell is on bar 4 */ db_len = pci_resource_len(pdev, 4); @@ -620,49 +621,349 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) printk(KERN_ERR "%s: doorbell is disabled\n", netxen_nic_driver_name); err = -EIO; - goto err_out_iounmap; + goto err_out; } - DPRINTK(INFO, "doorbell ioremap from %lx a size of %lx\n", db_base, - db_len); 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); err = -EIO; - goto err_out_iounmap; + goto err_out; } - 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; - adapter->ahw.pci_base2 = mem_ptr2; +skip_doorbell: adapter->ahw.db_base = db_ptr; adapter->ahw.db_len = db_len; + return 0; - netif_napi_add(netdev, &adapter->napi, - netxen_nic_poll, NETXEN_NETDEV_WEIGHT); +err_out: + netxen_cleanup_pci_map(adapter); + return err; +} - if (revision_id >= NX_P3_B0) - legacy_intrp = &legacy_intr[pci_func_id]; +static int +netxen_start_firmware(struct netxen_adapter *adapter) +{ + int val, err, first_boot; + struct pci_dev *pdev = adapter->pdev; + + int first_driver = 0; + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + if (adapter->ahw.pci_func == 0) + first_driver = 1; + } else { + if (adapter->portnum == 0) + first_driver = 1; + } + + if (!first_driver) + return 0; + + first_boot = adapter->pci_read_normalize(adapter, + NETXEN_CAM_RAM(0x1fc)); + + err = netxen_check_hw_init(adapter, first_boot); + if (err) { + dev_err(&pdev->dev, "error in init HW init sequence\n"); + return err; + } + + if (first_boot != 0x55555555) { + adapter->pci_write_normalize(adapter, + CRB_CMDPEG_STATE, 0); + netxen_pinit_from_rom(adapter, 0); + msleep(1); + } + + netxen_nic_reg_write(adapter, CRB_DMA_SHIFT, 0x55555555); + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + netxen_set_port_mode(adapter); + + netxen_load_firmware(adapter); + + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + + /* Initialize multicast addr pool owners */ + val = 0x7654; + if (adapter->ahw.port_type == NETXEN_NIC_XGBE) + val |= 0x0f000000; + netxen_crb_writelit_adapter(adapter, + NETXEN_MAC_ADDR_CNTL_REG, val); + + } + + err = netxen_initialize_adapter_offload(adapter); + if (err) + return err; + + /* + * Tell the hardware our version number. + */ + val = (_NETXEN_NIC_LINUX_MAJOR << 16) + | ((_NETXEN_NIC_LINUX_MINOR << 8)) + | (_NETXEN_NIC_LINUX_SUBVERSION); + adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, val); + + /* Handshake with the card before we register the devices. */ + err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); + if (err) { + netxen_free_adapter_offload(adapter); + return err; + } + + return 0; +} + +static int +netxen_nic_request_irq(struct netxen_adapter *adapter) +{ + irq_handler_t handler; + struct nx_host_sds_ring *sds_ring; + int err, ring; + + unsigned long flags = IRQF_SAMPLE_RANDOM; + struct net_device *netdev = adapter->netdev; + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + + if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) || + (adapter->intr_scheme != INTR_SCHEME_PERPORT)) { + printk(KERN_ERR "%s: Firmware interrupt scheme is " + "incompatible with driver\n", + netdev->name); + adapter->driver_mismatch = 1; + return -EINVAL; + } + + if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) + handler = netxen_msix_intr; + else if (adapter->flags & NETXEN_NIC_MSI_ENABLED) + handler = netxen_msi_intr; + else { + flags |= IRQF_SHARED; + handler = netxen_intr; + } + adapter->irq = netdev->irq; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + sprintf(sds_ring->name, "%16s[%d]", netdev->name, ring); + err = request_irq(sds_ring->irq, handler, + flags, sds_ring->name, sds_ring); + if (err) + return err; + } + + return 0; +} + +static void +netxen_nic_free_irq(struct netxen_adapter *adapter) +{ + int ring; + struct nx_host_sds_ring *sds_ring; + + struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; + + for (ring = 0; ring < adapter->max_sds_rings; ring++) { + sds_ring = &recv_ctx->sds_rings[ring]; + free_irq(sds_ring->irq, sds_ring); + } +} + +static int +netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) +{ + int err; + + 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 err; + } + adapter->macaddr_set(adapter, netdev->dev_addr); + + netxen_nic_set_link_parameters(adapter); + + netxen_set_multicast_list(netdev); + if (adapter->set_mtu) + adapter->set_mtu(adapter, netdev->mtu); + + adapter->ahw.linkup = 0; + mod_timer(&adapter->watchdog_timer, jiffies); + + netxen_napi_enable(adapter); + + if (adapter->max_sds_rings > 1) + netxen_config_rss(adapter, 1); + + return 0; +} + +static void +netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) +{ + netif_carrier_off(netdev); + netif_stop_queue(netdev); + netxen_napi_disable(adapter); + + if (adapter->stop_port) + adapter->stop_port(adapter); + + netxen_release_tx_buffers(adapter); + + FLUSH_SCHEDULED_WORK(); + del_timer_sync(&adapter->watchdog_timer); +} + + +static int +netxen_nic_attach(struct netxen_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + int err, ring; + struct nx_host_rds_ring *rds_ring; + + err = netxen_init_firmware(adapter); + if (err != 0) { + printk(KERN_ERR "Failed to init firmware\n"); + return -EIO; + } + + if (adapter->fw_major < 4) + adapter->max_rds_rings = 3; else - legacy_intrp = &legacy_intr[0]; + adapter->max_rds_rings = 2; - 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; + err = netxen_alloc_sw_resources(adapter); + if (err) { + printk(KERN_ERR "%s: Error in setting sw resources\n", + netdev->name); + return err; + } - /* this will be read from FW later */ - adapter->intr_scheme = -1; - adapter->msi_mode = -1; + 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 (ring = 0; ring < adapter->max_rds_rings; ring++) { + rds_ring = &adapter->recv_ctx.rds_rings[ring]; + netxen_post_rx_buffers(adapter, ring, rds_ring); + } + + err = netxen_nic_request_irq(adapter); + if (err) { + dev_err(&pdev->dev, "%s: failed to setup interrupt\n", + netdev->name); + goto err_out_free_rxbuf; + } + + adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; + return 0; + +err_out_free_rxbuf: + netxen_release_rx_buffers(adapter); + netxen_free_hw_resources(adapter); +err_out_free_sw: + netxen_free_sw_resources(adapter); + return err; +} + +static void +netxen_nic_detach(struct netxen_adapter *adapter) +{ + netxen_nic_free_irq(adapter); + + netxen_release_rx_buffers(adapter); + netxen_free_hw_resources(adapter); + netxen_free_sw_resources(adapter); + + adapter->is_up = 0; +} + +static int __devinit +netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct net_device *netdev = NULL; + struct netxen_adapter *adapter = NULL; + int i = 0, err; + int pci_func_id = PCI_FUNC(pdev->devfn); + uint8_t revision_id; + + 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 (pdev->revision >= NX_P3_A0 && pdev->revision < NX_P3_B1) { + printk(KERN_WARNING "NetXen chip revisions between 0x%x-0x%x" + "will not be enabled.\n", + NX_P3_A0, NX_P3_B1); + 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; + } + + if ((err = pci_request_regions(pdev, netxen_nic_driver_name))) + goto err_out_disable_pdev; + + pci_set_master(pdev); + + netdev = alloc_etherdev(sizeof(struct netxen_adapter)); + if(!netdev) { + printk(KERN_ERR"%s: Failed to allocate memory for the " + "device block.Check system memory resource" + " usage.\n", netxen_nic_driver_name); + goto err_out_free_res; + } + + SET_NETDEV_DEV(netdev, &pdev->dev); + + adapter = netdev_priv(netdev); + 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); + spin_lock_init(&adapter->tx_clean_lock); + + err = netxen_setup_pci_map(adapter); + if (err) + goto err_out_free_netdev; /* This will be reset for mezz cards */ 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)) @@ -690,12 +991,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->vlan_features |= NETIF_F_HIGHDMA; } - /* - * 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. - */ - adapter->curr_window = 255; - if (netxen_nic_get_board_info(adapter) != 0) { printk("%s: Error getting board config info.\n", netxen_nic_driver_name); @@ -706,7 +1001,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netxen_initialize_adapter_ops(adapter); /* Mezz cards have PCI function 0,2,3 enabled */ - switch (adapter->ahw.boardcfg.board_type) { + switch (adapter->ahw.board_type) { case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ: case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ: if (pci_func_id >= 2) @@ -716,82 +1011,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) break; } - /* - * 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; - } - - if (first_driver) { - first_boot = adapter->pci_read_normalize(adapter, - NETXEN_CAM_RAM(0x1fc)); - - 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 (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); - - 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); - - } - - err = netxen_initialize_adapter_offload(adapter); - if (err) - goto err_out_iounmap; - - /* - * Tell the hardware our version number. - */ - i = (_NETXEN_NIC_LINUX_MAJOR << 16) - | ((_NETXEN_NIC_LINUX_MINOR << 8)) - | (_NETXEN_NIC_LINUX_SUBVERSION); - adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, i); - - /* Handshake with the card before we register the devices. */ - err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); - if (err) - goto err_out_free_offload; + err = netxen_start_firmware(adapter); + if (err) + goto err_out_iounmap; - } /* first_driver */ + nx_update_dma_mask(adapter); - 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"); - } + netxen_nic_get_firmware_info(adapter); /* * See if the firmware gave us a virtual-physical port mapping. @@ -804,41 +1030,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 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_check_options(adapter); - netxen_init_msix_entries(adapter); + netxen_setup_intr(adapter); - if (pci_enable_msix(pdev, adapter->msix_entries, - MSIX_ENTRIES_PER_ADAPTER)) - goto request_msi; + netdev->irq = adapter->msix_entries[0].vector; - 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; + netxen_napi_add(adapter, netdev); err = netxen_receive_peg_ready(adapter); if (err) @@ -867,7 +1065,7 @@ request_msi: pci_set_drvdata(pdev, adapter); - switch (adapter->ahw.board_type) { + switch (adapter->ahw.port_type) { case NETXEN_NIC_GBE: dev_info(&adapter->pdev->dev, "%s: GbE port initialized\n", adapter->netdev->name); @@ -881,25 +1079,12 @@ request_msi: 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); + netxen_teardown_intr(adapter); -err_out_free_offload: - if (first_driver) - netxen_free_adapter_offload(adapter); + netxen_free_adapter_offload(adapter); err_out_iounmap: - if (db_ptr) - iounmap(db_ptr); - - if (mem_ptr0) - iounmap(mem_ptr0); - if (mem_ptr1) - iounmap(mem_ptr1); - if (mem_ptr2) - iounmap(mem_ptr2); + netxen_cleanup_pci_map(adapter); err_out_free_netdev: free_netdev(netdev); @@ -927,9 +1112,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) unregister_netdev(netdev); if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { - netxen_free_hw_resources(adapter); - netxen_release_rx_buffers(adapter); - netxen_free_sw_resources(adapter); + netxen_nic_detach(adapter); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) netxen_p3_free_mac_list(adapter); @@ -938,20 +1121,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) if (adapter->portnum == 0) netxen_free_adapter_offload(adapter); - if (adapter->irq) - free_irq(adapter->irq, adapter); + netxen_teardown_intr(adapter); - if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) - pci_disable_msix(pdev); - if (adapter->flags & NETXEN_NIC_MSI_ENABLED) - pci_disable_msi(pdev); - - iounmap(adapter->ahw.db_base); - iounmap(adapter->ahw.pci_base0); - if (adapter->ahw.pci_base1 != NULL) - iounmap(adapter->ahw.pci_base1); - if (adapter->ahw.pci_base2 != NULL) - iounmap(adapter->ahw.pci_base2); + netxen_cleanup_pci_map(adapter); pci_release_regions(pdev); pci_disable_device(pdev); @@ -960,125 +1132,95 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) free_netdev(netdev); } -/* - * Called when a network interface is made active - * @returns 0 on success, negative value on failure - */ -static int netxen_nic_open(struct net_device *netdev) +static int +netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) { - struct netxen_adapter *adapter = netdev_priv(netdev); - int err = 0; - int ctx, ring; - irq_handler_t handler; - unsigned long flags = IRQF_SAMPLE_RANDOM; - if (adapter->driver_mismatch) - return -EIO; + struct netxen_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; - if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) { - err = netxen_init_firmware(adapter); - if (err != 0) { - printk(KERN_ERR "Failed to init firmware\n"); - return -EIO; - } + netif_device_detach(netdev); - if (adapter->fw_major < 4) - adapter->max_rds_rings = 3; - else - adapter->max_rds_rings = 2; + if (netif_running(netdev)) + netxen_nic_down(adapter, netdev); - err = netxen_alloc_sw_resources(adapter); - if (err) { - printk(KERN_ERR "%s: Error in setting sw resources\n", - netdev->name); - return err; - } + if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) + netxen_nic_detach(adapter); - netxen_nic_clear_stats(adapter); + pci_save_state(pdev); - 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 (netxen_nic_wol_supported(adapter)) { + pci_enable_wake(pdev, PCI_D3cold, 1); + pci_enable_wake(pdev, PCI_D3hot, 1); + } - if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) || - (adapter->intr_scheme != INTR_SCHEME_PERPORT)) { - printk(KERN_ERR "%s: Firmware interrupt scheme is " - "incompatible with driver\n", - netdev->name); - adapter->driver_mismatch = 1; - goto err_out_free_hw; - } + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + + return 0; +} - 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]; +static int +netxen_nic_resume(struct pci_dev *pdev) +{ + struct netxen_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + int err; - netxen_nic_update_cmd_producer(adapter, 0); - netxen_nic_update_cmd_consumer(adapter, 0); - } + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); - for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { - for (ring = 0; ring < adapter->max_rds_rings; ring++) - netxen_post_rx_buffers(adapter, ctx, ring); - } - if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) - handler = netxen_msix_intr; - else if (adapter->flags & NETXEN_NIC_MSI_ENABLED) - 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); - goto err_out_free_rxbuf; - } + err = pci_enable_device(pdev); + if (err) + return err; - adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; - } + adapter->curr_window = 255; - /* Done here again so that even if phantom sw overwrote it, - * we set it */ - err = adapter->init_port(adapter, adapter->physical_port); + err = netxen_start_firmware(adapter); if (err) { - printk(KERN_ERR "%s: Failed to initialize port %d\n", - netxen_nic_driver_name, adapter->portnum); - goto err_out_free_irq; + dev_err(&pdev->dev, "failed to start firmware\n"); + return err; } - adapter->macaddr_set(adapter, netdev->dev_addr); - netxen_nic_set_link_parameters(adapter); + if (netif_running(netdev)) { + err = netxen_nic_attach(adapter); + if (err) + return err; - netxen_set_multicast_list(netdev); - if (adapter->set_mtu) - adapter->set_mtu(adapter, netdev->mtu); + err = netxen_nic_up(adapter, netdev); + if (err) + return err; - adapter->ahw.linkup = 0; - mod_timer(&adapter->watchdog_timer, jiffies); + netif_device_attach(netdev); + } + + return 0; +} - napi_enable(&adapter->napi); - netxen_nic_enable_int(adapter); +static int netxen_nic_open(struct net_device *netdev) +{ + struct netxen_adapter *adapter = netdev_priv(netdev); + int err = 0; + + if (adapter->driver_mismatch) + return -EIO; + + if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) { + err = netxen_nic_attach(adapter); + if (err) + return err; + } + + err = netxen_nic_up(adapter, netdev); + if (err) + goto err_out; netif_start_queue(netdev); return 0; -err_out_free_irq: - free_irq(adapter->irq, adapter); -err_out_free_rxbuf: - netxen_release_rx_buffers(adapter); -err_out_free_hw: - netxen_free_hw_resources(adapter); -err_out_free_sw: - netxen_free_sw_resources(adapter); +err_out: + netxen_nic_detach(adapter); return err; } @@ -1089,20 +1231,7 @@ static int netxen_nic_close(struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); - netif_carrier_off(netdev); - netif_stop_queue(netdev); - napi_disable(&adapter->napi); - - if (adapter->stop_port) - adapter->stop_port(adapter); - - netxen_nic_disable_int(adapter); - - netxen_release_tx_buffers(adapter); - - FLUSH_SCHEDULED_WORK(); - del_timer_sync(&adapter->watchdog_timer); - + netxen_nic_down(adapter, netdev); return 0; } @@ -1114,7 +1243,7 @@ static bool netxen_tso_check(struct net_device *netdev, __be16 protocol = skb->protocol; u16 flags = 0; - if (protocol == __constant_htons(ETH_P_8021Q)) { + if (protocol == cpu_to_be16(ETH_P_8021Q)) { struct vlan_ethhdr *vh = (struct vlan_ethhdr *)skb->data; protocol = vh->h_vlan_encapsulated_proto; flags = FLAGS_VLAN_TAGGED; @@ -1127,21 +1256,21 @@ static bool netxen_tso_check(struct net_device *netdev, desc->total_hdr_length = skb_transport_offset(skb) + tcp_hdrlen(skb); - opcode = (protocol == __constant_htons(ETH_P_IPV6)) ? + opcode = (protocol == cpu_to_be16(ETH_P_IPV6)) ? TX_TCP_LSO6 : TX_TCP_LSO; tso = true; } else if (skb->ip_summed == CHECKSUM_PARTIAL) { u8 l4proto; - if (protocol == __constant_htons(ETH_P_IP)) { + if (protocol == cpu_to_be16(ETH_P_IP)) { l4proto = ip_hdr(skb)->protocol; if (l4proto == IPPROTO_TCP) opcode = TX_TCP_PKT; else if(l4proto == IPPROTO_UDP) opcode = TX_UDP_PKT; - } else if (protocol == __constant_htons(ETH_P_IPV6)) { + } else if (protocol == cpu_to_be16(ETH_P_IPV6)) { l4proto = ipv6_hdr(skb)->nexthdr; if (l4proto == IPPROTO_TCP) @@ -1174,7 +1303,16 @@ netxen_clean_tx_dma_mapping(struct pci_dev *pdev, } } -static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +static inline void +netxen_clear_cmddesc(u64 *desc) +{ + int i; + for (i = 0; i < 8; i++) + desc[i] = 0ULL; +} + +static int +netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); struct netxen_hardware_context *hw = &adapter->ahw; @@ -1188,7 +1326,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) u32 producer, consumer; int frag_count, no_of_desc; - u32 num_txd = adapter->max_tx_desc_count; + u32 num_txd = adapter->num_txd; bool is_tso = false; frag_count = skb_shinfo(skb)->nr_frags + 1; @@ -1207,7 +1345,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* Copy the descriptors into the hardware */ hwdesc = &hw->cmd_desc_head[producer]; - memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); + netxen_clear_cmddesc((u64 *)hwdesc); /* Take skb->data itself */ pbuf = &adapter->cmd_buf_arr[producer]; @@ -1226,7 +1364,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) netxen_set_tx_frags_len(hwdesc, frag_count, skb->len); netxen_set_tx_port(hwdesc, adapter->portnum); - hwdesc->buffer1_length = cpu_to_le16(first_seg_len); + hwdesc->buffer_length[0] = cpu_to_le16(first_seg_len); hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); for (i = 1, k = 1; i < frag_count; i++, k++) { @@ -1239,7 +1377,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) k = 0; producer = get_next_index(producer, num_txd); hwdesc = &hw->cmd_desc_head[producer]; - memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); + netxen_clear_cmddesc((u64 *)hwdesc); pbuf = &adapter->cmd_buf_arr[producer]; pbuf->skb = NULL; } @@ -1259,21 +1397,18 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) buffrag->dma = temp_dma; buffrag->length = temp_len; + hwdesc->buffer_length[k] = cpu_to_le16(temp_len); switch (k) { case 0: - hwdesc->buffer1_length = cpu_to_le16(temp_len); hwdesc->addr_buffer1 = cpu_to_le64(temp_dma); break; case 1: - hwdesc->buffer2_length = cpu_to_le16(temp_len); hwdesc->addr_buffer2 = cpu_to_le64(temp_dma); break; case 2: - hwdesc->buffer3_length = cpu_to_le16(temp_len); hwdesc->addr_buffer3 = cpu_to_le64(temp_dma); break; case 3: - hwdesc->buffer4_length = cpu_to_le16(temp_len); hwdesc->addr_buffer4 = cpu_to_le64(temp_dma); break; } @@ -1388,7 +1523,7 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) linkup = (val == XG_LINK_UP_P3); } else { val = adapter->pci_read_normalize(adapter, CRB_XG_STATE); - if (adapter->ahw.board_type == NETXEN_NIC_GBE) + if (adapter->ahw.port_type == NETXEN_NIC_GBE) linkup = (val >> port) & 1; else { val = (val >> port*8) & 0xff; @@ -1455,13 +1590,11 @@ static void netxen_tx_timeout_task(struct work_struct *work) printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", netxen_nic_driver_name, adapter->netdev->name); - netxen_nic_disable_int(adapter); - napi_disable(&adapter->napi); + netxen_napi_disable(adapter); adapter->netdev->trans_start = jiffies; - napi_enable(&adapter->napi); - netxen_nic_enable_int(adapter); + netxen_napi_enable(adapter); netif_wake_queue(adapter->netdev); } @@ -1499,7 +1632,8 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) static irqreturn_t netxen_intr(int irq, void *data) { - struct netxen_adapter *adapter = data; + struct nx_host_sds_ring *sds_ring = data; + struct netxen_adapter *adapter = sds_ring->adapter; u32 status = 0; status = adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); @@ -1530,7 +1664,7 @@ static irqreturn_t netxen_intr(int irq, void *data) /* clear interrupt */ if (adapter->fw_major < 4) - netxen_nic_disable_int(adapter); + netxen_nic_disable_int(sds_ring); adapter->pci_write_immediate(adapter, adapter->legacy_intr.tgt_status_reg, @@ -1539,61 +1673,49 @@ static irqreturn_t netxen_intr(int irq, void *data) adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); - napi_schedule(&adapter->napi); + napi_schedule(&sds_ring->napi); return IRQ_HANDLED; } static irqreturn_t netxen_msi_intr(int irq, void *data) { - struct netxen_adapter *adapter = data; + struct nx_host_sds_ring *sds_ring = data; + struct netxen_adapter *adapter = sds_ring->adapter; /* clear interrupt */ adapter->pci_write_immediate(adapter, msi_tgt_status[adapter->ahw.pci_func], 0xffffffff); - napi_schedule(&adapter->napi); + napi_schedule(&sds_ring->napi); return IRQ_HANDLED; } static irqreturn_t netxen_msix_intr(int irq, void *data) { - struct netxen_adapter *adapter = data; + struct nx_host_sds_ring *sds_ring = data; - napi_schedule(&adapter->napi); + napi_schedule(&sds_ring->napi); return IRQ_HANDLED; } static int netxen_nic_poll(struct napi_struct *napi, int budget) { - struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi); + struct nx_host_sds_ring *sds_ring = + container_of(napi, struct nx_host_sds_ring, napi); + + struct netxen_adapter *adapter = sds_ring->adapter; + int tx_complete; - int ctx; int work_done; tx_complete = netxen_process_cmd_ring(adapter); - work_done = 0; - for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { - /* - * Fairness issue. This will give undue weight to the - * receive context 0. - */ - - /* - * To avoid starvation, we give each of our receivers, - * a fraction of the quota. Sometimes, it might happen that we - * have enough quota to process every packet, but since all the - * packets are on one context, it gets only half of the quota, - * and ends up not processing it. - */ - work_done += netxen_process_rcv_ring(adapter, ctx, - budget / MAX_RCV_CTX); - } + work_done = netxen_process_rcv_ring(sds_ring, budget); if ((work_done < budget) && tx_complete) { - netif_rx_complete(&adapter->napi); - netxen_nic_enable_int(adapter); + napi_complete(&sds_ring->napi); + netxen_nic_enable_int(sds_ring); } return work_done; @@ -1613,13 +1735,17 @@ static struct pci_driver netxen_driver = { .name = netxen_nic_driver_name, .id_table = netxen_pci_tbl, .probe = netxen_nic_probe, - .remove = __devexit_p(netxen_nic_remove) + .remove = __devexit_p(netxen_nic_remove), + .suspend = netxen_nic_suspend, + .resume = netxen_nic_resume }; /* Driver Registration on NetXen card */ static int __init netxen_init_module(void) { + printk(KERN_INFO "%s\n", netxen_nic_driver_string); + if ((netxen_workq = create_singlethread_workqueue("netxen")) == NULL) return -ENOMEM; diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c index c3b9c83b32fe..d85203203d4d 100644 --- a/drivers/net/netxen/netxen_nic_niu.c +++ b/drivers/net/netxen/netxen_nic_niu.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 - 2006 NetXen, Inc. + * Copyright (C) 2003 - 2009 NetXen, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -22,12 +22,9 @@ * * Contact Information: * info@netxen.com - * NetXen, - * 3965 Freedom Circle, Fourth floor, - * Santa Clara, CA 95054 - * - * - * Provides access to the Network Interface Unit h/w block. + * NetXen Inc, + * 18922 Forge Drive + * Cupertino, CA 95014-0701 * */ @@ -299,14 +296,6 @@ int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter) return result; } -#if 0 -int netxen_niu_xgbe_clear_phy_interrupts(struct netxen_adapter *adapter) -{ - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_ACTIVE_INT, -1); - return 0; -} -#endif /* 0 */ - static int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter) { int result = 0; @@ -467,104 +456,6 @@ int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port) return 0; } -#if 0 -/* - * netxen_niu_gbe_handle_phy_interrupt - Handles GbE PHY interrupts - * @param enable 0 means don't enable the port - * 1 means enable (or re-enable) the port - */ -int netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter, - int port, long enable) -{ - int result = 0; - __u32 int_src; - - printk(KERN_INFO PFX "NETXEN: Handling PHY interrupt on port %d" - " (device enable = %d)\n", (int)port, (int)enable); - - /* - * The read of the PHY INT status will clear the pending - * interrupt status - */ - if (netxen_niu_gbe_phy_read(adapter, - NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS, - &int_src) != 0) - result = -EINVAL; - else { - printk(KERN_INFO PFX "PHY Interrupt source = 0x%x \n", int_src); - if (netxen_get_phy_int_jabber(int_src)) - printk(KERN_INFO PFX "jabber Interrupt "); - if (netxen_get_phy_int_polarity_changed(int_src)) - printk(KERN_INFO PFX "polarity changed "); - if (netxen_get_phy_int_energy_detect(int_src)) - printk(KERN_INFO PFX "energy detect \n"); - if (netxen_get_phy_int_downshift(int_src)) - printk(KERN_INFO PFX "downshift \n"); - if (netxen_get_phy_int_mdi_xover_changed(int_src)) - printk(KERN_INFO PFX "mdi_xover_changed "); - if (netxen_get_phy_int_fifo_over_underflow(int_src)) - printk(KERN_INFO PFX "fifo_over_underflow "); - if (netxen_get_phy_int_false_carrier(int_src)) - printk(KERN_INFO PFX "false_carrier "); - if (netxen_get_phy_int_symbol_error(int_src)) - printk(KERN_INFO PFX "symbol_error "); - if (netxen_get_phy_int_autoneg_completed(int_src)) - printk(KERN_INFO PFX "autoneg_completed "); - if (netxen_get_phy_int_page_received(int_src)) - printk(KERN_INFO PFX "page_received "); - if (netxen_get_phy_int_duplex_changed(int_src)) - printk(KERN_INFO PFX "duplex_changed "); - if (netxen_get_phy_int_autoneg_error(int_src)) - printk(KERN_INFO PFX "autoneg_error "); - if ((netxen_get_phy_int_speed_changed(int_src)) - || (netxen_get_phy_int_link_status_changed(int_src))) { - __u32 status; - - printk(KERN_INFO PFX - "speed_changed or link status changed"); - if (netxen_niu_gbe_phy_read - (adapter, - NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, - &status) == 0) { - if (netxen_get_phy_speed(status) == 2) { - printk - (KERN_INFO PFX "Link speed changed" - " to 1000 Mbps\n"); - netxen_niu_gbe_set_gmii_mode(adapter, - port, - enable); - } else if (netxen_get_phy_speed(status) == 1) { - printk - (KERN_INFO PFX "Link speed changed" - " to 100 Mbps\n"); - netxen_niu_gbe_set_mii_mode(adapter, - port, - enable); - } else if (netxen_get_phy_speed(status) == 0) { - printk - (KERN_INFO PFX "Link speed changed" - " to 10 Mbps\n"); - netxen_niu_gbe_set_mii_mode(adapter, - port, - enable); - } else { - printk(KERN_ERR PFX "ERROR reading " - "PHY status. Invalid speed.\n"); - result = -1; - } - } else { - printk(KERN_ERR PFX - "ERROR reading PHY status.\n"); - result = -1; - } - - } - printk(KERN_INFO "\n"); - } - return result; -} -#endif /* 0 */ - /* * Return the current station MAC address. * Note that the passed-in value must already be in network byte order. @@ -641,86 +532,6 @@ int netxen_niu_macaddr_set(struct netxen_adapter *adapter, return 0; } -#if 0 -/* Enable a GbE interface */ -int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter, - int port, netxen_niu_gbe_ifmode_t mode) -{ - __u32 mac_cfg0; - __u32 mac_cfg1; - __u32 mii_cfg; - - if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) - return -EINVAL; - - mac_cfg0 = 0; - netxen_gb_soft_reset(mac_cfg0); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - &mac_cfg0, 4)) - return -EIO; - mac_cfg0 = 0; - netxen_gb_enable_tx(mac_cfg0); - netxen_gb_enable_rx(mac_cfg0); - netxen_gb_unset_rx_flowctl(mac_cfg0); - netxen_gb_tx_reset_pb(mac_cfg0); - netxen_gb_rx_reset_pb(mac_cfg0); - netxen_gb_tx_reset_mac(mac_cfg0); - netxen_gb_rx_reset_mac(mac_cfg0); - - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - &mac_cfg0, 4)) - return -EIO; - mac_cfg1 = 0; - netxen_gb_set_preamblelen(mac_cfg1, 0xf); - netxen_gb_set_duplex(mac_cfg1); - netxen_gb_set_crc_enable(mac_cfg1); - netxen_gb_set_padshort(mac_cfg1); - netxen_gb_set_checklength(mac_cfg1); - netxen_gb_set_hugeframes(mac_cfg1); - - if (mode == NETXEN_NIU_10_100_MB) { - netxen_gb_set_intfmode(mac_cfg1, 1); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_1(port), - &mac_cfg1, 4)) - return -EIO; - - /* set mii mode */ - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE + - (port << 3), 0); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE + - (port << 3), 1); - - } else if (mode == NETXEN_NIU_1000_MB) { - netxen_gb_set_intfmode(mac_cfg1, 2); - if (adapter->hw_write_wx(adapter, - NETXEN_NIU_GB_MAC_CONFIG_1(port), - &mac_cfg1, 4)) - return -EIO; - /* set gmii mode */ - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE + - (port << 3), 0); - netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE + - (port << 3), 1); - } - mii_cfg = 0; - netxen_gb_set_mii_mgmt_clockselect(mii_cfg, 7); - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), - &mii_cfg, 4)) - return -EIO; - mac_cfg0 = 0; - netxen_gb_enable_tx(mac_cfg0); - netxen_gb_enable_rx(mac_cfg0); - netxen_gb_unset_rx_flowctl(mac_cfg0); - netxen_gb_unset_tx_flowctl(mac_cfg0); - - if (adapter->hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), - &mac_cfg0, 4)) - return -EIO; - return 0; -} -#endif /* 0 */ - /* Disable a GbE interface */ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter) { @@ -869,39 +680,6 @@ int netxen_niu_xg_macaddr_set(struct netxen_adapter *adapter, return 0; } -#if 0 -/* - * Return the current station MAC address. - * Note that the passed-in value must already be in network byte order. - */ -int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, - netxen_ethernet_macaddr_t * addr) -{ - int phy = adapter->physical_port; - u32 stationhigh; - u32 stationlow; - u8 val[8]; - - if (addr == NULL) - return -EINVAL; - if (phy != 0) - return -EINVAL; - - if (adapter->hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI, - &stationhigh, 4)) - return -EIO; - if (adapter->hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1, - &stationlow, 4)) - return -EIO; - ((__le32 *)val)[1] = cpu_to_le32(stationhigh); - ((__le32 *)val)[0] = cpu_to_le32(stationlow); - - memcpy(addr, val + 2, 6); - - return 0; -} -#endif /* 0 */ - int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, u32 mode) { diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index b293adcc95ab..50183335e43a 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003 - 2006 NetXen, Inc. + * Copyright (C) 2003 - 2009 NetXen, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -22,9 +22,10 @@ * * Contact Information: * info@netxen.com - * NetXen, - * 3965 Freedom Circle, Fourth floor, - * Santa Clara, CA 95054 + * NetXen Inc, + * 18922 Forge Drive + * Cupertino, CA 95014-0701 + * */ #ifndef __NIC_PHAN_REG_H_ @@ -90,6 +91,7 @@ #define CRB_RX_LRO_START_NUM NETXEN_NIC_REG(0xc0) #define CRB_MPORT_MODE NETXEN_NIC_REG(0xc4) /* Multiport Mode */ #define CRB_CMD_RING_SIZE NETXEN_NIC_REG(0xc8) +#define CRB_DMA_SHIFT NETXEN_NIC_REG(0xcc) #define CRB_INT_VECTOR NETXEN_NIC_REG(0xd4) #define CRB_CTX_RESET NETXEN_NIC_REG(0xd8) #define CRB_HOST_STS_PROD NETXEN_NIC_REG(0xdc) |