myri10ge updates
Subsystems (2)
cover myri10ge updates
Hello Jeff,
myri10ge has not been updated for a while, so here's a huge pile of patches to fix a couple minor things and add multislices and DCA support:
01 - update firmware headers
02 - fix module parameter descriptions
03 - increase and fix handoff timeout
04 - properly align scratch buffers
05 - don't warn on rx page allocation failure
06 - report FIBER in ethtool for XFP based NIC
07 - add barrier in myri10ge_send_cmd
08 - trivial formatting fix
09 - fix potential infinite loop in enable_ecrc
10 - move data structures into a single slice
11 - cleanup retrieving of firmware capabilities
12 - fix the number of interrupt slots
13 - add routines for multislices
14 - add multislices support
15 - add Direct Cache Access support
16 - update driver version
01-09 are trivial and should easily go into 2.6.26. The other ones are much more intrusive, so I'll understand if they have to wait until 2.6.27. Just make sure you don't pickup anything out of order since there are big dependencies among the last ones.
Note that 10-14 are actually mostly the same thing. But a single patch for all the multislices support would have been unreviewable, so I tried to split it into independent pieces.
thanks,
Brice
PATCH 1/16 myri10ge: update firmware headers
Update myri10ge firmware headers.
--- drivers/net/myri10ge/myri10ge_mcp.h | 56 ++++++++++++++++++++++--- drivers/net/myri10ge/myri10ge_mcp_gen_header.h | 39 ++++++----------- 2 files changed, 64 insertions(+), 31 deletions(-)
drivers/net/myri10ge/myri10ge_mcp.h +50 -6
@@ -10,7 +10,7 @@__be32 low; }; -/* 4 Bytes. 8 Bytes for NDIS drivers. */ +/* 4 Bytes */ struct mcp_slot {__sum16 checksum;__be16 length;
@@ -144,6 +144,7 @@* a power of 2 number of entries. */ MXGEFW_CMD_SET_INTRQ_SIZE ,/* in bytes */ +#define MXGEFW_CMD_SET_INTRQ_SIZE_FLAG_NO_STRICT_SIZE_CHECK (1 << 31)/* command to bring ethernet interface up. Above parameters * (plus mtu & mac address) must have been exchanged prior
@@ -221,10 +222,14 @@ MXGEFW_CMD_GET_MAX_RSS_QUEUES, MXGEFW_CMD_ENABLE_RSS_QUEUES,/* data0 = number of slices n (0, 1, ..., n-1) to enable -* data1 = interrupt mode. 0=share one INTx/MSI, 1=use one MSI-X per queue. +* data1 = interrupt mode. +* 0=share one INTx/MSI, 1=use one MSI-X per queue. * If all queues share one interrupt, the driver must have set * RSS_SHARED_INTERRUPT_DMA before enabling queues. */ +#define MXGEFW_SLICE_INTR_MODE_SHARED 0 +#define MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE 1 +MXGEFW_CMD_GET_RSS_SHARED_INTERRUPT_MASK_OFFSET , MXGEFW_CMD_SET_RSS_SHARED_INTERRUPT_DMA,/* data0, data1 = bus address lsw, msw */
@@ -241,10 +246,14 @@* 0: disable rss. nic does not distribute receive packets. * 1: enable rss. nic distributes receive packets among queues. * data1 = hash type -* 1: IPV4 -* 2: TCP_IPV4 -* 3: IPV4 | TCP_IPV4 +* 1: IPV4 (required by RSS) +* 2: TCP_IPV4 (required by RSS) +* 3: IPV4 | TCP_IPV4 (required by RSS) +* 4: source port */ +#define MXGEFW_RSS_HASH_TYPE_IPV4 0x1 +#define MXGEFW_RSS_HASH_TYPE_TCP_IPV4 0x2 +#define MXGEFW_RSS_HASH_TYPE_SRC_PORT 0x4 MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE,/* Return data = the max. size of the entire headers of a IPv6 TSO packet.
@@ -260,6 +269,8 @@* 0: Linux/FreeBSD style (NIC default) * 1: NDIS/NetBSD style */ +#define MXGEFW_TSO_MODE_LINUX 0 +#define MXGEFW_TSO_MODE_NDIS 1 MXGEFW_CMD_MDIO_READ,/* data0 = dev_addr (PMA/PMD or PCS ...), data1 = register/addr */
@@ -286,6 +297,38 @@/* Return data = NIC memory offset of mcp_vpump_public_global */ MXGEFW_CMD_RESET_VPUMP, /* Resets the VPUMP state */ + + MXGEFW_CMD_SET_RSS_MCP_SLOT_TYPE, +/* data0 = mcp_slot type to use. +* 0 = the default 4B mcp_slot +* 1 = 8B mcp_slot_8 +*/ +#define MXGEFW_RSS_MCP_SLOT_TYPE_MIN 0 +#define MXGEFW_RSS_MCP_SLOT_TYPE_WITH_HASH 1 + + MXGEFW_CMD_SET_THROTTLE_FACTOR, +/* set the throttle factor for ethp_z8e +* data0 = throttle_factor +* throttle_factor = 256 * pcie-raw-speed / tx_speed +* tx_speed = 256 * pcie-raw-speed / throttle_factor +* +* For PCI-E x8: pcie-raw-speed == 16Gb/s +* For PCI-E x4: pcie-raw-speed == 8Gb/s +* +* ex1: throttle_factor == 0x1a0 (416), tx_speed == 1.23GB/s == 9.846 Gb/s +* ex2: throttle_factor == 0x200 (512), tx_speed == 1.0GB/s == 8 Gb/s +* +* with tx_boundary == 2048, max-throttle-factor == 8191 => min-speed == 500Mb/s +* with tx_boundary == 4096, max-throttle-factor == 4095 => min-speed == 1Gb/s +*/ + +MXGEFW_CMD_VPUMP_UP , +/* Allocates VPump Connection, Send Request and Zero copy buffer address tables */ +MXGEFW_CMD_GET_VPUMP_CLK , +/* Get the lanai clock */ + + MXGEFW_CMD_GET_DCA_OFFSET, + /* offset of dca control for WDMAs */ };enum myri10ge_mcp_cmd_status {
@@ -302,7 +345,8 @@MXGEFW_CMD_ERROR_UNALIGNED ,MXGEFW_CMD_ERROR_NO_MDIO ,MXGEFW_CMD_ERROR_XFP_FAILURE , - MXGEFW_CMD_ERROR_XFP_ABSENT +MXGEFW_CMD_ERROR_XFP_ABSENT , + MXGEFW_CMD_ERROR_BAD_PCIE_LINK };#define MXGEFW_OLD_IRQ_DATA_LEN 40
drivers/net/myri10ge/myri10ge_mcp_gen_header.h +14 -25
@@ -1,30 +1,6 @@#ifndef __MYRI10GE_MCP_GEN_HEADER_H__#define __MYRI10GE_MCP_GEN_HEADER_H__ -/* this file define a standard header used as a first entry point to -* exchange information between firmware/driver and driver. The -* header structure can be anywhere in the mcp. It will usually be in -* the .data section, because some fields needs to be initialized at -* compile time. -* The 32bit word at offset MX_HEADER_PTR_OFFSET in the mcp must -* contains the location of the header. -* -* Typically a MCP will start with the following: -* .text -* .space 52 ! to help catch MEMORY_INT errors -* bt start ! jump to real code -* nop -* .long _gen_mcp_header -* -* The source will have a definition like: -* -* mcp_gen_header_t gen_mcp_header = { -* .header_length = sizeof(mcp_gen_header_t), -* .mcp_type = MCP_TYPE_XXX, -* .version = "something $Id: mcp_gen_header.h,v 1.2 2006/05/13 10:04:35 bgoglin Exp $", -* .mcp_globals = (unsigned)&Globals -* }; -*/ #define MCP_HEADER_PTR_OFFSET 0x3c
@@ -32,13 +8,14 @@#define MCP_TYPE_PCIE 0x70636965/* "PCIE" pcie-only MCP */ #define MCP_TYPE_ETH 0x45544820/* "ETH " */ #define MCP_TYPE_MCP0 0x4d435030/* "MCP0" */ +#define MCP_TYPE_DFLT 0x20202020/* " " */ struct mcp_gen_header {/* the first 4 fields are filled at compile time */ unsigned header_length;__be32 mcp_type;char version[128 ]; -unsigned mcp_globals;/* pointer to mcp-type specific structure */ +unsigned mcp_private;/* pointer to mcp-type specific structure */ /* filled by the MCP at run-time */ unsigned sram_size;
@@ -53,6 +30,18 @@* * Never remove any field. Keep everything naturally align. */ + +/* Specifies if the running mcp is mcp0, 1, or 2. */ +unsigned char mcp_index; +unsigned char disable_rabbit; +unsigned char unaligned_tlp; +unsigned char pad1; +unsigned counters_addr; +unsigned copy_block_info;/* for small mcps loaded with "lload -d" */ +unsigned short handoff_id_major;/* must be equal */ +unsigned short handoff_id_caps;/* bitfield: new mcp must have superset */ +unsigned msix_table_addr;/* start address of msix table in firmware */ + /* 8 */ };#endif /* __MYRI10GE_MCP_GEN_HEADER_H__ */
Re: [PATCH 01/16] myri10ge: update firmware headers
Quoted 8 lines · Brice Goglin
Update myri10ge firmware headers.
Signed-off-by Brice Goglin <[email protected]>Signed-off-by Andrew Gallatin <[email protected]>--- drivers/net/myri10ge/myri10ge_mcp.h | 56 ++++++++++++++++++++++--- drivers/net/myri10ge/myri10ge_mcp_gen_header.h | 39 ++++++----------- 2 files changed, 64 insertions(+), 31 deletions(-)
applied 1-16
PATCH 2/16 myri10ge: fix module parameter descriptions
In reply to Brice GoglinRemove useless linebreaks at the end of MODULE_PARM_DESC and fix the description of myri10ge_lro_max_pkts.
--- drivers/net/myri10ge/myri10ge.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-)
drivers/net/myri10ge/myri10ge.c +18 -17
@@ -228,58 +228,58 @@static char *myri10ge_fw_name =NULL ;module_param (myri10ge_fw_name, charp,S_IRUGO |S_IWUSR ); -MODULE_PARM_DESC (myri10ge_fw_name,"Firmware image name\n" ); +MODULE_PARM_DESC (myri10ge_fw_name,"Firmware image name" );static int myri10ge_ecrc_enable =1 ;module_param (myri10ge_ecrc_enable, int,S_IRUGO ); -MODULE_PARM_DESC (myri10ge_ecrc_enable,"Enable Extended CRC on PCI-E\n" ); +MODULE_PARM_DESC (myri10ge_ecrc_enable,"Enable Extended CRC on PCI-E" );static int myri10ge_max_intr_slots =1024 ;module_param (myri10ge_max_intr_slots, int,S_IRUGO ); -MODULE_PARM_DESC (myri10ge_max_intr_slots,"Interrupt queue slots\n" ); +MODULE_PARM_DESC (myri10ge_max_intr_slots,"Interrupt queue slots" );static int myri10ge_small_bytes =-1 ;/* -1 == auto */ module_param (myri10ge_small_bytes, int,S_IRUGO |S_IWUSR ); -MODULE_PARM_DESC (myri10ge_small_bytes,"Threshold of small packets\n" ); +MODULE_PARM_DESC (myri10ge_small_bytes,"Threshold of small packets" );static int myri10ge_msi =1 ;/* enable msi by default */ module_param (myri10ge_msi, int,S_IRUGO |S_IWUSR ); -MODULE_PARM_DESC (myri10ge_msi,"Enable Message Signalled Interrupts\n" ); +MODULE_PARM_DESC (myri10ge_msi,"Enable Message Signalled Interrupts" );static int myri10ge_intr_coal_delay =75 ;module_param (myri10ge_intr_coal_delay, int,S_IRUGO ); -MODULE_PARM_DESC (myri10ge_intr_coal_delay,"Interrupt coalescing delay\n" ); +MODULE_PARM_DESC (myri10ge_intr_coal_delay,"Interrupt coalescing delay" );static int myri10ge_flow_control =1 ;module_param (myri10ge_flow_control, int,S_IRUGO ); -MODULE_PARM_DESC (myri10ge_flow_control,"Pause parameter\n" ); +MODULE_PARM_DESC (myri10ge_flow_control,"Pause parameter" );static int myri10ge_deassert_wait =1 ;module_param (myri10ge_deassert_wait, int,S_IRUGO |S_IWUSR );MODULE_PARM_DESC (myri10ge_deassert_wait, -"Wait when deasserting legacy interrupts\n" ); +"Wait when deasserting legacy interrupts" );static int myri10ge_force_firmware =0 ;module_param (myri10ge_force_firmware, int,S_IRUGO );MODULE_PARM_DESC (myri10ge_force_firmware, -"Force firmware to assume aligned completions\n" ); +"Force firmware to assume aligned completions" );static int myri10ge_initial_mtu =MYRI10GE_MAX_ETHER_MTU -ETH_HLEN ;module_param (myri10ge_initial_mtu, int,S_IRUGO ); -MODULE_PARM_DESC (myri10ge_initial_mtu,"Initial MTU\n" ); +MODULE_PARM_DESC (myri10ge_initial_mtu,"Initial MTU" );static int myri10ge_napi_weight =64 ;module_param (myri10ge_napi_weight, int,S_IRUGO ); -MODULE_PARM_DESC (myri10ge_napi_weight,"Set NAPI weight\n" ); +MODULE_PARM_DESC (myri10ge_napi_weight,"Set NAPI weight" );static int myri10ge_watchdog_timeout =1 ;module_param (myri10ge_watchdog_timeout, int,S_IRUGO ); -MODULE_PARM_DESC (myri10ge_watchdog_timeout,"Set watchdog timeout\n" ); +MODULE_PARM_DESC (myri10ge_watchdog_timeout,"Set watchdog timeout" );static int myri10ge_max_irq_loops =1048576 ;module_param (myri10ge_max_irq_loops, int,S_IRUGO );MODULE_PARM_DESC (myri10ge_max_irq_loops, -"Set stuck legacy IRQ detection threshold\n" ); +"Set stuck legacy IRQ detection threshold" );#define MYRI10GE_MSG_DEFAULT NETIF_MSG_LINK
@@ -289,21 +289,22 @@static int myri10ge_lro =1 ;module_param (myri10ge_lro, int,S_IRUGO ); -MODULE_PARM_DESC (myri10ge_lro,"Enable large receive offload\n" ); +MODULE_PARM_DESC (myri10ge_lro,"Enable large receive offload" );static int myri10ge_lro_max_pkts =MYRI10GE_LRO_MAX_PKTS ;module_param (myri10ge_lro_max_pkts, int,S_IRUGO ); -MODULE_PARM_DESC (myri10ge_lro,"Number of LRO packets to be aggregated\n" ); +MODULE_PARM_DESC (myri10ge_lro_max_pkts, +"Number of LRO packets to be aggregated" );static int myri10ge_fill_thresh =256 ;module_param (myri10ge_fill_thresh, int,S_IRUGO |S_IWUSR ); -MODULE_PARM_DESC (myri10ge_fill_thresh,"Number of empty rx slots allowed\n" ); +MODULE_PARM_DESC (myri10ge_fill_thresh,"Number of empty rx slots allowed" );static int myri10ge_reset_recover =1 ;static int myri10ge_wcfifo =0 ;module_param (myri10ge_wcfifo, int,S_IRUGO ); -MODULE_PARM_DESC (myri10ge_wcfifo,"Enable WC Fifo when WC is enabled\n" ); +MODULE_PARM_DESC (myri10ge_wcfifo,"Enable WC Fifo when WC is enabled" );#define MYRI10GE_FW_OFFSET 1024*1024#define MYRI10GE_HIGHPART_TO_U32 (X ) \
PATCH 3/16 myri10ge: increase and fix handoff timeout
In reply to Brice GoglinIncrease the handoff timeout to 512ms so as to give the aeluros based NICs sufficient time to handoff without relying on the msleep() being sloppy, and accidentally sleeping way longer than the 20ms we specified in 20 separate 1ms sleeps.
Fix typo in the handoff sleep delay, which made it additive, not exponential.
--- drivers/net/myri10ge/myri10ge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/myri10ge/myri10ge.c +2 -2
@@ -682,8 +682,8 @@msleep (1 );mb (); i =0 ; -while (mgp->cmd->data !=MYRI10GE_NO_CONFIRM_DATA && i <20 ) { -msleep (1 ); +while (mgp->cmd->data !=MYRI10GE_NO_CONFIRM_DATA && i <9 ) { +msleep (1 << i); i++; }if (mgp->cmd->data !=MYRI10GE_NO_CONFIRM_DATA ) {
PATCH 4/16 myri10ge: properly align scratch buffers
In reply to Brice GoglinProperly align scratch buffers when making boot commands.
--- drivers/net/myri10ge/myri10ge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/myri10ge/myri10ge.c +2 -2
@@ -443,7 +443,7 @@static void myri10ge_dummy_rdma (struct myri10ge_priv *mgp,int enable) {char __iomem *submit; -__be32 buf[16 ]; + __be32 buf[16] __attribute__ ((__aligned__(8)));u32 dma_low, dma_high;int i;
@@ -613,7 +613,7 @@static int myri10ge_load_firmware (struct myri10ge_priv *mgp) {char __iomem *submit; -__be32 buf[16 ]; + __be32 buf[16] __attribute__ ((__aligned__(8)));u32 dma_low, dma_high, size;int status, i;struct myri10ge_cmd cmd;
PATCH 5/16 myri10ge: don't warn on rx page allocation failure
In reply to Brice GoglinDon't warn when rx page allocations fail, the driver is written to handle failures, and the huge amount of console output generated by the warnings makes a bad situation worse.
--- drivers/net/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/myri10ge/myri10ge.c +1 -1
@@ -956,7 +956,7 @@ }else {/* we need a new page */ page = -alloc_pages (GFP_ATOMIC | __GFP_COMP, +alloc_pages (GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN,MYRI10GE_ALLOC_ORDER );if (unlikely (page ==NULL )) {if (rx->fill_cnt - rx->cnt <16 )
PATCH 6/16 myri10ge: report FIBER in ethtool for XFP based NIC
In reply to Brice GoglinMake ethtool report FIBER for XFP based NIC's port type. Don't bother to poke around and try to find out what is in the XFP cage, since Linux does not have separate media types for -SR -LR, etc.
--- drivers/net/myri10ge/myri10ge.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
drivers/net/myri10ge/myri10ge.c +35 -0
@@ -205,6 +205,7 @@int pause;char *fw_name;char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE ]; +char *product_code_string;char fw_version[128 ];int fw_ver_major;int fw_ver_minor;
@@ -421,6 +422,10 @@ ptr +=1 ; } } +if (memcmp (ptr,"PC=" ,3 ) ==0 ) { + ptr +=3 ; + mgp->product_code_string = ptr; + }if (memcmp ((const void *)ptr,"SN=" ,3 ) ==0 ) { ptr +=3 ; mgp->serial_number =simple_strtoul (ptr, &ptr,10 );
@@ -1304,9 +1309,39 @@static int myri10ge_get_settings (struct net_device *netdev,struct ethtool_cmd *cmd) { +struct myri10ge_priv *mgp =netdev_priv (netdev); +char *ptr; +int i; + cmd->autoneg =AUTONEG_DISABLE ; cmd->speed =SPEED_10000 ; cmd->duplex =DUPLEX_FULL ; + +/* +* parse the product code to deterimine the interface type +* (CX4, XFP, Quad Ribbon Fiber) by looking at the character +* after the 3rd dash in the driver's cached copy of the +* EEPROM's product code string. +*/ + ptr = mgp->product_code_string; +if (ptr ==NULL ) { +printk (KERN_ERR "myri10ge: %s: Missing product code\n" , + netdev->name); +return 0 ; + } +for (i =0 ; i <3 ; i++, ptr++) { + ptr =strchr (ptr,'-' ); +if (ptr ==NULL ) { +printk (KERN_ERR "myri10ge: %s: Invalid product " +"code %s\n" , netdev->name, + mgp->product_code_string); +return 0 ; + } + } +if (*ptr =='R' || *ptr =='Q' ) { +/* We've found either an XFP or quad ribbon fiber */ + cmd->port =PORT_FIBRE ; + }return 0 ; }
PATCH 7/16 myri10ge: add barrier in myri10ge_send_cmd
In reply to Brice GoglinAdd a barrier() in the usleep() loop in myri10ge_send_cmd(). Without the barrier, some mips machine never notices that the firmware has DMA'ed the response.
--- drivers/net/myri10ge/myri10ge.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
Index: linux-2.6/drivers/net/myri10ge/myri10ge.c
===================================================================
--- linux-2.6.orig/drivers/net/myri10ge/myri10ge.c 2008-05-09
00:04:48.000000000 +0200
+++ linux-2.6/drivers/net/myri10ge/myri10ge.c 2008-05-09
00:05:30.000000000 +0200
@@ -361,8 +361,10 @@
for (sleep_total = 0;
sleep_total < 1000
&& response->result == htonl(MYRI10GE_NO_RESPONSE_RESULT);
- sleep_total += 10)
+ sleep_total += 10) {
udelay(10);
+ mb();
+ }
} else {
/* use msleep for most command */
for (sleep_total = 0;PATCH 8/16 myri10ge: trivial formatting fix
In reply to Brice GoglinAdd some blank lines to uniformize the code and match the upstream code.
--- drivers/net/myri10ge/myri10ge.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/myri10ge/myri10ge.c +4 -1
@@ -1328,7 +1328,7 @@ ptr = mgp->product_code_string;if (ptr ==NULL ) {printk (KERN_ERR "myri10ge: %s: Missing product code\n" , - netdev->name); + netdev->name);return 0 ; }for (i =0 ; i <3 ; i++, ptr++) {
@@ -1362,6 +1362,7 @@ myri10ge_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal) { struct myri10ge_priv *mgp = netdev_priv(netdev); + coal->rx_coalesce_usecs = mgp->intr_coal_delay;return 0 ; }
@@ -1421,6 +1422,7 @@static u32 myri10ge_get_rx_csum (struct net_device *netdev) {struct myri10ge_priv *mgp =netdev_priv (netdev); +if (mgp->csum_flag)return 1 ;else
@@ -1430,6 +1432,7 @@static int myri10ge_set_rx_csum (struct net_device *netdev,u32 csum_enabled) {struct myri10ge_priv *mgp =netdev_priv (netdev); +if (csum_enabled) mgp->csum_flag =MXGEFW_FLAGS_CKSUM ;else
PATCH 9/16 myri10ge: fix potential infinite loop in enable_ecrc
In reply to Brice GoglinFix another potential for an infinite loop while looking for the root port in myri10ge_enable_ecrc().
--- drivers/net/myri10ge/myri10ge.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/myri10ge/myri10ge.c +3 -2
@@ -2657,13 +2657,14 @@ ext_type = (val &PCI_EXP_FLAGS_TYPE ) >>4 ;if (ext_type !=PCI_EXP_TYPE_ROOT_PORT ) {if (myri10ge_ecrc_enable >1 ) { -struct pci_dev *old_bridge = bridge; +struct pci_dev *prev_bridge, *old_bridge = bridge;/* Walk the hierarchy up to the root port * where ECRC has to be enabled */ do { + prev_bridge = bridge; bridge = bridge->bus->self; - if (!bridge) { + if (!bridge || prev_bridge == bridge) { dev_err(dev, "Failed to find root port" " to force ECRC\n");
PATCH 10/16 myri10ge: move data structures into a single slice
In reply to Brice GoglinTo prepare and simplify multislice rx support, add a single slice structure and move some fields in there.
No functional change yet.
--- drivers/net/myri10ge/myri10ge.c | 594 +++++++++++++++++++++------------------- 1 file changed, 316 insertions(+), 278 deletions(-)
drivers/net/myri10ge/myri10ge.c +316 -278
@@ -144,11 +144,13 @@char *req_bytes;struct myri10ge_tx_buffer_state *info;int mask;/* number of transmit slots -1 */ -int boundary;/* boundary transmits cannot cross */ int req____cacheline_aligned ;/* transmit slots submitted */ int pkt_start;/* packets started */ +int stop_queue; +int linearized;int done____cacheline_aligned ;/* transmit slots completed */ int pkt_done;/* packets completed */ +int wake_queue; };struct myri10ge_rx_done {
@@ -160,29 +162,49 @@struct net_lro_desc lro_desc[MYRI10GE_MAX_LRO_DESCRIPTORS ]; }; -struct myri10ge_priv { -int running;/* running? */ -int csum_flag;/* rx_csums? */ +struct myri10ge_slice_netstats { +unsigned long rx_packets; +unsigned long tx_packets; +unsigned long rx_bytes; +unsigned long tx_bytes; +unsigned long rx_dropped; +unsigned long tx_dropped; +}; + +struct myri10ge_slice_state {struct myri10ge_tx_buf tx;/* transmit ring */ struct myri10ge_rx_buf rx_small;struct myri10ge_rx_buf rx_big;struct myri10ge_rx_done rx_done; +struct net_device *dev; +struct napi_struct napi; +struct myri10ge_priv *mgp; +struct myri10ge_slice_netstats stats; +__be32 __iomem *irq_claim; +struct mcp_irq_data *fw_stats; +dma_addr_t fw_stats_bus; +int watchdog_tx_done; +int watchdog_tx_req; +}; + +struct myri10ge_priv { +struct myri10ge_slice_state ss; +int tx_boundary;/* boundary transmits cannot cross */ +int running;/* running? */ +int csum_flag;/* rx_csums? */ int small_bytes;int big_bytes;struct net_device *dev; -struct napi_struct napi;struct net_device_stats stats; +spinlock_t stats_lock;u8 __iomem *sram;int sram_size;unsigned long board_span;unsigned long iomem_base; -__be32 __iomem *irq_claim;__be32 __iomem *irq_deassert;char *mac_addr_string;struct mcp_cmd_response *cmd;dma_addr_t cmd_bus; -struct mcp_irq_data *fw_stats; -dma_addr_t fw_stats_bus;struct pci_dev *pdev;int msi_enabled;u32 link_state;
@@ -191,17 +213,12 @@__be32 __iomem *intr_coal_delay_ptr;int mtrr;int wc_enabled; -int wake_queue; -int stop_queue;int down_cnt;wait_queue_head_t down_wq;struct work_struct watchdog_work;struct timer_list watchdog_timer; -int watchdog_tx_done; -int watchdog_tx_req; -int watchdog_pause;int watchdog_resets; -int tx_linearized; +int watchdog_pause;int pause;char *fw_name;char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE ];
@@ -643,7 +660,7 @@ }dev_info (&mgp->pdev->dev,"Successfully adopted running firmware\n" ); -if (mgp->tx.boundary ==4096 ) { +if (mgp->tx_boundary ==4096 ) {dev_warn (&mgp->pdev->dev,"Using firmware currently running on NIC" ". For optimal\n" );
@@ -654,7 +671,7 @@ } mgp->fw_name ="adopted" ; - mgp->tx.boundary =2048 ; + mgp->tx_boundary =2048 ;return status; }
@@ -780,7 +797,7 @@* transfers took to complete. */ - len = mgp->tx.boundary; + len = mgp->tx_boundary; cmd.data0 =MYRI10GE_LOWPART_TO_U32 (dmatest_bus); cmd.data1 =MYRI10GE_HIGHPART_TO_U32 (dmatest_bus);
@@ -842,17 +859,17 @@/* Now exchange information about interrupts */ - bytes = myri10ge_max_intr_slots *sizeof (*mgp->rx_done.entry); -memset (mgp->rx_done.entry,0 , bytes); + bytes = myri10ge_max_intr_slots *sizeof (*mgp->ss.rx_done.entry); +memset (mgp->ss.rx_done.entry,0 , bytes); cmd.data0 = (u32 ) bytes; status =myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_INTRQ_SIZE , &cmd,0 ); - cmd.data0 =MYRI10GE_LOWPART_TO_U32 (mgp->rx_done.bus); - cmd.data1 =MYRI10GE_HIGHPART_TO_U32 (mgp->rx_done.bus); + cmd.data0 =MYRI10GE_LOWPART_TO_U32 (mgp->ss.rx_done.bus); + cmd.data1 =MYRI10GE_HIGHPART_TO_U32 (mgp->ss.rx_done.bus); status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_INTRQ_DMA , &cmd,0 ); status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_IRQ_ACK_OFFSET , &cmd,0 ); - mgp->irq_claim = (__iomem __be32 *) (mgp->sram + cmd.data0); + mgp->ss.irq_claim = (__iomem __be32 *) (mgp->sram + cmd.data0); status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET , &cmd,0 ); mgp->irq_deassert = (__iomem __be32 *) (mgp->sram + cmd.data0);
@@ -866,17 +883,17 @@ }put_be32 (htonl (mgp->intr_coal_delay), mgp->intr_coal_delay_ptr); -memset (mgp->rx_done.entry,0 , bytes); +memset (mgp->ss.rx_done.entry,0 , bytes);/* reset mcp/driver shared state back to 0 */ - mgp->tx.req =0 ; - mgp->tx.done =0 ; - mgp->tx.pkt_start =0 ; - mgp->tx.pkt_done =0 ; - mgp->rx_big.cnt =0 ; - mgp->rx_small.cnt =0 ; - mgp->rx_done.idx =0 ; - mgp->rx_done.cnt =0 ; + mgp->ss.tx.req =0 ; + mgp->ss.tx.done =0 ; + mgp->ss.tx.pkt_start =0 ; + mgp->ss.tx.pkt_done =0 ; + mgp->ss.rx_big.cnt =0 ; + mgp->ss.rx_small.cnt =0 ; + mgp->ss.rx_done.idx =0 ; + mgp->ss.rx_done.cnt =0 ; mgp->link_changes =0 ; status =myri10ge_update_mac_address (mgp, mgp->dev->dev_addr);myri10ge_change_pause (mgp, mgp->pause);
@@ -1028,9 +1045,10 @@* page into an skb */ static inline int -myri10ge_rx_done (struct myri10ge_priv *mgp,struct myri10ge_rx_buf *rx, +myri10ge_rx_done (struct myri10ge_slice_state *ss,struct myri10ge_rx_buf *rx,int bytes,int len,__wsum csum) { +struct myri10ge_priv *mgp = ss->mgp;struct sk_buff *skb;struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME ];int i, idx, hlen, remainder;
@@ -1060,11 +1078,10 @@ rx_frags[0 ].page_offset +=MXGEFW_PAD ; rx_frags[0 ].size -=MXGEFW_PAD ; len -=MXGEFW_PAD ; -lro_receive_frags (&mgp->rx_done.lro_mgr, rx_frags, +lro_receive_frags (&ss->rx_done.lro_mgr, rx_frags, len, len, -/* opaque, will come back in get_frag_header */ - (void *)(__force unsigned long )csum, - csum); +/* opaque, will come back in get_frag_header */ + (void *)(__force unsigned long )csum, csum);return 1 ; }
@@ -1104,10 +1121,11 @@return 1 ; } -static inline void myri10ge_tx_done (struct myri10ge_priv *mgp,int mcp_index) +static inline void +myri10ge_tx_done (struct myri10ge_slice_state *ss,int mcp_index) { -struct pci_dev *pdev = mgp->pdev; -struct myri10ge_tx_buf *tx = &mgp->tx; +struct pci_dev *pdev = ss->mgp->pdev; +struct myri10ge_tx_buf *tx = &ss->tx;struct sk_buff *skb;int idx, len;
@@ -1125,8 +1143,8 @@ len =pci_unmap_len (&tx->info[idx], len);pci_unmap_len_set (&tx->info[idx], len,0 );if (skb) { - mgp->stats.tx_bytes += skb->len; - mgp->stats.tx_packets++; + ss->stats.tx_bytes += skb->len; + ss->stats.tx_packets++;dev_kfree_skb_irq (skb);if (len) pci_unmap_single(pdev,
@@ -1142,16 +1160,18 @@ } }/* start the queue if we've stopped it */ -if (netif_queue_stopped (mgp->dev) +if (netif_queue_stopped (ss->dev) && tx->req - tx->done < (tx->mask >>1 )) { - mgp->wake_queue++; -netif_wake_queue (mgp->dev); + tx->wake_queue++; +netif_wake_queue (ss->dev); } } -static inline int myri10ge_clean_rx_done (struct myri10ge_priv *mgp,int budget) +static inline int +myri10ge_clean_rx_done (struct myri10ge_slice_state *ss,int budget) { -struct myri10ge_rx_done *rx_done = &mgp->rx_done; +struct myri10ge_rx_done *rx_done = &ss->rx_done; +struct myri10ge_priv *mgp = ss->mgp;unsigned long rx_bytes =0 ;unsigned long rx_packets =0 ;unsigned long rx_ok;
@@ -1167,11 +1187,11 @@ rx_done->entry[idx].length =0 ; checksum =csum_unfold (rx_done->entry[idx].checksum);if (length <= mgp->small_bytes) - rx_ok =myri10ge_rx_done (mgp, &mgp->rx_small, + rx_ok =myri10ge_rx_done (ss, &ss->rx_small, mgp->small_bytes, length, checksum);else - rx_ok =myri10ge_rx_done (mgp, &mgp->rx_big, + rx_ok =myri10ge_rx_done (ss, &ss->rx_big, mgp->big_bytes, length, checksum); rx_packets += rx_ok;
@@ -1182,25 +1202,25 @@ } rx_done->idx = idx; rx_done->cnt = cnt; - mgp->stats.rx_packets += rx_packets; - mgp->stats.rx_bytes += rx_bytes; + ss->stats.rx_packets += rx_packets; + ss->stats.rx_bytes += rx_bytes;if (myri10ge_lro)lro_flush_all (&rx_done->lro_mgr);/* restock receive rings if needed */ -if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt < myri10ge_fill_thresh) -myri10ge_alloc_rx_pages (mgp, &mgp->rx_small, +if (ss->rx_small.fill_cnt - ss->rx_small.cnt < myri10ge_fill_thresh) +myri10ge_alloc_rx_pages (mgp, &ss->rx_small, mgp->small_bytes +MXGEFW_PAD ,0 ); -if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt < myri10ge_fill_thresh) -myri10ge_alloc_rx_pages (mgp, &mgp->rx_big, mgp->big_bytes,0 ); +if (ss->rx_big.fill_cnt - ss->rx_big.cnt < myri10ge_fill_thresh) +myri10ge_alloc_rx_pages (mgp, &ss->rx_big, mgp->big_bytes,0 );return work_done; }static inline void myri10ge_check_statblock (struct myri10ge_priv *mgp) { -struct mcp_irq_data *stats = mgp->fw_stats; +struct mcp_irq_data *stats = mgp->ss.fw_stats;if (unlikely (stats->stats_updated)) {unsigned link_up =ntohl (stats->link_up);
@@ -1227,9 +1247,9 @@ } }if (mgp->rdma_tags_available != -ntohl (mgp->fw_stats->rdma_tags_available)) { +ntohl (stats->rdma_tags_available)) { mgp->rdma_tags_available = -ntohl (mgp->fw_stats->rdma_tags_available); +ntohl (stats->rdma_tags_available);printk (KERN_WARNING "myri10ge: %s: RDMA timed out! " "%d tags left\n" , mgp->dev->name, mgp->rdma_tags_available);
@@ -1242,26 +1262,27 @@static int myri10ge_poll (struct napi_struct *napi,int budget) { -struct myri10ge_priv *mgp = - container_of(napi, struct myri10ge_priv, napi); -struct net_device *netdev = mgp->dev; +struct myri10ge_slice_state *ss = + container_of(napi, struct myri10ge_slice_state, napi); +struct net_device *netdev = ss->mgp->dev;int work_done;/* process as many rx events as NAPI will allow */ - work_done =myri10ge_clean_rx_done (mgp, budget); + work_done =myri10ge_clean_rx_done (ss, budget);if (work_done < budget) {netif_rx_complete (netdev, napi); -put_be32 (htonl (3 ), mgp->irq_claim); +put_be32 (htonl (3 ), ss->irq_claim); }return work_done; }static irqreturn_t myri10ge_intr (int irq,void *arg) { -struct myri10ge_priv *mgp = arg; -struct mcp_irq_data *stats = mgp->fw_stats; -struct myri10ge_tx_buf *tx = &mgp->tx; +struct myri10ge_slice_state *ss = arg; +struct myri10ge_priv *mgp = ss->mgp; +struct mcp_irq_data *stats = ss->fw_stats; +struct myri10ge_tx_buf *tx = &ss->tx;u32 send_done_count;int i;
@@ -1272,7 +1293,7 @@/* low bit indicates receives are present, so schedule * napi poll handler */ if (stats->valid &1 ) -netif_rx_schedule (mgp->dev, &mgp->napi); +netif_rx_schedule (ss->dev, &ss->napi);if (!mgp->msi_enabled) {put_be32 (0 , mgp->irq_deassert);
@@ -1289,7 +1310,7 @@/* check for transmit completes and receives */ send_done_count =ntohl (stats->send_done_count);if (send_done_count != tx->pkt_done) -myri10ge_tx_done (mgp, (int )send_done_count); +myri10ge_tx_done (ss, (int )send_done_count);if (unlikely (i > myri10ge_max_irq_loops)) {printk (KERN_WARNING "myri10ge: %s: irq stuck?\n" , mgp->dev->name);
@@ -1304,7 +1325,7 @@myri10ge_check_statblock (mgp); -put_be32 (htonl (3 ), mgp->irq_claim +1 ); +put_be32 (htonl (3 ), ss->irq_claim +1 );return (IRQ_HANDLED ); }
@@ -1409,10 +1430,10 @@ {struct myri10ge_priv *mgp =netdev_priv (netdev); - ring->rx_mini_max_pending = mgp->rx_small.mask +1 ; - ring->rx_max_pending = mgp->rx_big.mask +1 ; + ring->rx_mini_max_pending = mgp->ss.rx_small.mask +1 ; + ring->rx_max_pending = mgp->ss.rx_big.mask +1 ; ring->rx_jumbo_max_pending =0 ; - ring->tx_max_pending = mgp->rx_small.mask +1 ; + ring->tx_max_pending = mgp->ss.rx_small.mask +1 ; ring->rx_mini_pending = ring->rx_mini_max_pending; ring->rx_pending = ring->rx_max_pending; ring->rx_jumbo_pending = ring->rx_jumbo_max_pending;
@@ -1452,7 +1473,7 @@return 0 ; } -static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN ] = { +static const char myri10ge_gstrings_main_stats[][ETH_GSTRING_LEN ] = {"rx_packets" ,"tx_packets" ,"rx_bytes" ,"tx_bytes" ,"rx_errors" ,"tx_errors" ,"rx_dropped" ,"tx_dropped" ,"multicast" ,"collisions" ,"rx_length_errors" ,"rx_over_errors" ,"rx_crc_errors" ,
@@ -1462,28 +1483,39 @@/* device-specific stats */ "tx_boundary" ,"WC" ,"irq" ,"MSI" ,"read_dma_bw_MBs" ,"write_dma_bw_MBs" ,"read_write_dma_bw_MBs" , -"serial_number" ,"tx_pkt_start" ,"tx_pkt_done" , -"tx_req" ,"tx_done" ,"rx_small_cnt" ,"rx_big_cnt" , -"wake_queue" ,"stop_queue" ,"watchdog_resets" ,"tx_linearized" , +"serial_number" ,"watchdog_resets" ,"link_changes" ,"link_up" ,"dropped_link_overflow" ,"dropped_link_error_or_filtered" ,"dropped_pause" ,"dropped_bad_phy" ,"dropped_bad_crc32" ,"dropped_unicast_filtered" ,"dropped_multicast_filtered" ,"dropped_runt" ,"dropped_overrun" ,"dropped_no_small_buffer" , -"dropped_no_big_buffer" ,"LRO aggregated" ,"LRO flushed" , +"dropped_no_big_buffer" +}; + +static const char myri10ge_gstrings_slice_stats[][ETH_GSTRING_LEN ] = { +"----------- slice ---------" , +"tx_pkt_start" ,"tx_pkt_done" ,"tx_req" ,"tx_done" , +"rx_small_cnt" ,"rx_big_cnt" , +"wake_queue" ,"stop_queue" ,"tx_linearized" ,"LRO aggregated" , +"LRO flushed" ,"LRO avg aggr" ,"LRO no_desc" };#define MYRI10GE_NET_STATS_LEN 21 -#define MYRI10GE_STATS_LEN ARRAY_SIZE(myri10ge_gstrings_stats) +#define MYRI10GE_MAIN_STATS_LEN ARRAY_SIZE(myri10ge_gstrings_main_stats) +#define MYRI10GE_SLICE_STATS_LEN ARRAY_SIZE(myri10ge_gstrings_slice_stats)static void myri10ge_get_strings (struct net_device *netdev,u32 stringset,u8 * data) {switch (stringset) {case ETH_SS_STATS : -memcpy (data, *myri10ge_gstrings_stats, -sizeof (myri10ge_gstrings_stats)); +memcpy (data, *myri10ge_gstrings_main_stats, +sizeof (myri10ge_gstrings_main_stats)); + data +=sizeof (myri10ge_gstrings_main_stats); +memcpy (data, *myri10ge_gstrings_slice_stats, +sizeof (myri10ge_gstrings_slice_stats)); + data +=sizeof (myri10ge_gstrings_slice_stats);break ; } }
@@ -1492,7 +1524,7 @@ {switch (sset) {case ETH_SS_STATS : -return MYRI10GE_STATS_LEN ; +return MYRI10GE_MAIN_STATS_LEN +MYRI10GE_SLICE_STATS_LEN ;default :return -EOPNOTSUPP ; }
@@ -1503,12 +1535,13 @@ struct ethtool_stats *stats, u64 * data) { struct myri10ge_priv *mgp = netdev_priv(netdev); +struct myri10ge_slice_state *ss;int i;for (i =0 ; i <MYRI10GE_NET_STATS_LEN ; i++) data[i] = ((unsigned long *)&mgp->stats)[i]; - data[i++] = (unsigned int )mgp->tx.boundary; + data[i++] = (unsigned int )mgp->tx_boundary; data[i++] = (unsigned int )mgp->wc_enabled; data[i++] = (unsigned int )mgp->pdev->irq; data[i++] = (unsigned int )mgp->msi_enabled;
@@ -1516,40 +1549,44 @@ data[i++] = (unsigned int )mgp->write_dma; data[i++] = (unsigned int )mgp->read_write_dma; data[i++] = (unsigned int )mgp->serial_number; - data[i++] = (unsigned int )mgp->tx.pkt_start; - data[i++] = (unsigned int )mgp->tx.pkt_done; - data[i++] = (unsigned int )mgp->tx.req; - data[i++] = (unsigned int )mgp->tx.done; - data[i++] = (unsigned int )mgp->rx_small.cnt; - data[i++] = (unsigned int )mgp->rx_big.cnt; - data[i++] = (unsigned int )mgp->wake_queue; - data[i++] = (unsigned int )mgp->stop_queue; data[i++] = (unsigned int )mgp->watchdog_resets; - data[i++] = (unsigned int )mgp->tx_linearized; data[i++] = (unsigned int )mgp->link_changes; - data[i++] = (unsigned int )ntohl (mgp->fw_stats->link_up); - data[i++] = (unsigned int )ntohl (mgp->fw_stats->dropped_link_overflow); - data[i++] = - (unsigned int )ntohl (mgp->fw_stats->dropped_link_error_or_filtered); - data[i++] = (unsigned int )ntohl (mgp->fw_stats->dropped_pause); - data[i++] = (unsigned int )ntohl (mgp->fw_stats->dropped_bad_phy); - data[i++] = (unsigned int )ntohl (mgp->fw_stats->dropped_bad_crc32); + +/* firmware stats are useful only in the first slice */ + ss = &mgp->ss; + data[i++] = (unsigned int )ntohl (ss->fw_stats->link_up); + data[i++] = (unsigned int )ntohl (ss->fw_stats->dropped_link_overflow); data[i++] = - (unsigned int )ntohl (mgp->fw_stats->dropped_unicast_filtered); + (unsigned int )ntohl (ss->fw_stats->dropped_link_error_or_filtered); + data[i++] = (unsigned int )ntohl (ss->fw_stats->dropped_pause); + data[i++] = (unsigned int )ntohl (ss->fw_stats->dropped_bad_phy); + data[i++] = (unsigned int )ntohl (ss->fw_stats->dropped_bad_crc32); + data[i++] = (unsigned int )ntohl (ss->fw_stats->dropped_unicast_filtered); data[i++] = - (unsigned int )ntohl (mgp->fw_stats->dropped_multicast_filtered); - data[i++] = (unsigned int )ntohl (mgp->fw_stats->dropped_runt); - data[i++] = (unsigned int )ntohl (mgp->fw_stats->dropped_overrun); - data[i++] = (unsigned int )ntohl (mgp->fw_stats->dropped_no_small_buffer); - data[i++] = (unsigned int )ntohl (mgp->fw_stats->dropped_no_big_buffer); - data[i++] = mgp->rx_done.lro_mgr.stats.aggregated; - data[i++] = mgp->rx_done.lro_mgr.stats.flushed; -if (mgp->rx_done.lro_mgr.stats.flushed) - data[i++] = mgp->rx_done.lro_mgr.stats.aggregated / - mgp->rx_done.lro_mgr.stats.flushed; + (unsigned int )ntohl (ss->fw_stats->dropped_multicast_filtered); + data[i++] = (unsigned int )ntohl (ss->fw_stats->dropped_runt); + data[i++] = (unsigned int )ntohl (ss->fw_stats->dropped_overrun); + data[i++] = (unsigned int )ntohl (ss->fw_stats->dropped_no_small_buffer); + data[i++] = (unsigned int )ntohl (ss->fw_stats->dropped_no_big_buffer); + + data[i++] =0 ; + data[i++] = (unsigned int )ss->tx.pkt_start; + data[i++] = (unsigned int )ss->tx.pkt_done; + data[i++] = (unsigned int )ss->tx.req; + data[i++] = (unsigned int )ss->tx.done; + data[i++] = (unsigned int )ss->rx_small.cnt; + data[i++] = (unsigned int )ss->rx_big.cnt; + data[i++] = (unsigned int )ss->tx.wake_queue; + data[i++] = (unsigned int )ss->tx.stop_queue; + data[i++] = (unsigned int )ss->tx.linearized; + data[i++] = ss->rx_done.lro_mgr.stats.aggregated; + data[i++] = ss->rx_done.lro_mgr.stats.flushed; +if (ss->rx_done.lro_mgr.stats.flushed) + data[i++] = ss->rx_done.lro_mgr.stats.aggregated / + ss->rx_done.lro_mgr.stats.flushed;else data[i++] =0 ; - data[i++] = mgp->rx_done.lro_mgr.stats.no_desc; + data[i++] = ss->rx_done.lro_mgr.stats.no_desc; }static void myri10ge_set_msglevel (struct net_device *netdev,u32 value)
@@ -1585,19 +1622,17 @@ .get_msglevel = myri10ge_get_msglevel }; -static int myri10ge_allocate_rings (struct net_device *dev) +static int myri10ge_allocate_rings (struct myri10ge_slice_state *ss) { -struct myri10ge_priv *mgp; +struct myri10ge_priv *mgp = ss->mgp;struct myri10ge_cmd cmd; +struct net_device *dev = mgp->dev;int tx_ring_size, rx_ring_size;int tx_ring_entries, rx_ring_entries;int i, status;size_t bytes; - mgp =netdev_priv (dev); -/* get ring sizes */ - status =myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_SEND_RING_SIZE , &cmd,0 ); tx_ring_size = cmd.data0; status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_RX_RING_SIZE , &cmd,0 );
@@ -1607,144 +1642,142 @@ tx_ring_entries = tx_ring_size /sizeof (struct mcp_kreq_ether_send ); rx_ring_entries = rx_ring_size /sizeof (struct mcp_dma_addr ); - mgp->tx.mask = tx_ring_entries -1 ; - mgp->rx_small.mask = mgp->rx_big.mask = rx_ring_entries -1 ; + ss->tx.mask = tx_ring_entries -1 ; + ss->rx_small.mask = ss->rx_big.mask = rx_ring_entries -1 ; status = -ENOMEM ;/* allocate the host shadow rings */ bytes =8 + (MYRI10GE_MAX_SEND_DESC_TSO +4 ) - *sizeof (*mgp->tx.req_list); - mgp->tx.req_bytes =kzalloc (bytes,GFP_KERNEL ); -if (mgp->tx.req_bytes ==NULL ) + *sizeof (*ss->tx.req_list); + ss->tx.req_bytes =kzalloc (bytes,GFP_KERNEL ); +if (ss->tx.req_bytes ==NULL ) goto abort_with_nothing;/* ensure req_list entries are aligned to 8 bytes */ - mgp->tx.req_list = (struct mcp_kreq_ether_send *) -ALIGN ((unsigned long )mgp->tx.req_bytes,8 ); + ss->tx.req_list = (struct mcp_kreq_ether_send *) +ALIGN ((unsigned long )ss->tx.req_bytes,8 ); - bytes = rx_ring_entries *sizeof (*mgp->rx_small.shadow); - mgp->rx_small.shadow =kzalloc (bytes,GFP_KERNEL ); -if (mgp->rx_small.shadow ==NULL ) + bytes = rx_ring_entries *sizeof (*ss->rx_small.shadow); + ss->rx_small.shadow =kzalloc (bytes,GFP_KERNEL ); +if (ss->rx_small.shadow ==NULL ) goto abort_with_tx_req_bytes; - bytes = rx_ring_entries *sizeof (*mgp->rx_big.shadow); - mgp->rx_big.shadow =kzalloc (bytes,GFP_KERNEL ); -if (mgp->rx_big.shadow ==NULL ) + bytes = rx_ring_entries *sizeof (*ss->rx_big.shadow); + ss->rx_big.shadow =kzalloc (bytes,GFP_KERNEL ); +if (ss->rx_big.shadow ==NULL ) goto abort_with_rx_small_shadow;/* allocate the host info rings */ - bytes = tx_ring_entries *sizeof (*mgp->tx.info); - mgp->tx.info =kzalloc (bytes,GFP_KERNEL ); -if (mgp->tx.info ==NULL ) + bytes = tx_ring_entries *sizeof (*ss->tx.info); + ss->tx.info =kzalloc (bytes,GFP_KERNEL ); +if (ss->tx.info ==NULL ) goto abort_with_rx_big_shadow; - bytes = rx_ring_entries *sizeof (*mgp->rx_small.info); - mgp->rx_small.info =kzalloc (bytes,GFP_KERNEL ); -if (mgp->rx_small.info ==NULL ) + bytes = rx_ring_entries *sizeof (*ss->rx_small.info); + ss->rx_small.info =kzalloc (bytes,GFP_KERNEL ); +if (ss->rx_small.info ==NULL ) goto abort_with_tx_info; - bytes = rx_ring_entries *sizeof (*mgp->rx_big.info); - mgp->rx_big.info =kzalloc (bytes,GFP_KERNEL ); -if (mgp->rx_big.info ==NULL ) + bytes = rx_ring_entries *sizeof (*ss->rx_big.info); + ss->rx_big.info =kzalloc (bytes,GFP_KERNEL ); +if (ss->rx_big.info ==NULL ) goto abort_with_rx_small_info;/* Fill the receive rings */ - mgp->rx_big.cnt =0 ; - mgp->rx_small.cnt =0 ; - mgp->rx_big.fill_cnt =0 ; - mgp->rx_small.fill_cnt =0 ; - mgp->rx_small.page_offset =MYRI10GE_ALLOC_SIZE ; - mgp->rx_big.page_offset =MYRI10GE_ALLOC_SIZE ; - mgp->rx_small.watchdog_needed =0 ; - mgp->rx_big.watchdog_needed =0 ; -myri10ge_alloc_rx_pages (mgp, &mgp->rx_small, + ss->rx_big.cnt =0 ; + ss->rx_small.cnt =0 ; + ss->rx_big.fill_cnt =0 ; + ss->rx_small.fill_cnt =0 ; + ss->rx_small.page_offset =MYRI10GE_ALLOC_SIZE ; + ss->rx_big.page_offset =MYRI10GE_ALLOC_SIZE ; + ss->rx_small.watchdog_needed =0 ; + ss->rx_big.watchdog_needed =0 ; +myri10ge_alloc_rx_pages (mgp, &ss->rx_small, mgp->small_bytes +MXGEFW_PAD ,0 ); -if (mgp->rx_small.fill_cnt < mgp->rx_small.mask +1 ) { +if (ss->rx_small.fill_cnt < ss->rx_small.mask +1 ) {printk (KERN_ERR "myri10ge: %s: alloced only %d small bufs\n" , - dev->name, mgp->rx_small.fill_cnt); + dev->name, ss->rx_small.fill_cnt); goto abort_with_rx_small_ring; } -myri10ge_alloc_rx_pages (mgp, &mgp->rx_big, mgp->big_bytes,0 ); -if (mgp->rx_big.fill_cnt < mgp->rx_big.mask +1 ) { +myri10ge_alloc_rx_pages (mgp, &ss->rx_big, mgp->big_bytes,0 ); +if (ss->rx_big.fill_cnt < ss->rx_big.mask +1 ) {printk (KERN_ERR "myri10ge: %s: alloced only %d big bufs\n" , - dev->name, mgp->rx_big.fill_cnt); + dev->name, ss->rx_big.fill_cnt); goto abort_with_rx_big_ring; }return 0 ; abort_with_rx_big_ring: -for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) { -int idx = i & mgp->rx_big.mask; -myri10ge_unmap_rx_page (mgp->pdev, &mgp->rx_big.info[idx], +for (i = ss->rx_big.cnt; i < ss->rx_big.fill_cnt; i++) { +int idx = i & ss->rx_big.mask; +myri10ge_unmap_rx_page (mgp->pdev, &ss->rx_big.info[idx], mgp->big_bytes); -put_page (mgp->rx_big.info[idx].page); +put_page (ss->rx_big.info[idx].page); } abort_with_rx_small_ring: -for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) { -int idx = i & mgp->rx_small.mask; -myri10ge_unmap_rx_page (mgp->pdev, &mgp->rx_small.info[idx], +for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) { +int idx = i & ss->rx_small.mask; +myri10ge_unmap_rx_page (mgp->pdev, &ss->rx_small.info[idx], mgp->small_bytes +MXGEFW_PAD ); -put_page (mgp->rx_small.info[idx].page); +put_page (ss->rx_small.info[idx].page); } -kfree (mgp->rx_big.info); +kfree (ss->rx_big.info); abort_with_rx_small_info: -kfree (mgp->rx_small.info); +kfree (ss->rx_small.info); abort_with_tx_info: -kfree (mgp->tx.info); +kfree (ss->tx.info); abort_with_rx_big_shadow: -kfree (mgp->rx_big.shadow); +kfree (ss->rx_big.shadow); abort_with_rx_small_shadow: -kfree (mgp->rx_small.shadow); +kfree (ss->rx_small.shadow); abort_with_tx_req_bytes: -kfree (mgp->tx.req_bytes); - mgp->tx.req_bytes =NULL ; - mgp->tx.req_list =NULL ; +kfree (ss->tx.req_bytes); + ss->tx.req_bytes =NULL ; + ss->tx.req_list =NULL ; abort_with_nothing:return status; } -static void myri10ge_free_rings (struct net_device *dev) +static void myri10ge_free_rings (struct myri10ge_slice_state *ss) { -struct myri10ge_priv *mgp; +struct myri10ge_priv *mgp = ss->mgp;struct sk_buff *skb;struct myri10ge_tx_buf *tx;int i, len, idx; - mgp =netdev_priv (dev); - -for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) { - idx = i & mgp->rx_big.mask; -if (i == mgp->rx_big.fill_cnt -1 ) - mgp->rx_big.info[idx].page_offset =MYRI10GE_ALLOC_SIZE ; -myri10ge_unmap_rx_page (mgp->pdev, &mgp->rx_big.info[idx], +for (i = ss->rx_big.cnt; i < ss->rx_big.fill_cnt; i++) { + idx = i & ss->rx_big.mask; +if (i == ss->rx_big.fill_cnt -1 ) + ss->rx_big.info[idx].page_offset =MYRI10GE_ALLOC_SIZE ; +myri10ge_unmap_rx_page (mgp->pdev, &ss->rx_big.info[idx], mgp->big_bytes); -put_page (mgp->rx_big.info[idx].page); +put_page (ss->rx_big.info[idx].page); } -for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) { - idx = i & mgp->rx_small.mask; -if (i == mgp->rx_small.fill_cnt -1 ) - mgp->rx_small.info[idx].page_offset = +for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) { + idx = i & ss->rx_small.mask; +if (i == ss->rx_small.fill_cnt -1 ) + ss->rx_small.info[idx].page_offset =MYRI10GE_ALLOC_SIZE ; -myri10ge_unmap_rx_page (mgp->pdev, &mgp->rx_small.info[idx], +myri10ge_unmap_rx_page (mgp->pdev, &ss->rx_small.info[idx], mgp->small_bytes +MXGEFW_PAD ); -put_page (mgp->rx_small.info[idx].page); +put_page (ss->rx_small.info[idx].page); } - tx = &mgp->tx; + tx = &ss->tx;while (tx->done != tx->req) { idx = tx->done & tx->mask; skb = tx->info[idx].skb;
@@ -1755,7 +1788,7 @@ len =pci_unmap_len (&tx->info[idx], len);pci_unmap_len_set (&tx->info[idx], len,0 );if (skb) { - mgp->stats.tx_dropped++; + ss->stats.tx_dropped++;dev_kfree_skb_any (skb);if (len) pci_unmap_single(mgp->pdev,
@@ -1770,19 +1803,19 @@ PCI_DMA_TODEVICE); } } -kfree (mgp->rx_big.info); +kfree (ss->rx_big.info); -kfree (mgp->rx_small.info); +kfree (ss->rx_small.info); -kfree (mgp->tx.info); +kfree (ss->tx.info); -kfree (mgp->rx_big.shadow); +kfree (ss->rx_big.shadow); -kfree (mgp->rx_small.shadow); +kfree (ss->rx_small.shadow); -kfree (mgp->tx.req_bytes); - mgp->tx.req_bytes =NULL ; - mgp->tx.req_list =NULL ; +kfree (ss->tx.req_bytes); + ss->tx.req_bytes =NULL ; + ss->tx.req_list =NULL ; }static int myri10ge_request_irq (struct myri10ge_priv *mgp)
@@ -1881,13 +1914,11 @@static int myri10ge_open (struct net_device *dev) { -struct myri10ge_priv *mgp; +struct myri10ge_priv *mgp =netdev_priv (dev);struct myri10ge_cmd cmd;struct net_lro_mgr *lro_mgr;int status, big_pow2; - mgp =netdev_priv (dev); -if (mgp->running !=MYRI10GE_ETH_STOPPED )return -EBUSY ;
@@ -1924,16 +1955,16 @@/* get the lanai pointers to the send and receive rings */ status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_SEND_OFFSET , &cmd,0 ); - mgp->tx.lanai = + mgp->ss.tx.lanai = (struct mcp_kreq_ether_send __iomem *)(mgp->sram + cmd.data0); status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_SMALL_RX_OFFSET , &cmd,0 ); - mgp->rx_small.lanai = + mgp->ss.rx_small.lanai = (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0); status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_BIG_RX_OFFSET , &cmd,0 ); - mgp->rx_big.lanai = + mgp->ss.rx_big.lanai = (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0);if (status !=0 ) {
@@ -1945,15 +1976,15 @@ }if (myri10ge_wcfifo && mgp->wc_enabled) { - mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram +MXGEFW_ETH_SEND_4 ; - mgp->rx_small.wc_fifo = + mgp->ss.tx.wc_fifo = (u8 __iomem *) mgp->sram +MXGEFW_ETH_SEND_4 ; + mgp->ss.rx_small.wc_fifo = (u8 __iomem *) mgp->sram +MXGEFW_ETH_RECV_SMALL ; - mgp->rx_big.wc_fifo = + mgp->ss.rx_big.wc_fifo = (u8 __iomem *) mgp->sram +MXGEFW_ETH_RECV_BIG ; }else { - mgp->tx.wc_fifo =NULL ; - mgp->rx_small.wc_fifo =NULL ; - mgp->rx_big.wc_fifo =NULL ; + mgp->ss.tx.wc_fifo =NULL ; + mgp->ss.rx_small.wc_fifo =NULL ; + mgp->ss.rx_big.wc_fifo =NULL ; }/* Firmware needs the big buff size as a power of 2. Lie and
@@ -1970,7 +2001,7 @@ mgp->big_bytes = big_pow2; } - status =myri10ge_allocate_rings (dev); + status =myri10ge_allocate_rings (&mgp->ss);if (status !=0 ) goto abort_with_irq;
@@ -1989,12 +2020,12 @@ goto abort_with_rings; } - cmd.data0 =MYRI10GE_LOWPART_TO_U32 (mgp->fw_stats_bus); - cmd.data1 =MYRI10GE_HIGHPART_TO_U32 (mgp->fw_stats_bus); + cmd.data0 =MYRI10GE_LOWPART_TO_U32 (mgp->ss.fw_stats_bus); + cmd.data1 =MYRI10GE_HIGHPART_TO_U32 (mgp->ss.fw_stats_bus); cmd.data2 =sizeof (struct mcp_irq_data ); status =myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_STATS_DMA_V2 , &cmd,0 );if (status == -ENOSYS ) { -dma_addr_t bus = mgp->fw_stats_bus; +dma_addr_t bus = mgp->ss.fw_stats_bus; bus += offsetof(struct mcp_irq_data , send_done_count); cmd.data0 =MYRI10GE_LOWPART_TO_U32 (bus); cmd.data1 =MYRI10GE_HIGHPART_TO_U32 (bus);
@@ -2015,20 +2046,20 @@ mgp->link_state = ~0U ; mgp->rdma_tags_available =15 ; - lro_mgr = &mgp->rx_done.lro_mgr; + lro_mgr = &mgp->ss.rx_done.lro_mgr; lro_mgr->dev = dev; lro_mgr->features =LRO_F_NAPI ; lro_mgr->ip_summed =CHECKSUM_COMPLETE ; lro_mgr->ip_summed_aggr =CHECKSUM_UNNECESSARY ; lro_mgr->max_desc =MYRI10GE_MAX_LRO_DESCRIPTORS ; - lro_mgr->lro_arr = mgp->rx_done.lro_desc; + lro_mgr->lro_arr = mgp->ss.rx_done.lro_desc; lro_mgr->get_frag_header = myri10ge_get_frag_header; lro_mgr->max_aggr = myri10ge_lro_max_pkts; lro_mgr->frag_align_pad =2 ;if (lro_mgr->max_aggr >MAX_SKB_FRAGS ) lro_mgr->max_aggr =MAX_SKB_FRAGS ; -napi_enable (&mgp->napi);/* must happen prior to any irq */ +napi_enable (&mgp->ss.napi);/* must happen prior to any irq */ status =myri10ge_send_cmd (mgp,MXGEFW_CMD_ETHERNET_UP , &cmd,0 );if (status) {
@@ -2037,8 +2068,8 @@ goto abort_with_rings; } - mgp->wake_queue =0 ; - mgp->stop_queue =0 ; + mgp->ss.tx.wake_queue =0 ; + mgp->ss.tx.stop_queue =0 ; mgp->running =MYRI10GE_ETH_RUNNING ; mgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout *HZ ;add_timer (&mgp->watchdog_timer);
@@ -2046,7 +2077,7 @@return 0 ; abort_with_rings: -myri10ge_free_rings (dev); +myri10ge_free_rings (&mgp->ss); abort_with_irq:myri10ge_free_irq (mgp);
@@ -2058,21 +2089,19 @@static int myri10ge_close (struct net_device *dev) { -struct myri10ge_priv *mgp; +struct myri10ge_priv *mgp =netdev_priv (dev);struct myri10ge_cmd cmd;int status, old_down_cnt; - mgp =netdev_priv (dev); -if (mgp->running !=MYRI10GE_ETH_RUNNING )return 0 ; -if (mgp->tx.req_bytes ==NULL ) +if (mgp->ss.tx.req_bytes ==NULL )return 0 ;del_timer_sync (&mgp->watchdog_timer); mgp->running =MYRI10GE_ETH_STOPPING ; -napi_disable (&mgp->napi); +napi_disable (&mgp->ss.napi);netif_carrier_off (dev);netif_stop_queue (dev); old_down_cnt = mgp->down_cnt;
@@ -2088,7 +2117,7 @@netif_tx_disable (dev);myri10ge_free_irq (mgp); -myri10ge_free_rings (dev); +myri10ge_free_rings (&mgp->ss); mgp->running =MYRI10GE_ETH_STOPPED ;return 0 ;
@@ -2184,7 +2213,7 @@/* * Transmit a packet. We need to split the packet so that a single -* segment does not cross myri10ge->tx.boundary, so this makes segment +* segment does not cross myri10ge->tx_boundary, so this makes segment * counting tricky. So rather than try to count segments up front, we * just give up if there are too few segments to hold a reasonably * fragmented packet currently available. If we run
@@ -2195,8 +2224,9 @@static int myri10ge_xmit (struct sk_buff *skb,struct net_device *dev) {struct myri10ge_priv *mgp =netdev_priv (dev); +struct myri10ge_slice_state *ss;struct mcp_kreq_ether_send *req; -struct myri10ge_tx_buf *tx = &mgp->tx; +struct myri10ge_tx_buf *tx;struct skb_frag_struct *frag;dma_addr_t bus;u32 low;
@@ -2207,6 +2237,9 @@int cum_len, seglen, boundary, rdma_count;u8 flags, odd_flag; +/* always transmit through slot 0 */ + ss = &mgp->ss; + tx = &ss->tx; again: req = tx->req_list; avail = tx->mask -1 - (tx->req - tx->done);
@@ -2221,7 +2254,7 @@if ((unlikely (avail < max_segments))) {/* we are out of transmit resources */ - mgp->stop_queue++; + tx->stop_queue++;netif_stop_queue (dev);return 1 ; }
@@ -2283,7 +2316,7 @@if (skb_padto (skb,ETH_ZLEN )) {/* The packet is gone, so we must * return 0 */ - mgp->stats.tx_dropped +=1 ; + ss->stats.tx_dropped +=1 ;return 0 ; }/* adjust the len to account for the zero pad
@@ -2325,7 +2358,7 @@while (1 ) {/* Break the SKB or Fragment up into pieces which -* do not cross mgp->tx.boundary */ +* do not cross mgp->tx_boundary */ low =MYRI10GE_LOWPART_TO_U32 (bus); high_swapped =htonl (MYRI10GE_HIGHPART_TO_U32 (bus));while (len) {
@@ -2335,7 +2368,8 @@if (unlikely (count == max_segments)) goto abort_linearize; - boundary = (low + tx->boundary) & ~(tx->boundary -1 ); + boundary = + (low + mgp->tx_boundary) & ~(mgp->tx_boundary -1 ); seglen = boundary - low;if (seglen > len) seglen = len;
@@ -2419,7 +2453,7 @@myri10ge_submit_req_wc (tx, tx->req_list, count); tx->pkt_start++;if ((avail - count) <MXGEFW_MAX_SEND_DESC ) { - mgp->stop_queue++; + tx->stop_queue++;netif_stop_queue (dev); } dev->trans_start = jiffies;
@@ -2461,12 +2495,12 @@if (skb_linearize (skb)) goto drop; - mgp->tx_linearized++; + tx->linearized++; goto again; drop:dev_kfree_skb_any (skb); - mgp->stats.tx_dropped +=1 ; + ss->stats.tx_dropped +=1 ;return 0 ; }
@@ -2474,7 +2508,7 @@static int myri10ge_sw_tso (struct sk_buff *skb,struct net_device *dev) {struct sk_buff *segs, *curr; -struct myri10ge_priv *mgp = dev->priv; +struct myri10ge_priv *mgp =netdev_priv (dev);int status; segs =skb_gso_segment (skb, dev->features & ~NETIF_F_TSO6 );
@@ -2514,14 +2548,13 @@static void myri10ge_set_multicast_list (struct net_device *dev) { +struct myri10ge_priv *mgp =netdev_priv (dev);struct myri10ge_cmd cmd; -struct myri10ge_priv *mgp;struct dev_mc_list *mc_list;__be32 data[2 ] = {0 ,0 };int err;DECLARE_MAC_BUF (mac); - mgp =netdev_priv (dev);/* can be called from atomic contexts, * pass 1 to force atomicity in myri10ge_send_cmd() */ myri10ge_change_promisc (mgp, dev->flags &IFF_PROMISC ,1 );
@@ -2723,9 +2756,9 @@* already been enabled, then it must use a firmware image which works * around unaligned completion packets (myri10ge_ethp_z8e.dat), and it * should also ensure that it never gives the device a Read-DMA which is -* larger than 2KB by setting the tx.boundary to 2KB. If ECRC is +* larger than 2KB by setting the tx_boundary to 2KB. If ECRC is * enabled, then the driver should use the aligned (myri10ge_eth_z8e.dat) -* firmware image, and set tx.boundary to 4KB. +* firmware image, and set tx_boundary to 4KB. */ static void myri10ge_firmware_probe (struct myri10ge_priv *mgp)
@@ -2734,7 +2767,7 @@struct device *dev = &pdev->dev;int status; - mgp->tx.boundary =4096 ; + mgp->tx_boundary =4096 ;/* * Verify the max read request size was set to 4KB * before trying the test with 4KB.
@@ -2746,7 +2779,7 @@ }if (status !=4096 ) {dev_warn (dev,"Max Read Request size != 4096 (%d)\n" , status); - mgp->tx.boundary =2048 ; + mgp->tx_boundary =2048 ; }/* * load the optimized firmware (which assumes aligned PCIe
@@ -2779,7 +2812,7 @@ "Please install up to date fw\n"); abort:/* fall back to using the unaligned firmware */ - mgp->tx.boundary =2048 ; + mgp->tx_boundary =2048 ; mgp->fw_name = myri10ge_fw_unaligned; }
@@ -2800,7 +2833,7 @@if (link_width <8 ) {dev_info (&mgp->pdev->dev,"PCIE x%d Link\n" , link_width); - mgp->tx.boundary =4096 ; + mgp->tx_boundary =4096 ; mgp->fw_name = myri10ge_fw_aligned; }else {myri10ge_firmware_probe (mgp);
@@ -2809,12 +2842,12 @@if (myri10ge_force_firmware ==1 ) {dev_info (&mgp->pdev->dev,"Assuming aligned completions (forced)\n" ); - mgp->tx.boundary =4096 ; + mgp->tx_boundary =4096 ; mgp->fw_name = myri10ge_fw_aligned; }else {dev_info (&mgp->pdev->dev,"Assuming unaligned completions (forced)\n" ); - mgp->tx.boundary =2048 ; + mgp->tx_boundary =2048 ; mgp->fw_name = myri10ge_fw_unaligned; } }
@@ -2931,6 +2964,7 @@ {struct myri10ge_priv *mgp = container_of(work, struct myri10ge_priv, watchdog_work); +struct myri10ge_tx_buf *tx;u32 reboot;int status;u16 cmd, vendor;
@@ -2980,15 +3014,16 @@printk (KERN_ERR "myri10ge: %s: device timeout, resetting\n" , mgp->dev->name); + tx = &mgp->ss.tx;printk (KERN_INFO "myri10ge: %s: %d %d %d %d %d\n" , - mgp->dev->name, mgp->tx.req, mgp->tx.done, - mgp->tx.pkt_start, mgp->tx.pkt_done, - (int )ntohl (mgp->fw_stats->send_done_count)); + mgp->dev->name, tx->req, tx->done, + tx->pkt_start, tx->pkt_done, + (int )ntohl (mgp->ss.fw_stats->send_done_count));msleep (2000 );printk (KERN_INFO "myri10ge: %s: %d %d %d %d %d\n" , - mgp->dev->name, mgp->tx.req, mgp->tx.done, - mgp->tx.pkt_start, mgp->tx.pkt_done, - (int )ntohl (mgp->fw_stats->send_done_count)); + mgp->dev->name, tx->req, tx->done, + tx->pkt_start, tx->pkt_done, + (int )ntohl (mgp->ss.fw_stats->send_done_count)); }rtnl_lock ();myri10ge_close (mgp->dev);
@@ -3011,28 +3046,31 @@static void myri10ge_watchdog_timer (unsigned long arg) {struct myri10ge_priv *mgp; +struct myri10ge_slice_state *ss;u32 rx_pause_cnt; mgp = (struct myri10ge_priv *)arg; -if (mgp->rx_small.watchdog_needed) { -myri10ge_alloc_rx_pages (mgp, &mgp->rx_small, + rx_pause_cnt =ntohl (mgp->ss.fw_stats->dropped_pause); + + ss = &mgp->ss; +if (ss->rx_small.watchdog_needed) { +myri10ge_alloc_rx_pages (mgp, &ss->rx_small, mgp->small_bytes +MXGEFW_PAD ,1 ); -if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt >= +if (ss->rx_small.fill_cnt - ss->rx_small.cnt >= myri10ge_fill_thresh) - mgp->rx_small.watchdog_needed =0 ; + ss->rx_small.watchdog_needed =0 ; } -if (mgp->rx_big.watchdog_needed) { -myri10ge_alloc_rx_pages (mgp, &mgp->rx_big, mgp->big_bytes,1 ); -if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt >= +if (ss->rx_big.watchdog_needed) { +myri10ge_alloc_rx_pages (mgp, &ss->rx_big, mgp->big_bytes,1 ); +if (ss->rx_big.fill_cnt - ss->rx_big.cnt >= myri10ge_fill_thresh) - mgp->rx_big.watchdog_needed =0 ; + ss->rx_big.watchdog_needed =0 ; } - rx_pause_cnt =ntohl (mgp->fw_stats->dropped_pause); -if (mgp->tx.req != mgp->tx.done && - mgp->tx.done == mgp->watchdog_tx_done && - mgp->watchdog_tx_req != mgp->watchdog_tx_done) { +if (ss->tx.req != ss->tx.done && + ss->tx.done == ss->watchdog_tx_done && + ss->watchdog_tx_req != ss->watchdog_tx_done) {/* nic seems like it might be stuck.. */ if (rx_pause_cnt != mgp->watchdog_pause) {if (net_ratelimit ())
@@ -3047,8 +3085,8 @@/* rearm timer */ mod_timer (&mgp->watchdog_timer, jiffies + myri10ge_watchdog_timeout *HZ ); - mgp->watchdog_tx_done = mgp->tx.done; - mgp->watchdog_tx_req = mgp->tx.req; + ss->watchdog_tx_done = ss->tx.done; + ss->watchdog_tx_req = ss->tx.req; mgp->watchdog_pause = rx_pause_cnt; }
@@ -3072,7 +3110,7 @@ mgp =netdev_priv (netdev); mgp->dev = netdev; -netif_napi_add (netdev, &mgp->napi, myri10ge_poll, myri10ge_napi_weight); +netif_napi_add (netdev, &mgp->ss.napi, myri10ge_poll, myri10ge_napi_weight); mgp->pdev = pdev; mgp->csum_flag =MXGEFW_FLAGS_CKSUM ; mgp->pause = myri10ge_flow_control;
@@ -3118,9 +3156,9 @@if (mgp->cmd ==NULL ) goto abort_with_netdev; - mgp->fw_stats =dma_alloc_coherent (&pdev->dev,sizeof (*mgp->fw_stats), - &mgp->fw_stats_bus,GFP_KERNEL ); -if (mgp->fw_stats ==NULL ) + mgp->ss.fw_stats =dma_alloc_coherent (&pdev->dev,sizeof (*mgp->ss.fw_stats), + &mgp->ss.fw_stats_bus,GFP_KERNEL ); +if (mgp->ss.fw_stats ==NULL ) goto abort_with_cmd; mgp->board_span =pci_resource_len (pdev,0 );
@@ -3160,12 +3198,12 @@ netdev->dev_addr[i] = mgp->mac_addr[i];/* allocate rx done ring */ - bytes = myri10ge_max_intr_slots *sizeof (*mgp->rx_done.entry); - mgp->rx_done.entry =dma_alloc_coherent (&pdev->dev, bytes, - &mgp->rx_done.bus,GFP_KERNEL ); -if (mgp->rx_done.entry ==NULL ) + bytes = myri10ge_max_intr_slots *sizeof (*mgp->ss.rx_done.entry); + mgp->ss.rx_done.entry =dma_alloc_coherent (&pdev->dev, bytes, + &mgp->ss.rx_done.bus,GFP_KERNEL ); +if (mgp->ss.rx_done.entry ==NULL ) goto abort_with_ioremap; -memset (mgp->rx_done.entry,0 , bytes); +memset (mgp->ss.rx_done.entry,0 , bytes);myri10ge_select_firmware (mgp);
@@ -3225,7 +3263,7 @@ }dev_info (dev,"%s IRQ %d, tx bndry %d, fw %s, WC %s\n" , (mgp->msi_enabled ?"MSI" :"xPIC" ), - netdev->irq, mgp->tx.boundary, mgp->fw_name, + netdev->irq, mgp->tx_boundary, mgp->fw_name, (mgp->wc_enabled ?"Enabled" :"Disabled" ));return 0 ;
@@ -3237,9 +3275,9 @@myri10ge_dummy_rdma (mgp,0 ); abort_with_rx_done: - bytes = myri10ge_max_intr_slots *sizeof (*mgp->rx_done.entry); + bytes = myri10ge_max_intr_slots *sizeof (*mgp->ss.rx_done.entry);dma_free_coherent (&pdev->dev, bytes, - mgp->rx_done.entry, mgp->rx_done.bus); + mgp->ss.rx_done.entry, mgp->ss.rx_done.bus); abort_with_ioremap:iounmap (mgp->sram);
@@ -3249,8 +3287,8 @@if (mgp->mtrr >=0 )mtrr_del (mgp->mtrr, mgp->iomem_base, mgp->board_span);#endif -dma_free_coherent (&pdev->dev,sizeof (*mgp->fw_stats), - mgp->fw_stats, mgp->fw_stats_bus); +dma_free_coherent (&pdev->dev,sizeof (*mgp->ss.fw_stats), + mgp->ss.fw_stats, mgp->ss.fw_stats_bus); abort_with_cmd: dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd),
@@ -3288,9 +3326,9 @@/* avoid a memory leak */ pci_restore_state (pdev); - bytes = myri10ge_max_intr_slots *sizeof (*mgp->rx_done.entry); + bytes = myri10ge_max_intr_slots *sizeof (*mgp->ss.rx_done.entry);dma_free_coherent (&pdev->dev, bytes, - mgp->rx_done.entry, mgp->rx_done.bus); + mgp->ss.rx_done.entry, mgp->ss.rx_done.bus);iounmap (mgp->sram);
@@ -3298,8 +3336,8 @@if (mgp->mtrr >=0 )mtrr_del (mgp->mtrr, mgp->iomem_base, mgp->board_span);#endif -dma_free_coherent (&pdev->dev,sizeof (*mgp->fw_stats), - mgp->fw_stats, mgp->fw_stats_bus); +dma_free_coherent (&pdev->dev,sizeof (*mgp->ss.fw_stats), + mgp->ss.fw_stats, mgp->ss.fw_stats_bus);dma_free_coherent (&pdev->dev,sizeof (*mgp->cmd), mgp->cmd, mgp->cmd_bus);
PATCH 11/16 myri10ge: cleanup retrieving of firmware capabilities
In reply to Brice GoglinAdd myri10ge_get_firmware_capabilities() to retrieve TSO6 and interrupt slots capabilities from the firmware.
--- drivers/net/myri10ge/myri10ge.c | 42 +++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-)
drivers/net/myri10ge/myri10ge.c +31 -11
@@ -194,6 +194,7 @@int csum_flag;/* rx_csums? */ int small_bytes;int big_bytes; +int max_intr_slots;struct net_device *dev;struct net_device_stats stats;spinlock_t stats_lock;
@@ -634,13 +635,38 @@return status; } +int myri10ge_get_firmware_capabilities (struct myri10ge_priv *mgp) +{ +struct myri10ge_cmd cmd; +int status; + +/* probe for IPv6 TSO support */ + mgp->features =NETIF_F_SG |NETIF_F_HW_CSUM |NETIF_F_TSO ; + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE , + &cmd,0 ); +if (status ==0 ) { + mgp->max_tso6 = cmd.data0; + mgp->features |=NETIF_F_TSO6 ; + } + + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_RX_RING_SIZE , &cmd,0 ); +if (status !=0 ) { +dev_err (&mgp->pdev->dev, +"failed MXGEFW_CMD_GET_RX_RING_SIZE\n" ); +return -ENXIO ; + } + + mgp->max_intr_slots =2 * (cmd.data0 /sizeof (struct mcp_dma_addr )); + +return 0 ; +} +static int myri10ge_load_firmware (struct myri10ge_priv *mgp) {char __iomem *submit; __be32 buf[16] __attribute__ ((__aligned__(8)));u32 dma_low, dma_high, size;int status, i; -struct myri10ge_cmd cmd; size =0 ; status =myri10ge_load_hotplug_firmware (mgp, &size);
@@ -672,6 +698,8 @@ mgp->fw_name ="adopted" ; mgp->tx_boundary =2048 ; +myri10ge_dummy_rdma (mgp,1 ); + status =myri10ge_get_firmware_capabilities (mgp);return status; }
@@ -714,18 +742,10 @@dev_err (&mgp->pdev->dev,"handoff failed\n" );return -ENXIO ; } -dev_info (&mgp->pdev->dev,"handoff confirmed\n" );myri10ge_dummy_rdma (mgp,1 ); + status =myri10ge_get_firmware_capabilities (mgp); -/* probe for IPv6 TSO support */ - mgp->features =NETIF_F_SG |NETIF_F_HW_CSUM |NETIF_F_TSO ; - status =myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE , - &cmd,0 ); -if (status ==0 ) { - mgp->max_tso6 = cmd.data0; - mgp->features |=NETIF_F_TSO6 ; - } -return 0 ; +return status; }static int myri10ge_update_mac_address (struct myri10ge_priv *mgp,u8 * addr)
PATCH 12/16 myri10ge: fix the number of interrupt slots
In reply to Brice GoglinFix a long-standing bug/misunderstanding between the driver and the firmware. The size of the interrupt queue must be set to the number of rx slots (big + small), and it should never have been a tunable.
Setting it too small results in chaos.
--- drivers/net/myri10ge/myri10ge.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-)
drivers/net/myri10ge/myri10ge.c +5 -9
@@ -253,10 +253,6 @@module_param (myri10ge_ecrc_enable, int,S_IRUGO );MODULE_PARM_DESC (myri10ge_ecrc_enable,"Enable Extended CRC on PCI-E" ); -static int myri10ge_max_intr_slots =1024 ; -module_param (myri10ge_max_intr_slots, int,S_IRUGO ); -MODULE_PARM_DESC (myri10ge_max_intr_slots,"Interrupt queue slots" ); -static int myri10ge_small_bytes =-1 ;/* -1 == auto */ module_param (myri10ge_small_bytes, int,S_IRUGO |S_IWUSR );MODULE_PARM_DESC (myri10ge_small_bytes,"Threshold of small packets" );
@@ -879,7 +875,7 @@/* Now exchange information about interrupts */ - bytes = myri10ge_max_intr_slots *sizeof (*mgp->ss.rx_done.entry); + bytes = mgp->max_intr_slots *sizeof (*mgp->ss.rx_done.entry);memset (mgp->ss.rx_done.entry,0 , bytes); cmd.data0 = (u32 ) bytes; status =myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_INTRQ_SIZE , &cmd,0 );
@@ -1217,7 +1213,7 @@ rx_packets += rx_ok; rx_bytes += rx_ok * (unsigned long )length; cnt++; - idx = cnt & (myri10ge_max_intr_slots -1 ); + idx = cnt & (mgp->max_intr_slots -1 ); work_done++; } rx_done->idx = idx;
@@ -3218,7 +3214,7 @@ netdev->dev_addr[i] = mgp->mac_addr[i];/* allocate rx done ring */ - bytes = myri10ge_max_intr_slots *sizeof (*mgp->ss.rx_done.entry); + bytes = mgp->max_intr_slots *sizeof (*mgp->ss.rx_done.entry); mgp->ss.rx_done.entry =dma_alloc_coherent (&pdev->dev, bytes, &mgp->ss.rx_done.bus,GFP_KERNEL );if (mgp->ss.rx_done.entry ==NULL )
@@ -3295,7 +3291,7 @@myri10ge_dummy_rdma (mgp,0 ); abort_with_rx_done: - bytes = myri10ge_max_intr_slots *sizeof (*mgp->ss.rx_done.entry); + bytes = mgp->max_intr_slots *sizeof (*mgp->ss.rx_done.entry);dma_free_coherent (&pdev->dev, bytes, mgp->ss.rx_done.entry, mgp->ss.rx_done.bus);
@@ -3346,7 +3342,7 @@/* avoid a memory leak */ pci_restore_state (pdev); - bytes = myri10ge_max_intr_slots *sizeof (*mgp->ss.rx_done.entry); + bytes = mgp->max_intr_slots *sizeof (*mgp->ss.rx_done.entry);dma_free_coherent (&pdev->dev, bytes, mgp->ss.rx_done.entry, mgp->ss.rx_done.bus);
PATCH 13/16 myri10ge: add routines for multislices
In reply to Brice GoglinAdd several routines that multislices support will use.
--- drivers/net/myri10ge/myri10ge.c | 256 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+)
drivers/net/myri10ge/myri10ge.c +256 -0
@@ -1928,6 +1928,76 @@return 0 ; } +#if 0 +static int myri10ge_get_txrx (struct myri10ge_priv *mgp,int slice) +{ +struct myri10ge_cmd cmd; +struct myri10ge_slice_state *ss; +int status; + + ss = &mgp->ss[slice]; + cmd.data0 =0 ;/* single slice for now */ + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_SEND_OFFSET , &cmd,0 ); + ss->tx.lanai = (struct mcp_kreq_ether_send __iomem *) + (mgp->sram + cmd.data0); + + cmd.data0 = slice; + status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_SMALL_RX_OFFSET , + &cmd,0 ); + ss->rx_small.lanai = (struct mcp_kreq_ether_recv __iomem *) + (mgp->sram + cmd.data0); + + cmd.data0 = slice; + status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_BIG_RX_OFFSET , &cmd,0 ); + ss->rx_big.lanai = (struct mcp_kreq_ether_recv __iomem *) + (mgp->sram + cmd.data0); + +if (myri10ge_wcfifo && mgp->wc_enabled) { + ss->tx.wc_fifo = (u8 __iomem *) + mgp->sram +MXGEFW_ETH_SEND_4 +64 * slice; + ss->rx_small.wc_fifo = (u8 __iomem *) + mgp->sram +MXGEFW_ETH_RECV_SMALL +64 * slice; + ss->rx_big.wc_fifo = (u8 __iomem *) + mgp->sram +MXGEFW_ETH_RECV_BIG +64 * slice; + }else { + ss->tx.wc_fifo =NULL ; + ss->rx_small.wc_fifo =NULL ; + ss->rx_big.wc_fifo =NULL ; + } +return status; + +} + +static int myri10ge_set_stats (struct myri10ge_priv *mgp,int slice) +{ +struct myri10ge_cmd cmd; +struct myri10ge_slice_state *ss; +int status; + + ss = &mgp->ss[slice]; + cmd.data0 =MYRI10GE_LOWPART_TO_U32 (ss->fw_stats_bus); + cmd.data1 =MYRI10GE_HIGHPART_TO_U32 (ss->fw_stats_bus); + cmd.data2 =sizeof (struct mcp_irq_data ); + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_STATS_DMA_V2 , &cmd,0 ); +if (status == -ENOSYS ) { +dma_addr_t bus = ss->fw_stats_bus; +if (slice !=0 ) +return -EINVAL ; + bus += offsetof(struct mcp_irq_data , send_done_count); + cmd.data0 =MYRI10GE_LOWPART_TO_U32 (bus); + cmd.data1 =MYRI10GE_HIGHPART_TO_U32 (bus); + status =myri10ge_send_cmd (mgp, +MXGEFW_CMD_SET_STATS_DMA_OBSOLETE , + &cmd,0 ); +/* Firmware cannot support multicast without STATS_DMA_V2 */ + mgp->fw_multicast_support =0 ; + }else { + mgp->fw_multicast_support =1 ; + } +return 0 ; +} +#endif +static int myri10ge_open (struct net_device *dev) {struct myri10ge_priv *mgp =netdev_priv (dev);
@@ -3106,6 +3176,192 @@ mgp->watchdog_pause = rx_pause_cnt; } +#if 0 +static void myri10ge_free_slices (struct myri10ge_priv *mgp) +{ +struct myri10ge_slice_state *ss; +struct pci_dev *pdev = mgp->pdev; +size_t bytes; +int i; + +if (mgp->ss ==NULL ) +return ; + +for (i =0 ; i < mgp->num_slices; i++) { + ss = &mgp->ss[i]; +if (ss->rx_done.entry !=NULL ) { + bytes = mgp->max_intr_slots * +sizeof (*ss->rx_done.entry); +dma_free_coherent (&pdev->dev, bytes, + ss->rx_done.entry, ss->rx_done.bus); + ss->rx_done.entry =NULL ; + } +if (ss->fw_stats !=NULL ) { + bytes =sizeof (*ss->fw_stats); +dma_free_coherent (&pdev->dev, bytes, + ss->fw_stats, ss->fw_stats_bus); + ss->fw_stats =NULL ; + } + } +kfree (mgp->ss); + mgp->ss =NULL ; +} + +static int myri10ge_alloc_slices (struct myri10ge_priv *mgp) +{ +struct myri10ge_slice_state *ss; +struct pci_dev *pdev = mgp->pdev; +size_t bytes; +int i; + + bytes =sizeof (*mgp->ss) * mgp->num_slices; + mgp->ss =kzalloc (bytes,GFP_KERNEL ); +if (mgp->ss ==NULL ) { +return -ENOMEM ; + } + +for (i =0 ; i < mgp->num_slices; i++) { + ss = &mgp->ss[i]; + bytes = mgp->max_intr_slots *sizeof (*ss->rx_done.entry); + ss->rx_done.entry =dma_alloc_coherent (&pdev->dev, bytes, + &ss->rx_done.bus, +GFP_KERNEL ); +if (ss->rx_done.entry ==NULL ) + goto abort; +memset (ss->rx_done.entry,0 , bytes); + bytes =sizeof (*ss->fw_stats); + ss->fw_stats =dma_alloc_coherent (&pdev->dev, bytes, + &ss->fw_stats_bus, +GFP_KERNEL ); +if (ss->fw_stats ==NULL ) + goto abort; + ss->mgp = mgp; + ss->dev = mgp->dev; +netif_napi_add (ss->dev, &ss->napi, myri10ge_poll, + myri10ge_napi_weight); + } +return 0 ; +abort: +myri10ge_free_slices (mgp); +return -ENOMEM ; +} + +/* +* This function determines the number of slices supported. +* The number slices is the minumum of the number of CPUS, +* the number of MSI-X irqs supported, the number of slices +* supported by the firmware +*/ +static void myri10ge_probe_slices (struct myri10ge_priv *mgp) +{ +struct myri10ge_cmd cmd; +struct pci_dev *pdev = mgp->pdev; +char *old_fw; +int i, status, ncpus, msix_cap; + + mgp->num_slices =1 ; + msix_cap =pci_find_capability (pdev,PCI_CAP_ID_MSIX ); + ncpus =num_online_cpus (); + +if (myri10ge_max_slices ==1 || msix_cap ==0 || + (myri10ge_max_slices ==-1 && ncpus <2 )) +return ; + +/* try to load the slice aware rss firmware */ + old_fw = mgp->fw_name; +if (old_fw == myri10ge_fw_aligned) + mgp->fw_name = myri10ge_fw_rss_aligned; +else + mgp->fw_name = myri10ge_fw_rss_unaligned; + status =myri10ge_load_firmware (mgp,0 ); +if (status !=0 ) { +dev_info (&pdev->dev,"Rss firmware not found\n" ); +return ; + } + +/* hit the board with a reset to ensure it is alive */ +memset (&cmd,0 ,sizeof (cmd)); + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_RESET , &cmd,0 ); +if (status !=0 ) { +dev_err (&mgp->pdev->dev,"failed reset\n" ); + goto abort_with_fw; +return ; + } + + mgp->max_intr_slots = cmd.data0 /sizeof (struct mcp_slot ); + +/* tell it the size of the interrupt queues */ + cmd.data0 = mgp->max_intr_slots *sizeof (struct mcp_slot ); + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_INTRQ_SIZE , &cmd,0 ); +if (status !=0 ) { +dev_err (&mgp->pdev->dev,"failed MXGEFW_CMD_SET_INTRQ_SIZE\n" ); + goto abort_with_fw; + } + +/* ask the maximum number of slices it supports */ + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_MAX_RSS_QUEUES , &cmd,0 ); +if (status !=0 ) + goto abort_with_fw; +else + mgp->num_slices = cmd.data0; + +/* Only allow multiple slices if MSI-X is usable */ +if (!myri10ge_msi) { + goto abort_with_fw; + } + +/* if the admin did not specify a limit to how many +* slices we should use, cap it automatically to the +* number of CPUs currently online */ +if (myri10ge_max_slices ==-1 ) + myri10ge_max_slices = ncpus; + +if (mgp->num_slices > myri10ge_max_slices) + mgp->num_slices = myri10ge_max_slices; + +/* Now try to allocate as many MSI-X vectors as we have +* slices. We give up on MSI-X if we can only get a single +* vector. */ + + mgp->msix_vectors =kzalloc (mgp->num_slices * +sizeof (*mgp->msix_vectors),GFP_KERNEL ); +if (mgp->msix_vectors ==NULL ) + goto disable_msix; +for (i =0 ; i < mgp->num_slices; i++) { + mgp->msix_vectors[i].entry = i; + } + +while (mgp->num_slices >1 ) { +/* make sure it is a power of two */ +while (!is_power_of_2 (mgp->num_slices)) + mgp->num_slices--; +if (mgp->num_slices ==1 ) + goto disable_msix; + status =pci_enable_msix (pdev, mgp->msix_vectors, + mgp->num_slices); +if (status ==0 ) { +pci_disable_msix (pdev); +return ; + } +if (status >0 ) + mgp->num_slices = status; +else + goto disable_msix; + } + +disable_msix: +if (mgp->msix_vectors !=NULL ) { +kfree (mgp->msix_vectors); + mgp->msix_vectors =NULL ; + } + +abort_with_fw: + mgp->num_slices =1 ; + mgp->fw_name = old_fw; +myri10ge_load_firmware (mgp,0 ); +} +#endif +static int myri10ge_probe (struct pci_dev *pdev,const struct pci_device_id *ent) {struct net_device *netdev;
Re: [PATCH 13/16] myri10ge: add routines for multislices
Quoted 7 lines · Brice Goglin
Add several routines that multislices support will use.
Signed-off-by Brice Goglin <[email protected]>Signed-off-by Andrew Gallatin <[email protected]>--- drivers/net/myri10ge/myri10ge.c | 256 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+)
this is not really appropriate for the bug-fixes-only 2.6.26-rc.
I temporarily put patches 13-16 in netdev-2.6.git#upstream-myri, and will shove them into net-next once davem pulls in the myri bugfixes into net-next (or you guys have some alternate suggestions)
Re: [PATCH 13/16] myri10ge: add routines for multislices
Quoted 10 lines · Jeff Garzik
Quoted 8 lines · Brice Goglin
Add several routines that multislices support will use.
Signed-off-by Brice Goglin <[email protected]>Signed-off-by Andrew Gallatin <[email protected]>--- drivers/net/myri10ge/myri10ge.c | 256 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+)
Quoted 5 lines
this is not really appropriate for the bug-fixes-only 2.6.26-rc.
I temporarily put patches 13-16 in netdev-2.6.git#upstream-myri, and will shove them into net-next once davem pulls in the myri bugfixes into net-next (or you guys have some alternate suggestions)
Actually, if #16 (update driver version) isn't going to Linus soon, there is no need to keep it for now. It will very probably be outdated when the 2.6.27 release cycle will start. So I'll send an updated one for then (and I may send an updated one for 2.6.26 later also). So please drop this #16 from upstream-myri.
By the way, there is no MAINTAINERS entry for myri10ge, so here's one in the next patch.
thanks,
Brice
PATCH 1/1 Add maintainers for myri10ge driver
Add a MAINTAINERS entry for the myri10ge driver.
--- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+)
MAINTAINERS +9 -0
@@ -2808,6 +2808,15 @@ L: [email protected] S: Maintained +MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE) +P: Andrew Gallatin +M: [email protected] +P: Brice Goglin +M: [email protected] +L: [email protected] +W: http://www.myri.com/scs/download-Myri10GE.html +S: Supported + NATSEMI ETHERNET DRIVER (DP8381x) P: Tim Hockin M: [email protected]
PATCH 14/16 myri10ge: add multislices support
In reply to Brice GoglinAdd multi-slice/MSI-X support. By default, a single slice (and the normal firmware) are used. To enable msi-x, multi-slice mode, one must load the driver with myri10ge_max_slices set to either -1, or something larger than 1.
--- drivers/net/myri10ge/myri10ge.c | 684 +++++++++++++++++++++++++--------------- 1 file changed, 442 insertions(+), 242 deletions(-)
drivers/net/myri10ge/myri10ge.c +442 -242
@@ -185,11 +185,13 @@dma_addr_t fw_stats_bus;int watchdog_tx_done;int watchdog_tx_req; +char irq_desc[32 ]; };struct myri10ge_priv { -struct myri10ge_slice_state ss; +struct myri10ge_slice_state *ss;int tx_boundary;/* boundary transmits cannot cross */ +int num_slices;int running;/* running? */ int csum_flag;/* rx_csums? */ int small_bytes;
@@ -208,6 +210,8 @@dma_addr_t cmd_bus;struct pci_dev *pdev;int msi_enabled; +int msix_enabled; +struct msix_entry *msix_vectors;u32 link_state;unsigned int rdma_tags_available;int intr_coal_delay;
@@ -244,6 +248,8 @@static char *myri10ge_fw_unaligned ="myri10ge_ethp_z8e.dat" ;static char *myri10ge_fw_aligned ="myri10ge_eth_z8e.dat" ; +static char *myri10ge_fw_rss_unaligned ="myri10ge_rss_ethp_z8e.dat" ; +static char *myri10ge_fw_rss_aligned ="myri10ge_rss_eth_z8e.dat" ;static char *myri10ge_fw_name =NULL ;module_param (myri10ge_fw_name, charp,S_IRUGO |S_IWUSR );
@@ -321,6 +327,14 @@module_param (myri10ge_wcfifo, int,S_IRUGO );MODULE_PARM_DESC (myri10ge_wcfifo,"Enable WC Fifo when WC is enabled" ); +static int myri10ge_max_slices =1 ; +module_param (myri10ge_max_slices, int,S_IRUGO ); +MODULE_PARM_DESC (myri10ge_max_slices,"Max tx/rx queues" ); + +static int myri10ge_rss_hash =MXGEFW_RSS_HASH_TYPE_SRC_PORT ; +module_param (myri10ge_rss_hash, int,S_IRUGO ); +MODULE_PARM_DESC (myri10ge_rss_hash,"Type of RSS hashing to do" ); +#define MYRI10GE_FW_OFFSET 1024*1024#define MYRI10GE_HIGHPART_TO_U32 (X ) \ (sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
@@ -657,7 +671,7 @@return 0 ; } -static int myri10ge_load_firmware (struct myri10ge_priv *mgp) +static int myri10ge_load_firmware (struct myri10ge_priv *mgp,int adopt) {char __iomem *submit; __be32 buf[16] __attribute__ ((__aligned__(8)));
@@ -667,6 +681,8 @@ size =0 ; status =myri10ge_load_hotplug_firmware (mgp, &size);if (status) { +if (!adopt) +return status;dev_warn (&mgp->pdev->dev,"hotplug firmware loading failed\n" );/* Do not attempt to adopt firmware if there
@@ -859,7 +875,8 @@static int myri10ge_reset (struct myri10ge_priv *mgp) {struct myri10ge_cmd cmd; -int status; +struct myri10ge_slice_state *ss; +int i, status;size_t bytes;/* try to send a reset command to the card to see if it
@@ -872,20 +889,74 @@ } (void )myri10ge_dma_test (mgp,MXGEFW_DMA_TEST ); +/* +* Use non-ndis mcp_slot (eg, 4 bytes total, +* no toeplitz hash value returned. Older firmware will +* not understand this command, but will use the correct +* sized mcp_slot, so we ignore error returns +*/ + cmd.data0 =MXGEFW_RSS_MCP_SLOT_TYPE_MIN ; + (void )myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_RSS_MCP_SLOT_TYPE , &cmd,0 );/* Now exchange information about interrupts */ - bytes = mgp->max_intr_slots *sizeof (*mgp->ss.rx_done.entry); -memset (mgp->ss.rx_done.entry,0 , bytes); + bytes = mgp->max_intr_slots *sizeof (*mgp->ss[0 ].rx_done.entry); cmd.data0 = (u32 ) bytes; status =myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_INTRQ_SIZE , &cmd,0 ); - cmd.data0 =MYRI10GE_LOWPART_TO_U32 (mgp->ss.rx_done.bus); - cmd.data1 =MYRI10GE_HIGHPART_TO_U32 (mgp->ss.rx_done.bus); - status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_INTRQ_DMA , &cmd,0 ); + +/* +* Even though we already know how many slices are supported +* via myri10ge_probe_slices() MXGEFW_CMD_GET_MAX_RSS_QUEUES +* has magic side effects, and must be called after a reset. +* It must be called prior to calling any RSS related cmds, +* including assigning an interrupt queue for anything but +* slice 0. It must also be called *after* +* MXGEFW_CMD_SET_INTRQ_SIZE, since the intrq size is used by +* the firmware to compute offsets. +*/ + +if (mgp->num_slices >1 ) { + +/* ask the maximum number of slices it supports */ + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_MAX_RSS_QUEUES , + &cmd,0 ); +if (status !=0 ) { +dev_err (&mgp->pdev->dev, +"failed to get number of slices\n" ); + } + +/* +* MXGEFW_CMD_ENABLE_RSS_QUEUES must be called prior +* to setting up the interrupt queue DMA +*/ + + cmd.data0 = mgp->num_slices; + cmd.data1 =1 ;/* use MSI-X */ + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_ENABLE_RSS_QUEUES , + &cmd,0 ); +if (status !=0 ) { +dev_err (&mgp->pdev->dev, +"failed to set number of slices\n" ); + +return status; + } + } +for (i =0 ; i < mgp->num_slices; i++) { + ss = &mgp->ss[i]; + cmd.data0 =MYRI10GE_LOWPART_TO_U32 (ss->rx_done.bus); + cmd.data1 =MYRI10GE_HIGHPART_TO_U32 (ss->rx_done.bus); + cmd.data2 = i; + status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_INTRQ_DMA , + &cmd,0 ); + }; status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_IRQ_ACK_OFFSET , &cmd,0 ); - mgp->ss.irq_claim = (__iomem __be32 *) (mgp->sram + cmd.data0); +for (i =0 ; i < mgp->num_slices; i++) { + ss = &mgp->ss[i]; + ss->irq_claim = + (__iomem __be32 *) (mgp->sram + cmd.data0 +8 * i); + } status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET , &cmd,0 ); mgp->irq_deassert = (__iomem __be32 *) (mgp->sram + cmd.data0);
@@ -899,18 +970,25 @@ }put_be32 (htonl (mgp->intr_coal_delay), mgp->intr_coal_delay_ptr); -memset (mgp->ss.rx_done.entry,0 , bytes); -/* reset mcp/driver shared state back to 0 */ - mgp->ss.tx.req =0 ; - mgp->ss.tx.done =0 ; - mgp->ss.tx.pkt_start =0 ; - mgp->ss.tx.pkt_done =0 ; - mgp->ss.rx_big.cnt =0 ; - mgp->ss.rx_small.cnt =0 ; - mgp->ss.rx_done.idx =0 ; - mgp->ss.rx_done.cnt =0 ; + mgp->link_changes =0 ; +for (i =0 ; i < mgp->num_slices; i++) { + ss = &mgp->ss[i]; + +memset (ss->rx_done.entry,0 , bytes); + ss->tx.req =0 ; + ss->tx.done =0 ; + ss->tx.pkt_start =0 ; + ss->tx.pkt_done =0 ; + ss->rx_big.cnt =0 ; + ss->rx_small.cnt =0 ; + ss->rx_done.idx =0 ; + ss->rx_done.cnt =0 ; + ss->tx.wake_queue =0 ; + ss->tx.stop_queue =0 ; + } + status =myri10ge_update_mac_address (mgp, mgp->dev->dev_addr);myri10ge_change_pause (mgp, mgp->pause);myri10ge_set_multicast_list (mgp->dev);
@@ -1095,9 +1173,10 @@ rx_frags[0 ].size -=MXGEFW_PAD ; len -=MXGEFW_PAD ;lro_receive_frags (&ss->rx_done.lro_mgr, rx_frags, - len, len,/* opaque, will come back in get_frag_header */ + len, len, (void *)(__force unsigned long )csum, csum); +return 1 ; }
@@ -1236,7 +1315,7 @@static inline void myri10ge_check_statblock (struct myri10ge_priv *mgp) { -struct mcp_irq_data *stats = mgp->ss.fw_stats; +struct mcp_irq_data *stats = mgp->ss[0 ].fw_stats;if (unlikely (stats->stats_updated)) {unsigned link_up =ntohl (stats->link_up);
@@ -1302,6 +1381,13 @@u32 send_done_count;int i; +/* an interrupt on a non-zero slice is implicitly valid +* since MSI-X irqs are not shared */ +if (ss != mgp->ss) { +netif_rx_schedule (ss->dev, &ss->napi); +return (IRQ_HANDLED ); + } +/* make sure it is our IRQ, and that the DMA has finished */ if (unlikely (!stats->valid))return (IRQ_NONE );
@@ -1311,7 +1397,7 @@if (stats->valid &1 )netif_rx_schedule (ss->dev, &ss->napi); -if (!mgp->msi_enabled) { +if (!mgp->msi_enabled && !mgp->msix_enabled) {put_be32 (0 , mgp->irq_deassert);if (!myri10ge_deassert_wait) stats->valid =0 ;
@@ -1446,10 +1532,10 @@ {struct myri10ge_priv *mgp =netdev_priv (netdev); - ring->rx_mini_max_pending = mgp->ss.rx_small.mask +1 ; - ring->rx_max_pending = mgp->ss.rx_big.mask +1 ; + ring->rx_mini_max_pending = mgp->ss[0 ].rx_small.mask +1 ; + ring->rx_max_pending = mgp->ss[0 ].rx_big.mask +1 ; ring->rx_jumbo_max_pending =0 ; - ring->tx_max_pending = mgp->ss.rx_small.mask +1 ; + ring->tx_max_pending = mgp->ss[0 ].rx_small.mask +1 ; ring->rx_mini_pending = ring->rx_mini_max_pending; ring->rx_pending = ring->rx_max_pending; ring->rx_jumbo_pending = ring->rx_jumbo_max_pending;
@@ -1497,7 +1583,7 @@"tx_aborted_errors" ,"tx_carrier_errors" ,"tx_fifo_errors" ,"tx_heartbeat_errors" ,"tx_window_errors" ,/* device-specific stats */ -"tx_boundary" ,"WC" ,"irq" ,"MSI" , +"tx_boundary" ,"WC" ,"irq" ,"MSI" ,"MSIX" ,"read_dma_bw_MBs" ,"write_dma_bw_MBs" ,"read_write_dma_bw_MBs" ,"serial_number" ,"watchdog_resets" , "link_changes", "link_up", "dropped_link_overflow",
@@ -1524,23 +1610,31 @@static void myri10ge_get_strings (struct net_device *netdev,u32 stringset,u8 * data) { +struct myri10ge_priv *mgp =netdev_priv (netdev); +int i; +switch (stringset) {case ETH_SS_STATS :memcpy (data, *myri10ge_gstrings_main_stats,sizeof (myri10ge_gstrings_main_stats)); data +=sizeof (myri10ge_gstrings_main_stats); -memcpy (data, *myri10ge_gstrings_slice_stats, -sizeof (myri10ge_gstrings_slice_stats)); - data +=sizeof (myri10ge_gstrings_slice_stats); +for (i =0 ; i < mgp->num_slices; i++) { +memcpy (data, *myri10ge_gstrings_slice_stats, +sizeof (myri10ge_gstrings_slice_stats)); + data +=sizeof (myri10ge_gstrings_slice_stats); + }break ; } }static int myri10ge_get_sset_count (struct net_device *netdev,int sset) { +struct myri10ge_priv *mgp =netdev_priv (netdev); +switch (sset) {case ETH_SS_STATS : -return MYRI10GE_MAIN_STATS_LEN +MYRI10GE_SLICE_STATS_LEN ; +return MYRI10GE_MAIN_STATS_LEN + + mgp->num_slices *MYRI10GE_SLICE_STATS_LEN ;default :return -EOPNOTSUPP ; }
@@ -1552,6 +1646,7 @@ {struct myri10ge_priv *mgp =netdev_priv (netdev);struct myri10ge_slice_state *ss; +int slice;int i;for (i =0 ; i <MYRI10GE_NET_STATS_LEN ; i++)
@@ -1561,6 +1656,7 @@ data[i++] = (unsigned int )mgp->wc_enabled; data[i++] = (unsigned int )mgp->pdev->irq; data[i++] = (unsigned int )mgp->msi_enabled; + data[i++] = (unsigned int )mgp->msix_enabled; data[i++] = (unsigned int )mgp->read_dma; data[i++] = (unsigned int )mgp->write_dma; data[i++] = (unsigned int )mgp->read_write_dma;
@@ -1569,7 +1665,7 @@ data[i++] = (unsigned int )mgp->link_changes;/* firmware stats are useful only in the first slice */ - ss = &mgp->ss; + ss = &mgp->ss[0 ]; data[i++] = (unsigned int )ntohl (ss->fw_stats->link_up); data[i++] = (unsigned int )ntohl (ss->fw_stats->dropped_link_overflow); data[i++] =
@@ -1585,24 +1681,27 @@ data[i++] = (unsigned int )ntohl (ss->fw_stats->dropped_no_small_buffer); data[i++] = (unsigned int )ntohl (ss->fw_stats->dropped_no_big_buffer); - data[i++] =0 ; - data[i++] = (unsigned int )ss->tx.pkt_start; - data[i++] = (unsigned int )ss->tx.pkt_done; - data[i++] = (unsigned int )ss->tx.req; - data[i++] = (unsigned int )ss->tx.done; - data[i++] = (unsigned int )ss->rx_small.cnt; - data[i++] = (unsigned int )ss->rx_big.cnt; - data[i++] = (unsigned int )ss->tx.wake_queue; - data[i++] = (unsigned int )ss->tx.stop_queue; - data[i++] = (unsigned int )ss->tx.linearized; - data[i++] = ss->rx_done.lro_mgr.stats.aggregated; - data[i++] = ss->rx_done.lro_mgr.stats.flushed; -if (ss->rx_done.lro_mgr.stats.flushed) - data[i++] = ss->rx_done.lro_mgr.stats.aggregated / - ss->rx_done.lro_mgr.stats.flushed; -else - data[i++] =0 ; - data[i++] = ss->rx_done.lro_mgr.stats.no_desc; +for (slice =0 ; slice < mgp->num_slices; slice++) { + ss = &mgp->ss[slice]; + data[i++] = slice; + data[i++] = (unsigned int )ss->tx.pkt_start; + data[i++] = (unsigned int )ss->tx.pkt_done; + data[i++] = (unsigned int )ss->tx.req; + data[i++] = (unsigned int )ss->tx.done; + data[i++] = (unsigned int )ss->rx_small.cnt; + data[i++] = (unsigned int )ss->rx_big.cnt; + data[i++] = (unsigned int )ss->tx.wake_queue; + data[i++] = (unsigned int )ss->tx.stop_queue; + data[i++] = (unsigned int )ss->tx.linearized; + data[i++] = ss->rx_done.lro_mgr.stats.aggregated; + data[i++] = ss->rx_done.lro_mgr.stats.flushed; +if (ss->rx_done.lro_mgr.stats.flushed) + data[i++] = ss->rx_done.lro_mgr.stats.aggregated / + ss->rx_done.lro_mgr.stats.flushed; +else + data[i++] =0 ; + data[i++] = ss->rx_done.lro_mgr.stats.no_desc; + } }static void myri10ge_set_msglevel (struct net_device *netdev,u32 value)
@@ -1645,12 +1744,15 @@struct net_device *dev = mgp->dev;int tx_ring_size, rx_ring_size;int tx_ring_entries, rx_ring_entries; -int i, status; +int i, slice, status;size_t bytes;/* get ring sizes */ + slice = ss - mgp->ss; + cmd.data0 = slice; status =myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_SEND_RING_SIZE , &cmd,0 ); tx_ring_size = cmd.data0; + cmd.data0 = slice; status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_RX_RING_SIZE , &cmd,0 );if (status !=0 )return status;
@@ -1715,15 +1817,17 @@ mgp->small_bytes + MXGEFW_PAD, 0);if (ss->rx_small.fill_cnt < ss->rx_small.mask +1 ) { -printk (KERN_ERR "myri10ge: %s: alloced only %d small bufs\n" , - dev->name, ss->rx_small.fill_cnt); +printk (KERN_ERR +"myri10ge: %s:slice-%d: alloced only %d small bufs\n" , + dev->name, slice, ss->rx_small.fill_cnt); goto abort_with_rx_small_ring; }myri10ge_alloc_rx_pages (mgp, &ss->rx_big, mgp->big_bytes,0 );if (ss->rx_big.fill_cnt < ss->rx_big.mask +1 ) { -printk (KERN_ERR "myri10ge: %s: alloced only %d big bufs\n" , - dev->name, ss->rx_big.fill_cnt); +printk (KERN_ERR +"myri10ge: %s:slice-%d: alloced only %d big bufs\n" , + dev->name, slice, ss->rx_big.fill_cnt); goto abort_with_rx_big_ring; }
@@ -1775,6 +1879,10 @@struct myri10ge_tx_buf *tx;int i, len, idx; +/* If not allocated, skip it */ +if (ss->tx.req_list ==NULL ) +return ; +for (i = ss->rx_big.cnt; i < ss->rx_big.fill_cnt; i++) { idx = i & ss->rx_big.mask;if (i == ss->rx_big.fill_cnt -1 )
@@ -1837,25 +1945,67 @@static int myri10ge_request_irq (struct myri10ge_priv *mgp) {struct pci_dev *pdev = mgp->pdev; +struct myri10ge_slice_state *ss; +struct net_device *netdev = mgp->dev; +int i;int status; + mgp->msi_enabled =0 ; + mgp->msix_enabled =0 ; + status =0 ;if (myri10ge_msi) { - status =pci_enable_msi (pdev); -if (status !=0 ) -dev_err (&pdev->dev, -"Error %d setting up MSI; falling back to xPIC\n" , - status); -else - mgp->msi_enabled =1 ; - }else { - mgp->msi_enabled =0 ; +if (mgp->num_slices >1 ) { + status = +pci_enable_msix (pdev, mgp->msix_vectors, + mgp->num_slices); +if (status ==0 ) { + mgp->msix_enabled =1 ; + }else { +dev_err (&pdev->dev, +"Error %d setting up MSI-X\n" , status); +return status; + } + } +if (mgp->msix_enabled ==0 ) { + status =pci_enable_msi (pdev); +if (status !=0 ) { +dev_err (&pdev->dev, +"Error %d setting up MSI; falling back to xPIC\n" , + status); + }else { + mgp->msi_enabled =1 ; + } + } } - status =request_irq (pdev->irq, myri10ge_intr,IRQF_SHARED , - mgp->dev->name, mgp); -if (status !=0 ) { -dev_err (&pdev->dev,"failed to allocate IRQ\n" ); -if (mgp->msi_enabled) -pci_disable_msi (pdev); +if (mgp->msix_enabled) { +for (i =0 ; i < mgp->num_slices; i++) { + ss = &mgp->ss[i]; +snprintf (ss->irq_desc,sizeof (ss->irq_desc), +"%s:slice-%d" , netdev->name, i); + status =request_irq (mgp->msix_vectors[i].vector, + myri10ge_intr,0 , ss->irq_desc, + ss); +if (status !=0 ) { +dev_err (&pdev->dev, +"slice %d failed to allocate IRQ\n" , i); + i--; +while (i >=0 ) { +free_irq (mgp->msix_vectors[i].vector, + &mgp->ss[i]); + i--; + } +pci_disable_msix (pdev); +return status; + } + } + }else { + status =request_irq (pdev->irq, myri10ge_intr,IRQF_SHARED , + mgp->dev->name, &mgp->ss[0 ]); +if (status !=0 ) { +dev_err (&pdev->dev,"failed to allocate IRQ\n" ); +if (mgp->msi_enabled) +pci_disable_msi (pdev); + } }return status; }
@@ -1863,10 +2013,18 @@static void myri10ge_free_irq (struct myri10ge_priv *mgp) {struct pci_dev *pdev = mgp->pdev; +int i; -free_irq (pdev->irq, mgp); +if (mgp->msix_enabled) { +for (i =0 ; i < mgp->num_slices; i++) +free_irq (mgp->msix_vectors[i].vector, &mgp->ss[i]); + }else { +free_irq (pdev->irq, &mgp->ss[0 ]); + }if (mgp->msi_enabled)pci_disable_msi (pdev); +if (mgp->msix_enabled) +pci_disable_msix (pdev); } static int
@@ -1928,7 +2086,6 @@return 0 ; } -#if 0 static int myri10ge_get_txrx (struct myri10ge_priv *mgp,int slice) {struct myri10ge_cmd cmd;
@@ -1996,14 +2153,15 @@ }return 0 ; } -#endif static int myri10ge_open (struct net_device *dev) { +struct myri10ge_slice_state *ss;struct myri10ge_priv *mgp =netdev_priv (dev);struct myri10ge_cmd cmd; +int i, status, big_pow2, slice; +u8 *itable;struct net_lro_mgr *lro_mgr; -int status, big_pow2;if (mgp->running !=MYRI10GE_ETH_STOPPED )return -EBUSY ;
@@ -2015,6 +2173,48 @@ goto abort_with_nothing; } +if (mgp->num_slices >1 ) { + cmd.data0 = mgp->num_slices; + cmd.data1 =1 ;/* use MSI-X */ + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_ENABLE_RSS_QUEUES , + &cmd,0 ); +if (status !=0 ) { +printk (KERN_ERR +"myri10ge: %s: failed to set number of slices\n" , + dev->name); + goto abort_with_nothing; + } +/* setup the indirection table */ + cmd.data0 = mgp->num_slices; + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_RSS_TABLE_SIZE , + &cmd,0 ); + + status |=myri10ge_send_cmd (mgp, +MXGEFW_CMD_GET_RSS_TABLE_OFFSET , + &cmd,0 ); +if (status !=0 ) { +printk (KERN_ERR +"myri10ge: %s: failed to setup rss tables\n" , + dev->name); + } + +/* just enable an identity mapping */ + itable = mgp->sram + cmd.data0; +for (i =0 ; i < mgp->num_slices; i++) +__raw_writeb (i, &itable[i]); + + cmd.data0 =1 ; + cmd.data1 = myri10ge_rss_hash; + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_RSS_ENABLE , + &cmd,0 ); +if (status !=0 ) { +printk (KERN_ERR +"myri10ge: %s: failed to enable slices\n" , + dev->name); + goto abort_with_nothing; + } + } + status =myri10ge_request_irq (mgp);if (status !=0 ) goto abort_with_nothing;
@@ -2038,41 +2238,6 @@if (myri10ge_small_bytes >0 ) mgp->small_bytes = myri10ge_small_bytes; -/* get the lanai pointers to the send and receive rings */ - - status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_SEND_OFFSET , &cmd,0 ); - mgp->ss.tx.lanai = - (struct mcp_kreq_ether_send __iomem *)(mgp->sram + cmd.data0); - - status |= -myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_SMALL_RX_OFFSET , &cmd,0 ); - mgp->ss.rx_small.lanai = - (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0); - - status |=myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_BIG_RX_OFFSET , &cmd,0 ); - mgp->ss.rx_big.lanai = - (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0); - -if (status !=0 ) { -printk (KERN_ERR -"myri10ge: %s: failed to get ring sizes or locations\n" , - dev->name); - mgp->running =MYRI10GE_ETH_STOPPED ; - goto abort_with_irq; - } - -if (myri10ge_wcfifo && mgp->wc_enabled) { - mgp->ss.tx.wc_fifo = (u8 __iomem *) mgp->sram +MXGEFW_ETH_SEND_4 ; - mgp->ss.rx_small.wc_fifo = - (u8 __iomem *) mgp->sram +MXGEFW_ETH_RECV_SMALL ; - mgp->ss.rx_big.wc_fifo = - (u8 __iomem *) mgp->sram +MXGEFW_ETH_RECV_BIG ; - }else { - mgp->ss.tx.wc_fifo =NULL ; - mgp->ss.rx_small.wc_fifo =NULL ; - mgp->ss.rx_big.wc_fifo =NULL ; - } -/* Firmware needs the big buff size as a power of 2. Lie and * tell him the buffer is larger, because we only use 1 * buffer/pkt, and the mtu will prevent overruns.
@@ -2087,9 +2252,44 @@ mgp->big_bytes = big_pow2; } - status =myri10ge_allocate_rings (&mgp->ss); -if (status !=0 ) - goto abort_with_irq; +/* setup the per-slice data structures */ +for (slice =0 ; slice < mgp->num_slices; slice++) { + ss = &mgp->ss[slice]; + + status =myri10ge_get_txrx (mgp, slice); +if (status !=0 ) { +printk (KERN_ERR +"myri10ge: %s: failed to get ring sizes or locations\n" , + dev->name); + goto abort_with_rings; + } + status =myri10ge_allocate_rings (ss); +if (status !=0 ) + goto abort_with_rings; +if (slice ==0 ) + status =myri10ge_set_stats (mgp, slice); +if (status) { +printk (KERN_ERR +"myri10ge: %s: Couldn't set stats DMA\n" , + dev->name); + goto abort_with_rings; + } + + lro_mgr = &ss->rx_done.lro_mgr; + lro_mgr->dev = dev; + lro_mgr->features =LRO_F_NAPI ; + lro_mgr->ip_summed =CHECKSUM_COMPLETE ; + lro_mgr->ip_summed_aggr =CHECKSUM_UNNECESSARY ; + lro_mgr->max_desc =MYRI10GE_MAX_LRO_DESCRIPTORS ; + lro_mgr->lro_arr = ss->rx_done.lro_desc; + lro_mgr->get_frag_header = myri10ge_get_frag_header; + lro_mgr->max_aggr = myri10ge_lro_max_pkts; +if (lro_mgr->max_aggr >MAX_SKB_FRAGS ) + lro_mgr->max_aggr =MAX_SKB_FRAGS ; + +/* must happen prior to any irq */ +napi_enable (&(ss)->napi); + }/* now give firmware buffers sizes, and MTU */ cmd.data0 = dev->mtu +ETH_HLEN +VLAN_HLEN ;
@@ -2106,25 +2306,15 @@ goto abort_with_rings; } - cmd.data0 =MYRI10GE_LOWPART_TO_U32 (mgp->ss.fw_stats_bus); - cmd.data1 =MYRI10GE_HIGHPART_TO_U32 (mgp->ss.fw_stats_bus); - cmd.data2 =sizeof (struct mcp_irq_data ); - status =myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_STATS_DMA_V2 , &cmd,0 ); -if (status == -ENOSYS ) { -dma_addr_t bus = mgp->ss.fw_stats_bus; - bus += offsetof(struct mcp_irq_data , send_done_count); - cmd.data0 =MYRI10GE_LOWPART_TO_U32 (bus); - cmd.data1 =MYRI10GE_HIGHPART_TO_U32 (bus); - status =myri10ge_send_cmd (mgp, -MXGEFW_CMD_SET_STATS_DMA_OBSOLETE , - &cmd,0 ); -/* Firmware cannot support multicast without STATS_DMA_V2 */ - mgp->fw_multicast_support =0 ; - }else { - mgp->fw_multicast_support =1 ; - } -if (status) { -printk (KERN_ERR "myri10ge: %s: Couldn't set stats DMA\n" , +/* +* Set Linux style TSO mode; this is needed only on newer +* firmware versions. Older versions default to Linux +* style TSO +*/ + cmd.data0 =0 ; + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_SET_TSO_MODE , &cmd,0 ); +if (status && status != -ENOSYS ) { +printk (KERN_ERR "myri10ge: %s: Couldn't set TSO mode\n" , dev->name); goto abort_with_rings; }
@@ -2132,21 +2322,6 @@ mgp->link_state = ~0U ; mgp->rdma_tags_available =15 ; - lro_mgr = &mgp->ss.rx_done.lro_mgr; - lro_mgr->dev = dev; - lro_mgr->features =LRO_F_NAPI ; - lro_mgr->ip_summed =CHECKSUM_COMPLETE ; - lro_mgr->ip_summed_aggr =CHECKSUM_UNNECESSARY ; - lro_mgr->max_desc =MYRI10GE_MAX_LRO_DESCRIPTORS ; - lro_mgr->lro_arr = mgp->ss.rx_done.lro_desc; - lro_mgr->get_frag_header = myri10ge_get_frag_header; - lro_mgr->max_aggr = myri10ge_lro_max_pkts; - lro_mgr->frag_align_pad =2 ; -if (lro_mgr->max_aggr >MAX_SKB_FRAGS ) - lro_mgr->max_aggr =MAX_SKB_FRAGS ; - -napi_enable (&mgp->ss.napi);/* must happen prior to any irq */ - status =myri10ge_send_cmd (mgp,MXGEFW_CMD_ETHERNET_UP , &cmd,0 );if (status) { printk(KERN_ERR "myri10ge: %s: Couldn't bring up link\n",
@@ -2154,8 +2329,6 @@ goto abort_with_rings; } - mgp->ss.tx.wake_queue =0 ; - mgp->ss.tx.stop_queue =0 ; mgp->running =MYRI10GE_ETH_RUNNING ; mgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout *HZ ;add_timer (&mgp->watchdog_timer);
@@ -2163,9 +2336,9 @@return 0 ; abort_with_rings: -myri10ge_free_rings (&mgp->ss); +for (i =0 ; i < mgp->num_slices; i++) +myri10ge_free_rings (&mgp->ss[i]); -abort_with_irq:myri10ge_free_irq (mgp); abort_with_nothing:
@@ -2178,16 +2351,19 @@struct myri10ge_priv *mgp =netdev_priv (dev);struct myri10ge_cmd cmd;int status, old_down_cnt; +int i;if (mgp->running !=MYRI10GE_ETH_RUNNING )return 0 ; -if (mgp->ss.tx.req_bytes ==NULL ) +if (mgp->ss[0 ].tx.req_bytes ==NULL )return 0 ;del_timer_sync (&mgp->watchdog_timer); mgp->running =MYRI10GE_ETH_STOPPING ; -napi_disable (&mgp->ss.napi); +for (i =0 ; i < mgp->num_slices; i++) { +napi_disable (&mgp->ss[i].napi); + }netif_carrier_off (dev);netif_stop_queue (dev); old_down_cnt = mgp->down_cnt;
@@ -2203,7 +2379,8 @@netif_tx_disable (dev);myri10ge_free_irq (mgp); -myri10ge_free_rings (&mgp->ss); +for (i =0 ; i < mgp->num_slices; i++) +myri10ge_free_rings (&mgp->ss[i]); mgp->running =MYRI10GE_ETH_STOPPED ;return 0 ;
@@ -2324,7 +2501,7 @@u8 flags, odd_flag;/* always transmit through slot 0 */ - ss = &mgp->ss; + ss = mgp->ss; tx = &ss->tx; again: req = tx->req_list;
@@ -2629,7 +2806,21 @@static struct net_device_stats *myri10ge_get_stats (struct net_device *dev) {struct myri10ge_priv *mgp =netdev_priv (dev); -return &mgp->stats; +struct myri10ge_slice_netstats *slice_stats; +struct net_device_stats *stats = &mgp->stats; +int i; + +memset (stats,0 ,sizeof (*stats)); +for (i =0 ; i < mgp->num_slices; i++) { + slice_stats = &mgp->ss[i].stats; + stats->rx_packets += slice_stats->rx_packets; + stats->tx_packets += slice_stats->tx_packets; + stats->rx_bytes += slice_stats->rx_bytes; + stats->tx_bytes += slice_stats->tx_bytes; + stats->rx_dropped += slice_stats->rx_dropped; + stats->tx_dropped += slice_stats->tx_dropped; + } +return stats; }static void myri10ge_set_multicast_list (struct net_device *dev)
@@ -2840,10 +3031,10 @@* * If the driver can neither enable ECRC nor verify that it has * already been enabled, then it must use a firmware image which works -* around unaligned completion packets (myri10ge_ethp_z8e.dat), and it +* around unaligned completion packets (myri10ge_rss_ethp_z8e.dat), and it * should also ensure that it never gives the device a Read-DMA which is * larger than 2KB by setting the tx_boundary to 2KB. If ECRC is -* enabled, then the driver should use the aligned (myri10ge_eth_z8e.dat) +* enabled, then the driver should use the aligned (myri10ge_rss_eth_z8e.dat) * firmware image, and set tx_boundary to 4KB. */
@@ -2872,7 +3063,7 @@* completions) in order to see if it works on this host. */ mgp->fw_name = myri10ge_fw_aligned; - status =myri10ge_load_firmware (mgp); + status =myri10ge_load_firmware (mgp,1 );if (status !=0 ) { goto abort; }
@@ -3053,6 +3244,7 @@struct myri10ge_tx_buf *tx;u32 reboot;int status; +int i;u16 cmd, vendor; mgp->watchdog_resets++;
@@ -3100,20 +3292,26 @@printk (KERN_ERR "myri10ge: %s: device timeout, resetting\n" , mgp->dev->name); - tx = &mgp->ss.tx; -printk (KERN_INFO "myri10ge: %s: %d %d %d %d %d\n" , - mgp->dev->name, tx->req, tx->done, - tx->pkt_start, tx->pkt_done, - (int )ntohl (mgp->ss.fw_stats->send_done_count)); -msleep (2000 ); -printk (KERN_INFO "myri10ge: %s: %d %d %d %d %d\n" , - mgp->dev->name, tx->req, tx->done, - tx->pkt_start, tx->pkt_done, - (int )ntohl (mgp->ss.fw_stats->send_done_count)); +for (i =0 ; i < mgp->num_slices; i++) { + tx = &mgp->ss[i].tx; +printk (KERN_INFO +"myri10ge: %s: (%d): %d %d %d %d %d\n" , + mgp->dev->name, i, tx->req, tx->done, + tx->pkt_start, tx->pkt_done, + (int )ntohl (mgp->ss[i].fw_stats-> + send_done_count)); +msleep (2000 ); +printk (KERN_INFO +"myri10ge: %s: (%d): %d %d %d %d %d\n" , + mgp->dev->name, i, tx->req, tx->done, + tx->pkt_start, tx->pkt_done, + (int )ntohl (mgp->ss[i].fw_stats-> + send_done_count)); + } }rtnl_lock ();myri10ge_close (mgp->dev); - status =myri10ge_load_firmware (mgp); + status =myri10ge_load_firmware (mgp,1 );if (status !=0 )printk (KERN_ERR "myri10ge: %s: failed to load firmware\n" , mgp->dev->name);
@@ -3133,50 +3331,59 @@ {struct myri10ge_priv *mgp;struct myri10ge_slice_state *ss; +int i, reset_needed;u32 rx_pause_cnt; mgp = (struct myri10ge_priv *)arg; - rx_pause_cnt =ntohl (mgp->ss.fw_stats->dropped_pause); + rx_pause_cnt =ntohl (mgp->ss[0 ].fw_stats->dropped_pause); +for (i =0 , reset_needed =0 ; + i < mgp->num_slices && reset_needed ==0 ; ++i) { - ss = &mgp->ss; -if (ss->rx_small.watchdog_needed) { -myri10ge_alloc_rx_pages (mgp, &ss->rx_small, - mgp->small_bytes +MXGEFW_PAD ,1 ); -if (ss->rx_small.fill_cnt - ss->rx_small.cnt >= - myri10ge_fill_thresh) - ss->rx_small.watchdog_needed =0 ; - } -if (ss->rx_big.watchdog_needed) { -myri10ge_alloc_rx_pages (mgp, &ss->rx_big, mgp->big_bytes,1 ); -if (ss->rx_big.fill_cnt - ss->rx_big.cnt >= - myri10ge_fill_thresh) - ss->rx_big.watchdog_needed =0 ; - } - -if (ss->tx.req != ss->tx.done && - ss->tx.done == ss->watchdog_tx_done && - ss->watchdog_tx_req != ss->watchdog_tx_done) { -/* nic seems like it might be stuck.. */ -if (rx_pause_cnt != mgp->watchdog_pause) { -if (net_ratelimit ()) -printk (KERN_WARNING "myri10ge %s:" -"TX paused, check link partner\n" , - mgp->dev->name); - }else { -schedule_work (&mgp->watchdog_work); -return ; + ss = &mgp->ss[i]; +if (ss->rx_small.watchdog_needed) { +myri10ge_alloc_rx_pages (mgp, &ss->rx_small, + mgp->small_bytes +MXGEFW_PAD , +1 ); +if (ss->rx_small.fill_cnt - ss->rx_small.cnt >= + myri10ge_fill_thresh) + ss->rx_small.watchdog_needed =0 ; + } +if (ss->rx_big.watchdog_needed) { +myri10ge_alloc_rx_pages (mgp, &ss->rx_big, + mgp->big_bytes,1 ); +if (ss->rx_big.fill_cnt - ss->rx_big.cnt >= + myri10ge_fill_thresh) + ss->rx_big.watchdog_needed =0 ; + } + +if (ss->tx.req != ss->tx.done && + ss->tx.done == ss->watchdog_tx_done && + ss->watchdog_tx_req != ss->watchdog_tx_done) { +/* nic seems like it might be stuck.. */ +if (rx_pause_cnt != mgp->watchdog_pause) { +if (net_ratelimit ()) +printk (KERN_WARNING "myri10ge %s:" +"TX paused, check link partner\n" , + mgp->dev->name); + }else { + reset_needed =1 ; + } } + ss->watchdog_tx_done = ss->tx.done; + ss->watchdog_tx_req = ss->tx.req; } -/* rearm timer */ -mod_timer (&mgp->watchdog_timer, - jiffies + myri10ge_watchdog_timeout *HZ ); - ss->watchdog_tx_done = ss->tx.done; - ss->watchdog_tx_req = ss->tx.req; mgp->watchdog_pause = rx_pause_cnt; + +if (reset_needed) { +schedule_work (&mgp->watchdog_work); + }else { +/* rearm timer */ +mod_timer (&mgp->watchdog_timer, + jiffies + myri10ge_watchdog_timeout *HZ ); + } } -#if 0 static void myri10ge_free_slices (struct myri10ge_priv *mgp) {struct myri10ge_slice_state *ss;
@@ -3360,14 +3567,12 @@ mgp->fw_name = old_fw;myri10ge_load_firmware (mgp,0 ); } -#endif static int myri10ge_probe (struct pci_dev *pdev,const struct pci_device_id *ent) {struct net_device *netdev;struct myri10ge_priv *mgp;struct device *dev = &pdev->dev; -size_t bytes;int i;int status = -ENXIO ;int dac_enabled;
@@ -3382,7 +3587,6 @@ mgp =netdev_priv (netdev); mgp->dev = netdev; -netif_napi_add (netdev, &mgp->ss.napi, myri10ge_poll, myri10ge_napi_weight); mgp->pdev = pdev; mgp->csum_flag =MXGEFW_FLAGS_CKSUM ; mgp->pause = myri10ge_flow_control;
@@ -3428,11 +3632,6 @@if (mgp->cmd ==NULL ) goto abort_with_netdev; - mgp->ss.fw_stats =dma_alloc_coherent (&pdev->dev,sizeof (*mgp->ss.fw_stats), - &mgp->ss.fw_stats_bus,GFP_KERNEL ); -if (mgp->ss.fw_stats ==NULL ) - goto abort_with_cmd; - mgp->board_span =pci_resource_len (pdev,0 ); mgp->iomem_base =pci_resource_start (pdev,0 ); mgp->mtrr =-1 ;
@@ -3469,26 +3668,24 @@for (i =0 ; i <ETH_ALEN ; i++) netdev->dev_addr[i] = mgp->mac_addr[i]; -/* allocate rx done ring */ - bytes = mgp->max_intr_slots *sizeof (*mgp->ss.rx_done.entry); - mgp->ss.rx_done.entry =dma_alloc_coherent (&pdev->dev, bytes, - &mgp->ss.rx_done.bus,GFP_KERNEL ); -if (mgp->ss.rx_done.entry ==NULL ) - goto abort_with_ioremap; -memset (mgp->ss.rx_done.entry,0 , bytes); -myri10ge_select_firmware (mgp); - status =myri10ge_load_firmware (mgp); + status =myri10ge_load_firmware (mgp,1 );if (status !=0 ) {dev_err (&pdev->dev,"failed to load firmware\n" ); - goto abort_with_rx_done; + goto abort_with_ioremap; + } +myri10ge_probe_slices (mgp); + status =myri10ge_alloc_slices (mgp); +if (status !=0 ) { +dev_err (&pdev->dev,"failed to alloc slice state\n" ); + goto abort_with_firmware; } status =myri10ge_reset (mgp);if (status !=0 ) {dev_err (&pdev->dev,"failed reset\n" ); - goto abort_with_firmware; + goto abort_with_slices; }pci_set_drvdata (pdev, mgp);
@@ -3533,24 +3730,27 @@dev_err (&pdev->dev,"register_netdev failed: %d\n" , status); goto abort_with_state; } -dev_info (dev,"%s IRQ %d, tx bndry %d, fw %s, WC %s\n" , - (mgp->msi_enabled ?"MSI" :"xPIC" ), - netdev->irq, mgp->tx_boundary, mgp->fw_name, - (mgp->wc_enabled ?"Enabled" :"Disabled" )); +if (mgp->msix_enabled) +dev_info (dev,"%d MSI-X IRQs, tx bndry %d, fw %s, WC %s\n" , + mgp->num_slices, mgp->tx_boundary, mgp->fw_name, + (mgp->wc_enabled ?"Enabled" :"Disabled" )); +else +dev_info (dev,"%s IRQ %d, tx bndry %d, fw %s, WC %s\n" , + mgp->msi_enabled ?"MSI" :"xPIC" , + netdev->irq, mgp->tx_boundary, mgp->fw_name, + (mgp->wc_enabled ?"Enabled" :"Disabled" ));return 0 ; abort_with_state:pci_restore_state (pdev); +abort_with_slices: +myri10ge_free_slices (mgp); + abort_with_firmware:myri10ge_dummy_rdma (mgp,0 ); -abort_with_rx_done: - bytes = mgp->max_intr_slots *sizeof (*mgp->ss.rx_done.entry); -dma_free_coherent (&pdev->dev, bytes, - mgp->ss.rx_done.entry, mgp->ss.rx_done.bus); - abort_with_ioremap:iounmap (mgp->sram);
@@ -3559,10 +3759,6 @@if (mgp->mtrr >=0 )mtrr_del (mgp->mtrr, mgp->iomem_base, mgp->board_span);#endif -dma_free_coherent (&pdev->dev,sizeof (*mgp->ss.fw_stats), - mgp->ss.fw_stats, mgp->ss.fw_stats_bus); - -abort_with_cmd:dma_free_coherent (&pdev->dev,sizeof (*mgp->cmd), mgp->cmd, mgp->cmd_bus);
@@ -3583,7 +3779,6 @@ {struct myri10ge_priv *mgp;struct net_device *netdev; -size_t bytes; mgp =pci_get_drvdata (pdev);if (mgp ==NULL )
@@ -3598,19 +3793,15 @@/* avoid a memory leak */ pci_restore_state (pdev); - bytes = mgp->max_intr_slots *sizeof (*mgp->ss.rx_done.entry); -dma_free_coherent (&pdev->dev, bytes, - mgp->ss.rx_done.entry, mgp->ss.rx_done.bus); -iounmap (mgp->sram);#ifdef CONFIG_MTRR if (mgp->mtrr >=0 )mtrr_del (mgp->mtrr, mgp->iomem_base, mgp->board_span);#endif -dma_free_coherent (&pdev->dev,sizeof (*mgp->ss.fw_stats), - mgp->ss.fw_stats, mgp->ss.fw_stats_bus); - +myri10ge_free_slices (mgp); +if (mgp->msix_vectors !=NULL ) +kfree (mgp->msix_vectors);dma_free_coherent (&pdev->dev,sizeof (*mgp->cmd), mgp->cmd, mgp->cmd_bus);
@@ -3643,6 +3834,15 @@ {printk (KERN_INFO "%s: Version %s\n" , myri10ge_driver.name,MYRI10GE_VERSION_STR ); + +if (myri10ge_rss_hash >MXGEFW_RSS_HASH_TYPE_SRC_PORT || + myri10ge_rss_hash <MXGEFW_RSS_HASH_TYPE_IPV4 ) { +printk (KERN_ERR +"%s: Illegal rssh hash type %d, defaulting to source port\n" , + myri10ge_driver.name, myri10ge_rss_hash); + myri10ge_rss_hash =MXGEFW_RSS_HASH_TYPE_SRC_PORT ; + } +return pci_register_driver (&myri10ge_driver); }
PATCH 15/16 myri10ge: add Direct Cache Access support
In reply to Brice GoglinAdd I/O AT DCA (Direct Cache Access) support.
--- drivers/net/myri10ge/myri10ge.c | 146 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 145 insertions(+), 1 deletion(-)
drivers/net/myri10ge/myri10ge.c +145 -1
@@ -49,6 +49,7 @@#include <linux/if_ether.h> #include <linux/if_vlan.h> #include <linux/inet_lro.h> +#include <linux/dca.h> #include <linux/ip.h> #include <linux/inet.h> #include <linux/in.h>
@@ -185,6 +186,11 @@dma_addr_t fw_stats_bus;int watchdog_tx_done;int watchdog_tx_req; +#ifdef CONFIG_DCA +int cached_dca_tag; +int cpu; +__be32 __iomem *dca_tag; +#endif char irq_desc[32 ]; };
@@ -212,6 +218,9 @@int msi_enabled;int msix_enabled;struct msix_entry *msix_vectors; +#ifdef CONFIG_DCA +int dca_enabled; +#endif u32 link_state;unsigned int rdma_tags_available;int intr_coal_delay;
@@ -335,6 +344,10 @@module_param (myri10ge_rss_hash, int,S_IRUGO );MODULE_PARM_DESC (myri10ge_rss_hash,"Type of RSS hashing to do" ); +static int myri10ge_dca =1 ; +module_param (myri10ge_dca, int,S_IRUGO ); +MODULE_PARM_DESC (myri10ge_dca,"Enable DCA if possible" ); +#define MYRI10GE_FW_OFFSET 1024*1024#define MYRI10GE_HIGHPART_TO_U32 (X ) \ (sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
@@ -878,6 +891,9 @@struct myri10ge_slice_state *ss;int i, status;size_t bytes; +#ifdef CONFIG_DCA +unsigned long dca_tag_off; +#endif /* try to send a reset command to the card to see if it * is alive */
@@ -970,6 +986,20 @@ }put_be32 (htonl (mgp->intr_coal_delay), mgp->intr_coal_delay_ptr); +#ifdef CONFIG_DCA + status =myri10ge_send_cmd (mgp,MXGEFW_CMD_GET_DCA_OFFSET , &cmd,0 ); + dca_tag_off = cmd.data0; +for (i =0 ; i < mgp->num_slices; i++) { + ss = &mgp->ss[i]; +if (status ==0 ) { + ss->dca_tag = (__iomem __be32 *) + (mgp->sram + dca_tag_off +4 * i); + }else { + ss->dca_tag =NULL ; + } + } +#endif /* CONFIG_DCA */ +/* reset mcp/driver shared state back to 0 */ mgp->link_changes =0 ;
@@ -995,6 +1025,77 @@return status; } +#ifdef CONFIG_DCA +static void +myri10ge_write_dca (struct myri10ge_slice_state *ss,int cpu,int tag) +{ + ss->cpu = cpu; + ss->cached_dca_tag = tag; +put_be32 (htonl (tag), ss->dca_tag); +} + +static inline void myri10ge_update_dca (struct myri10ge_slice_state *ss) +{ +int cpu =get_cpu (); +int tag; + +if (cpu != ss->cpu) { + tag =dca_get_tag (cpu); +if (ss->cached_dca_tag != tag) +myri10ge_write_dca (ss, cpu, tag); + } +put_cpu (); +} + +static void myri10ge_setup_dca (struct myri10ge_priv *mgp) +{ +int err, i; +struct pci_dev *pdev = mgp->pdev; + +if (mgp->ss[0 ].dca_tag ==NULL || mgp->dca_enabled) +return ; +if (!myri10ge_dca) { +dev_err (&pdev->dev,"dca disabled by administrator\n" ); +return ; + } + err =dca_add_requester (&pdev->dev); +if (err) { +dev_err (&pdev->dev, +"dca_add_requester() failed, err=%d\n" , err); +return ; + } + mgp->dca_enabled =1 ; +for (i =0 ; i < mgp->num_slices; i++) +myri10ge_write_dca (&mgp->ss[i],-1 ,0 ); +} + +static void myri10ge_teardown_dca (struct myri10ge_priv *mgp) +{ +struct pci_dev *pdev = mgp->pdev; +int err; + +if (!mgp->dca_enabled) +return ; + mgp->dca_enabled =0 ; + err =dca_remove_requester (&pdev->dev); +} + +static int myri10ge_notify_dca_device (struct device *dev,void *data) +{ +struct myri10ge_priv *mgp; +unsigned long event; + + mgp =dev_get_drvdata (dev); + event = *(unsigned long *)data; + +if (event ==DCA_PROVIDER_ADD ) +myri10ge_setup_dca (mgp); +else if (event ==DCA_PROVIDER_REMOVE ) +myri10ge_teardown_dca (mgp); +return 0 ; +} +#endif /* CONFIG_DCA */ +static inline void myri10ge_submit_8rx (struct mcp_kreq_ether_recv __iomem * dst,struct mcp_kreq_ether_recv *src)
@@ -1362,6 +1463,11 @@struct net_device *netdev = ss->mgp->dev;int work_done; +#ifdef CONFIG_DCA +if (ss->mgp->dca_enabled) +myri10ge_update_dca (ss); +#endif +/* process as many rx events as NAPI will allow */ work_done =myri10ge_clean_rx_done (ss, budget);
@@ -1586,6 +1692,9 @@"tx_boundary" ,"WC" ,"irq" ,"MSI" ,"MSIX" ,"read_dma_bw_MBs" ,"write_dma_bw_MBs" ,"read_write_dma_bw_MBs" ,"serial_number" ,"watchdog_resets" , +#ifdef CONFIG_DCA +"dca_capable" ,"dca_enabled" , +#endif"link_changes" ,"link_up" ,"dropped_link_overflow" ,"dropped_link_error_or_filtered" , "dropped_pause", "dropped_bad_phy", "dropped_bad_crc32",
@@ -1662,6 +1771,10 @@ data[i++] = (unsigned int )mgp->read_write_dma; data[i++] = (unsigned int )mgp->serial_number; data[i++] = (unsigned int )mgp->watchdog_resets; +#ifdef CONFIG_DCA + data[i++] = (unsigned int )(mgp->ss[0 ].dca_tag !=NULL ); + data[i++] = (unsigned int )(mgp->dca_enabled); +#endif data[i++] = (unsigned int )mgp->link_changes;/* firmware stats are useful only in the first slice */
@@ -3687,7 +3800,9 @@dev_err (&pdev->dev,"failed reset\n" ); goto abort_with_slices; } - +#ifdef CONFIG_DCA +myri10ge_setup_dca (mgp); +#endif pci_set_drvdata (pdev, mgp);if ((myri10ge_initial_mtu +ETH_HLEN ) >MYRI10GE_MAX_ETHER_MTU ) myri10ge_initial_mtu =MYRI10GE_MAX_ETHER_MTU -ETH_HLEN ;
@@ -3788,6 +3903,9 @@ netdev = mgp->dev;unregister_netdev (netdev); +#ifdef CONFIG_DCA +myri10ge_teardown_dca (mgp); +#endif myri10ge_dummy_rdma (mgp,0 );/* avoid a memory leak */
@@ -3830,6 +3948,26 @@#endif }; +#ifdef CONFIG_DCA +static int +myri10ge_notify_dca (struct notifier_block *nb,unsigned long event,void *p) +{ +int err =driver_for_each_device (&myri10ge_driver.driver, +NULL , &event, + myri10ge_notify_dca_device); + +if (err) +return NOTIFY_BAD ; +return NOTIFY_DONE ; +} + +static struct notifier_block myri10ge_dca_notifier = { + .notifier_call = myri10ge_notify_dca, + .next =NULL , + .priority =0 , +}; +#endif /* CONFIG_DCA */ +static __init int myri10ge_init_module (void ) { printk(KERN_INFO "%s: Version %s\n", myri10ge_driver.name,
@@ -3842,6 +3980,9 @@ myri10ge_driver.name, myri10ge_rss_hash); myri10ge_rss_hash =MXGEFW_RSS_HASH_TYPE_SRC_PORT ; } +#ifdef CONFIG_DCA +dca_register_notify (&myri10ge_dca_notifier); +#endif return pci_register_driver (&myri10ge_driver); }
@@ -3850,6 +3991,9 @@ static __exit void myri10ge_cleanup_module(void) { +#ifdef CONFIG_DCA +dca_unregister_notify (&myri10ge_dca_notifier); +#endif pci_unregister_driver (&myri10ge_driver); }
PATCH 16/16 myri10ge: update driver version
In reply to Brice GoglinUpdate myri10ge driver version to 1.4.2-1.341
--- drivers/net/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/myri10ge/myri10ge.c +1 -1
@@ -76,7 +76,7 @@#include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.3.2-1.287" +#define MYRI10GE_VERSION_STR "1.4.2-1.342"MODULE_DESCRIPTION ("Myricom 10G driver (10GbE)" );MODULE_AUTHOR ("Maintainer: [email protected]" );