netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] myri10ge updates for 2.6.28
@ 2008-09-29  1:30 Brice Goglin
  2008-09-29  1:34 ` [PATCH 1/3] myri10ge: add multiqueue TX Brice Goglin
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Brice Goglin @ 2008-09-29  1:30 UTC (permalink / raw)
  To: Jeff Garzik, David S. Miller; +Cc: netdev

Hello Jeff and Dave or whoever is not on a trip :)

Here's the multiqueue TX patch for myri10ge again. And it is followed by
2 patches splitting the huge myri10ge.c into pieces (no functional
changes at all there). It's my first time sending a "git rename" patch,
I hope I did well :)

Please apply for 2.6.28.
thanks,
Brice

PS: These patches are against Dave's net-next tree. So, if you get yet
another strange conflict, I'd like to see the actual conflict. I still
don't understand what could have conflicted in the previous submission,
it did apply fine as well here :/


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] myri10ge: add multiqueue TX
  2008-09-29  1:30 [PATCH 0/3] myri10ge updates for 2.6.28 Brice Goglin
@ 2008-09-29  1:34 ` Brice Goglin
  2008-09-29  1:34 ` [PATCH 2/3] myri10ge: rename main file into myri10ge_main.c Brice Goglin
  2008-09-29  1:34 ` [PATCH 3/3] myri10ge: split main file into pieces Brice Goglin
  2 siblings, 0 replies; 4+ messages in thread
From: Brice Goglin @ 2008-09-29  1:34 UTC (permalink / raw)
  To: Jeff Garzik, David S. Miller; +Cc: netdev

Add multiqueue TX support to myri10ge.

Signed-off-by: Brice Goglin <brice@myri.com>
---
 drivers/net/myri10ge/myri10ge.c |  155 ++++++++++++++++++++++++++++++---------
 1 files changed, 121 insertions(+), 34 deletions(-)

diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 005f2aa..d9fcd2c 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -102,6 +102,8 @@ MODULE_LICENSE("Dual BSD/GPL");
 #define MYRI10GE_ALLOC_SIZE ((1 << MYRI10GE_ALLOC_ORDER) * PAGE_SIZE)
 #define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1)
 
+#define MYRI10GE_MAX_SLICES 32
+
 struct myri10ge_rx_buffer_state {
 	struct page *page;
 	int page_offset;
@@ -138,6 +140,8 @@ struct myri10ge_rx_buf {
 
 struct myri10ge_tx_buf {
 	struct mcp_kreq_ether_send __iomem *lanai;	/* lanai ptr for sendq */
+	__be32 __iomem *send_go;	/* "go" doorbell ptr */
+	__be32 __iomem *send_stop;	/* "stop" doorbell ptr */
 	struct mcp_kreq_ether_send *req_list;	/* host shadow of sendq */
 	char *req_bytes;
 	struct myri10ge_tx_buffer_state *info;
@@ -149,6 +153,7 @@ struct myri10ge_tx_buf {
 	int done ____cacheline_aligned;	/* transmit slots completed     */
 	int pkt_done;		/* packets completed */
 	int wake_queue;
+	int queue_active;
 };
 
 struct myri10ge_rx_done {
@@ -418,6 +423,12 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
 			return -ENOSYS;
 		} else if (result == MXGEFW_CMD_ERROR_UNALIGNED) {
 			return -E2BIG;
+		} else if (result == MXGEFW_CMD_ERROR_RANGE &&
+			   cmd == MXGEFW_CMD_ENABLE_RSS_QUEUES &&
+			   (data->
+			    data1 & MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES) !=
+			   0) {
+			return -ERANGE;
 		} else {
 			dev_err(&mgp->pdev->dev,
 				"command %d failed, result = %d\n",
@@ -947,9 +958,24 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
 		 */
 
 		cmd.data0 = mgp->num_slices;
-		cmd.data1 = 1;	/* use MSI-X */
+		cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;
+		if (mgp->dev->real_num_tx_queues > 1)
+			cmd.data1 |= MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES;
 		status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES,
 					   &cmd, 0);
+
+		/* Firmware older than 1.4.32 only supports multiple
+		 * RX queues, so if we get an error, first retry using a
+		 * single TX queue before giving up */
+		if (status != 0 && mgp->dev->real_num_tx_queues > 1) {
+			mgp->dev->real_num_tx_queues = 1;
+			cmd.data0 = mgp->num_slices;
+			cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;
+			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");
@@ -1317,6 +1343,7 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index)
 {
 	struct pci_dev *pdev = ss->mgp->pdev;
 	struct myri10ge_tx_buf *tx = &ss->tx;
+	struct netdev_queue *dev_queue;
 	struct sk_buff *skb;
 	int idx, len;
 
@@ -1350,11 +1377,31 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index)
 					       PCI_DMA_TODEVICE);
 		}
 	}
+
+	dev_queue = netdev_get_tx_queue(ss->dev, ss - ss->mgp->ss);
+	/*
+	 * Make a minimal effort to prevent the NIC from polling an
+	 * idle tx queue.  If we can't get the lock we leave the queue
+	 * active. In this case, either a thread was about to start
+	 * using the queue anyway, or we lost a race and the NIC will
+	 * waste some of its resources polling an inactive queue for a
+	 * while.
+	 */
+
+	if ((ss->mgp->dev->real_num_tx_queues > 1) &&
+	    __netif_tx_trylock(dev_queue)) {
+		if (tx->req == tx->done) {
+			tx->queue_active = 0;
+			put_be32(htonl(1), tx->send_stop);
+		}
+		__netif_tx_unlock(dev_queue);
+	}
+
 	/* start the queue if we've stopped it */
-	if (netif_queue_stopped(ss->dev)
+	if (netif_tx_queue_stopped(dev_queue)
 	    && tx->req - tx->done < (tx->mask >> 1)) {
 		tx->wake_queue++;
-		netif_wake_queue(ss->dev);
+		netif_tx_wake_queue(dev_queue);
 	}
 }
 
@@ -1482,9 +1529,9 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
 	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) {
+	/* an interrupt on a non-zero receive-only slice is implicitly
+	 * valid  since MSI-X irqs are not shared */
+	if ((mgp->dev->real_num_tx_queues == 1) && (ss != mgp->ss)) {
 		netif_rx_schedule(ss->dev, &ss->napi);
 		return (IRQ_HANDLED);
 	}
@@ -1526,7 +1573,9 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
 		barrier();
 	}
 
-	myri10ge_check_statblock(mgp);
+	/* Only slice 0 updates stats */
+	if (ss == mgp->ss)
+		myri10ge_check_statblock(mgp);
 
 	put_be32(htonl(3), ss->irq_claim + 1);
 	return (IRQ_HANDLED);
@@ -1884,6 +1933,7 @@ static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss)
 	/* ensure req_list entries are aligned to 8 bytes */
 	ss->tx.req_list = (struct mcp_kreq_ether_send *)
 	    ALIGN((unsigned long)ss->tx.req_bytes, 8);
+	ss->tx.queue_active = 0;
 
 	bytes = rx_ring_entries * sizeof(*ss->rx_small.shadow);
 	ss->rx_small.shadow = kzalloc(bytes, GFP_KERNEL);
@@ -2201,11 +2251,14 @@ static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)
 	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);
-
+	status = 0;
+	if (slice == 0 || (mgp->dev->real_num_tx_queues > 1)) {
+		cmd.data0 = slice;
+		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);
@@ -2217,6 +2270,10 @@ static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)
 	ss->rx_big.lanai = (struct mcp_kreq_ether_recv __iomem *)
 	    (mgp->sram + cmd.data0);
 
+	ss->tx.send_go = (__iomem __be32 *)
+	    (mgp->sram + MXGEFW_ETH_SEND_GO + 64 * slice);
+	ss->tx.send_stop = (__iomem __be32 *)
+	    (mgp->sram + MXGEFW_ETH_SEND_STOP + 64 * slice);
 	return status;
 
 }
@@ -2230,7 +2287,7 @@ static int myri10ge_set_stats(struct myri10ge_priv *mgp, int slice)
 	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);
+	cmd.data2 = sizeof(struct mcp_irq_data) | (slice << 16);
 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd, 0);
 	if (status == -ENOSYS) {
 		dma_addr_t bus = ss->fw_stats_bus;
@@ -2271,7 +2328,9 @@ static int myri10ge_open(struct net_device *dev)
 
 	if (mgp->num_slices > 1) {
 		cmd.data0 = mgp->num_slices;
-		cmd.data1 = 1;	/* use MSI-X */
+		cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;
+		if (mgp->dev->real_num_tx_queues > 1)
+			cmd.data1 |= MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES;
 		status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES,
 					   &cmd, 0);
 		if (status != 0) {
@@ -2292,6 +2351,7 @@ static int myri10ge_open(struct net_device *dev)
 			printk(KERN_ERR
 			       "myri10ge: %s: failed to setup rss tables\n",
 			       dev->name);
+			goto abort_with_nothing;
 		}
 
 		/* just enable an identity mapping */
@@ -2362,7 +2422,11 @@ static int myri10ge_open(struct net_device *dev)
 		status = myri10ge_allocate_rings(ss);
 		if (status != 0)
 			goto abort_with_rings;
-		if (slice == 0)
+
+		/* only firmware which supports multiple TX queues
+		 * supports setting up the tx stats on non-zero
+		 * slices */
+		if (slice == 0 || mgp->dev->real_num_tx_queues > 1)
 			status = myri10ge_set_stats(mgp, slice);
 		if (status) {
 			printk(KERN_ERR
@@ -2428,7 +2492,8 @@ static int myri10ge_open(struct net_device *dev)
 	mgp->running = MYRI10GE_ETH_RUNNING;
 	mgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout * HZ;
 	add_timer(&mgp->watchdog_timer);
-	netif_wake_queue(dev);
+	netif_tx_wake_all_queues(dev);
+
 	return 0;
 
 abort_with_rings:
@@ -2461,7 +2526,8 @@ static int myri10ge_close(struct net_device *dev)
 		napi_disable(&mgp->ss[i].napi);
 	}
 	netif_carrier_off(dev);
-	netif_stop_queue(dev);
+
+	netif_tx_stop_all_queues(dev);
 	old_down_cnt = mgp->down_cnt;
 	mb();
 	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0);
@@ -2566,18 +2632,23 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct mcp_kreq_ether_send *req;
 	struct myri10ge_tx_buf *tx;
 	struct skb_frag_struct *frag;
+	struct netdev_queue *netdev_queue;
 	dma_addr_t bus;
 	u32 low;
 	__be32 high_swapped;
 	unsigned int len;
 	int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments;
-	u16 pseudo_hdr_offset, cksum_offset;
+	u16 pseudo_hdr_offset, cksum_offset, queue;
 	int cum_len, seglen, boundary, rdma_count;
 	u8 flags, odd_flag;
 
-	/* always transmit through slot 0 */
-	ss = mgp->ss;
+	queue = skb_get_queue_mapping(skb);
+	queue &= (mgp->num_slices - 1);
+
+	ss = &mgp->ss[queue];
+	netdev_queue = netdev_get_tx_queue(mgp->dev, queue);
 	tx = &ss->tx;
+
 again:
 	req = tx->req_list;
 	avail = tx->mask - 1 - (tx->req - tx->done);
@@ -2593,7 +2664,7 @@ again:
 	if ((unlikely(avail < max_segments))) {
 		/* we are out of transmit resources */
 		tx->stop_queue++;
-		netif_stop_queue(dev);
+		netif_tx_stop_queue(netdev_queue);
 		return 1;
 	}
 
@@ -2786,10 +2857,16 @@ again:
 	idx = ((count - 1) + tx->req) & tx->mask;
 	tx->info[idx].last = 1;
 	myri10ge_submit_req(tx, tx->req_list, count);
+	/* if using multiple tx queues, make sure NIC polls the
+	 * current slice */
+	if ((mgp->dev->real_num_tx_queues > 1) && tx->queue_active == 0) {
+		tx->queue_active = 1;
+		put_be32(htonl(1), tx->send_go);
+	}
 	tx->pkt_start++;
 	if ((avail - count) < MXGEFW_MAX_SEND_DESC) {
 		tx->stop_queue++;
-		netif_stop_queue(dev);
+		netif_tx_stop_queue(netdev_queue);
 	}
 	dev->trans_start = jiffies;
 	return 0;
@@ -3367,20 +3444,21 @@ static void myri10ge_watchdog(struct work_struct *work)
 		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,
+			       "myri10ge: %s: (%d): %d %d %d %d %d %d\n",
+			       mgp->dev->name, i, tx->queue_active, 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,
+			       "myri10ge: %s: (%d): %d %d %d %d %d %d\n",
+			       mgp->dev->name, i, tx->queue_active, 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, 1);
@@ -3435,10 +3513,14 @@ static void myri10ge_watchdog_timer(unsigned long arg)
 			/* nic seems like it might be stuck.. */
 			if (rx_pause_cnt != mgp->watchdog_pause) {
 				if (net_ratelimit())
-					printk(KERN_WARNING "myri10ge %s:"
+					printk(KERN_WARNING
+					       "myri10ge %s slice %d:"
 					       "TX paused, check link partner\n",
-					       mgp->dev->name);
+					       mgp->dev->name, i);
 			} else {
+				printk(KERN_WARNING
+				       "myri10ge %s slice %d stuck:",
+				       mgp->dev->name, i);
 				reset_needed = 1;
 			}
 		}
@@ -3624,6 +3706,9 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp)
 					 mgp->num_slices);
 		if (status == 0) {
 			pci_disable_msix(pdev);
+#ifdef CONFIG_NETDEVICES_MULTIQUEUE
+			mgp->features |= NETIF_F_MULTI_QUEUE;
+#endif
 			return;
 		}
 		if (status > 0)
@@ -3653,7 +3738,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	int status = -ENXIO;
 	int dac_enabled;
 
-	netdev = alloc_etherdev(sizeof(*mgp));
+	netdev = alloc_etherdev_mq(sizeof(*mgp), MYRI10GE_MAX_SLICES);
 	if (netdev == NULL) {
 		dev_err(dev, "Could not allocate ethernet device\n");
 		return -ENOMEM;
@@ -3758,7 +3843,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		dev_err(&pdev->dev, "failed to alloc slice state\n");
 		goto abort_with_firmware;
 	}
-
+	netdev->real_num_tx_queues = mgp->num_slices;
 	status = myri10ge_reset(mgp);
 	if (status != 0) {
 		dev_err(&pdev->dev, "failed reset\n");
@@ -3782,6 +3867,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	netdev->set_multicast_list = myri10ge_set_multicast_list;
 	netdev->set_mac_address = myri10ge_set_mac_address;
 	netdev->features = mgp->features;
+
 	if (dac_enabled)
 		netdev->features |= NETIF_F_HIGHDMA;
 
@@ -3937,8 +4023,7 @@ static __init int myri10ge_init_module(void)
 	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) {
+	if (myri10ge_rss_hash > MXGEFW_RSS_HASH_TYPE_MAX) {
 		printk(KERN_ERR
 		       "%s: Illegal rssh hash type %d, defaulting to source port\n",
 		       myri10ge_driver.name, myri10ge_rss_hash);
@@ -3947,6 +4032,8 @@ static __init int myri10ge_init_module(void)
 #if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
 	dca_register_notify(&myri10ge_dca_notifier);
 #endif
+	if (myri10ge_max_slices > MYRI10GE_MAX_SLICES)
+		myri10ge_max_slices = MYRI10GE_MAX_SLICES;
 
 	return pci_register_driver(&myri10ge_driver);
 }
-- 
1.5.6.5




^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] myri10ge: rename main file into myri10ge_main.c
  2008-09-29  1:30 [PATCH 0/3] myri10ge updates for 2.6.28 Brice Goglin
  2008-09-29  1:34 ` [PATCH 1/3] myri10ge: add multiqueue TX Brice Goglin
@ 2008-09-29  1:34 ` Brice Goglin
  2008-09-29  1:34 ` [PATCH 3/3] myri10ge: split main file into pieces Brice Goglin
  2 siblings, 0 replies; 4+ messages in thread
From: Brice Goglin @ 2008-09-29  1:34 UTC (permalink / raw)
  To: Jeff Garzik, David S. Miller; +Cc: netdev

To prepare myri10ge.c split into multiple files, rename
it to myri10ge_main.c first.

Signed-off-by: Brice Goglin <brice@myri.com>
---
 drivers/net/myri10ge/Makefile                      |    2 ++
 .../net/myri10ge/{myri10ge.c => myri10ge_main.c}   |    0 
 2 files changed, 2 insertions(+), 0 deletions(-)
 rename drivers/net/myri10ge/{myri10ge.c => myri10ge_main.c} (100%)

diff --git a/drivers/net/myri10ge/Makefile b/drivers/net/myri10ge/Makefile
index 5df8916..597440c 100644
--- a/drivers/net/myri10ge/Makefile
+++ b/drivers/net/myri10ge/Makefile
@@ -3,3 +3,5 @@
 #
 
 obj-$(CONFIG_MYRI10GE) += myri10ge.o
+
+myri10ge-objs := myri10ge_main.o
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge_main.c
similarity index 100%
rename from drivers/net/myri10ge/myri10ge.c
rename to drivers/net/myri10ge/myri10ge_main.c
-- 
1.5.6.5




^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] myri10ge: split main file into pieces
  2008-09-29  1:30 [PATCH 0/3] myri10ge updates for 2.6.28 Brice Goglin
  2008-09-29  1:34 ` [PATCH 1/3] myri10ge: add multiqueue TX Brice Goglin
  2008-09-29  1:34 ` [PATCH 2/3] myri10ge: rename main file into myri10ge_main.c Brice Goglin
@ 2008-09-29  1:34 ` Brice Goglin
  2 siblings, 0 replies; 4+ messages in thread
From: Brice Goglin @ 2008-09-29  1:34 UTC (permalink / raw)
  To: Jeff Garzik, David S. Miller; +Cc: netdev

Move ethtool-related functions to myri10ge_ethtool.c.
Move firmware-probing/selecting/loading routines to myri10ge_firmware.c.
Move types and defines to myri10ge.h, and add some prototypes.

Signed-off-by: Brice Goglin <brice@myri.com>
---
 drivers/net/myri10ge/Makefile            |    2 +-
 drivers/net/myri10ge/myri10ge.h          |  244 ++++++++++
 drivers/net/myri10ge/myri10ge_ethtool.c  |  362 ++++++++++++++
 drivers/net/myri10ge/myri10ge_firmware.c |  309 ++++++++++++
 drivers/net/myri10ge/myri10ge_main.c     |  779 +-----------------------------
 5 files changed, 926 insertions(+), 770 deletions(-)
 create mode 100644 drivers/net/myri10ge/myri10ge.h
 create mode 100644 drivers/net/myri10ge/myri10ge_ethtool.c
 create mode 100644 drivers/net/myri10ge/myri10ge_firmware.c

diff --git a/drivers/net/myri10ge/Makefile b/drivers/net/myri10ge/Makefile
index 597440c..98bf3bf 100644
--- a/drivers/net/myri10ge/Makefile
+++ b/drivers/net/myri10ge/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_MYRI10GE) += myri10ge.o
 
-myri10ge-objs := myri10ge_main.o
+myri10ge-objs := myri10ge_main.o myri10ge_firmware.o myri10ge_ethtool.o
diff --git a/drivers/net/myri10ge/myri10ge.h b/drivers/net/myri10ge/myri10ge.h
new file mode 100644
index 0000000..a10e01a
--- /dev/null
+++ b/drivers/net/myri10ge/myri10ge.h
@@ -0,0 +1,244 @@
+/*************************************************************************
+ * myri10ge.c: Myricom Myri-10G Ethernet driver.
+ *
+ * Copyright (C) 2005 - 2007 Myricom, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Myricom, Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * If the eeprom on your board is not recent enough, you will need to get a
+ * newer firmware image at:
+ *   http://www.myri.com/scs/download-Myri10GE.html
+ *
+ * Contact Information:
+ *   <help@myri.com>
+ *   Myricom, Inc., 325N Santa Anita Avenue, Arcadia, CA 91006
+ *************************************************************************/
+
+#ifndef __MYRI10GE_H__
+#define __MYRI10GE_H__
+
+#define MYRI10GE_MAX_ETHER_MTU 9014
+
+#define MYRI10GE_ETH_STOPPED 0
+#define MYRI10GE_ETH_STOPPING 1
+#define MYRI10GE_ETH_STARTING 2
+#define MYRI10GE_ETH_RUNNING 3
+#define MYRI10GE_ETH_OPEN_FAILED 4
+
+#define MYRI10GE_EEPROM_STRINGS_SIZE 256
+#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2)
+#define MYRI10GE_MAX_LRO_DESCRIPTORS 8
+#define MYRI10GE_LRO_MAX_PKTS 64
+
+#define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff)
+#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
+
+#define MYRI10GE_ALLOC_ORDER 0
+#define MYRI10GE_ALLOC_SIZE ((1 << MYRI10GE_ALLOC_ORDER) * PAGE_SIZE)
+#define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1)
+
+#define MYRI10GE_MAX_SLICES 32
+
+struct myri10ge_rx_buffer_state {
+	struct page *page;
+	int page_offset;
+	 DECLARE_PCI_UNMAP_ADDR(bus)
+	 DECLARE_PCI_UNMAP_LEN(len)
+};
+
+struct myri10ge_tx_buffer_state {
+	struct sk_buff *skb;
+	int last;
+	 DECLARE_PCI_UNMAP_ADDR(bus)
+	 DECLARE_PCI_UNMAP_LEN(len)
+};
+
+struct myri10ge_cmd {
+	u32 data0;
+	u32 data1;
+	u32 data2;
+};
+
+struct myri10ge_rx_buf {
+	struct mcp_kreq_ether_recv __iomem *lanai;	/* lanai ptr for recv ring */
+	struct mcp_kreq_ether_recv *shadow;	/* host shadow of recv ring */
+	struct myri10ge_rx_buffer_state *info;
+	struct page *page;
+	dma_addr_t bus;
+	int page_offset;
+	int cnt;
+	int fill_cnt;
+	int alloc_fail;
+	int mask;		/* number of rx slots -1 */
+	int watchdog_needed;
+};
+
+struct myri10ge_tx_buf {
+	struct mcp_kreq_ether_send __iomem *lanai;	/* lanai ptr for sendq */
+	__be32 __iomem *send_go;	/* "go" doorbell ptr */
+	__be32 __iomem *send_stop;	/* "stop" doorbell ptr */
+	struct mcp_kreq_ether_send *req_list;	/* host shadow of sendq */
+	char *req_bytes;
+	struct myri10ge_tx_buffer_state *info;
+	int mask;		/* number of transmit slots -1  */
+	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;
+	int queue_active;
+};
+
+struct myri10ge_rx_done {
+	struct mcp_slot *entry;
+	dma_addr_t bus;
+	int cnt;
+	int idx;
+	struct net_lro_mgr lro_mgr;
+	struct net_lro_desc lro_desc[MYRI10GE_MAX_LRO_DESCRIPTORS];
+};
+
+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;
+#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+	int cached_dca_tag;
+	int cpu;
+	__be32 __iomem *dca_tag;
+#endif
+	char irq_desc[32];
+};
+
+struct myri10ge_priv {
+	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;
+	int big_bytes;
+	int max_intr_slots;
+	struct net_device *dev;
+	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_deassert;
+	char *mac_addr_string;
+	struct mcp_cmd_response *cmd;
+	dma_addr_t cmd_bus;
+	struct pci_dev *pdev;
+	int msi_enabled;
+	int msix_enabled;
+	struct msix_entry *msix_vectors;
+#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+	int dca_enabled;
+#endif
+	u32 link_state;
+	unsigned int rdma_tags_available;
+	int intr_coal_delay;
+	__be32 __iomem *intr_coal_delay_ptr;
+	int mtrr;
+	int wc_enabled;
+	int down_cnt;
+	wait_queue_head_t down_wq;
+	struct work_struct watchdog_work;
+	struct timer_list watchdog_timer;
+	int watchdog_resets;
+	int watchdog_pause;
+	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;
+	int fw_ver_tiny;
+	int adopted_rx_filter_bug;
+	u8 mac_addr[6];		/* eeprom mac address */
+	unsigned long serial_number;
+	int vendor_specific_offset;
+	int fw_multicast_support;
+	unsigned long features;
+	u32 max_tso6;
+	u32 read_dma;
+	u32 write_dma;
+	u32 read_write_dma;
+	u32 link_changes;
+	u32 msg_enable;
+};
+
+extern char *myri10ge_fw_unaligned;
+extern char *myri10ge_fw_aligned;
+extern char *myri10ge_fw_rss_unaligned;
+extern char *myri10ge_fw_rss_aligned;
+extern char *myri10ge_fw_name;
+extern const struct ethtool_ops myri10ge_ethtool_ops;
+extern int myri10ge_tso6;
+
+int myri10ge_load_firmware(struct myri10ge_priv *mgp, int adopt);
+int myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
+		      struct myri10ge_cmd *data, int atomic);
+void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable);
+int myri10ge_change_pause(struct myri10ge_priv *mgp, int pause);
+
+#define MYRI10GE_FW_OFFSET 1024*1024
+#define MYRI10GE_HIGHPART_TO_U32(X) \
+(sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
+#define MYRI10GE_LOWPART_TO_U32(X) ((u32)(X))
+
+#define put_be32(val, p) __raw_writel((__force __u32)(val), (__force void __iomem *)(p))
+
+#define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
+
+#define MYRI10GE_VERSION_STR "1.4.3-1.366"
+
+#endif /* __MYRI10GE_H__ */
diff --git a/drivers/net/myri10ge/myri10ge_ethtool.c b/drivers/net/myri10ge/myri10ge_ethtool.c
new file mode 100644
index 0000000..d095a8c
--- /dev/null
+++ b/drivers/net/myri10ge/myri10ge_ethtool.c
@@ -0,0 +1,362 @@
+/*************************************************************************
+ * myri10ge.c: Myricom Myri-10G Ethernet driver.
+ *
+ * Copyright (C) 2005 - 2008 Myricom, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Myricom, Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * If the eeprom on your board is not recent enough, you will need to get a
+ * newer firmware image at:
+ *   http://www.myri.com/scs/download-Myri10GE.html
+ *
+ * Contact Information:
+ *   <help@myri.com>
+ *   Myricom, Inc., 325N Santa Anita Avenue, Arcadia, CA 91006
+ *************************************************************************/
+
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/inet_lro.h>
+#include <linux/dca.h>
+#include <linux/ethtool.h>
+#include <linux/firmware.h>
+#include "myri10ge_mcp.h"
+#include "myri10ge.h"
+
+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;
+}
+
+static void
+myri10ge_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+	strlcpy(info->driver, "myri10ge", sizeof(info->driver));
+	strlcpy(info->version, MYRI10GE_VERSION_STR, sizeof(info->version));
+	strlcpy(info->fw_version, mgp->fw_version, sizeof(info->fw_version));
+	strlcpy(info->bus_info, pci_name(mgp->pdev), sizeof(info->bus_info));
+}
+
+static int
+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;
+}
+
+static int
+myri10ge_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+	mgp->intr_coal_delay = coal->rx_coalesce_usecs;
+	put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
+	return 0;
+}
+
+static void
+myri10ge_get_pauseparam(struct net_device *netdev,
+			struct ethtool_pauseparam *pause)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+	pause->autoneg = 0;
+	pause->rx_pause = mgp->pause;
+	pause->tx_pause = mgp->pause;
+}
+
+static int
+myri10ge_set_pauseparam(struct net_device *netdev,
+			struct ethtool_pauseparam *pause)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+	if (pause->tx_pause != mgp->pause)
+		return myri10ge_change_pause(mgp, pause->tx_pause);
+	if (pause->rx_pause != mgp->pause)
+		return myri10ge_change_pause(mgp, pause->tx_pause);
+	if (pause->autoneg != 0)
+		return -EINVAL;
+	return 0;
+}
+
+static void
+myri10ge_get_ringparam(struct net_device *netdev,
+		       struct ethtool_ringparam *ring)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+	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[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;
+	ring->tx_pending = ring->tx_max_pending;
+}
+
+static u32 myri10ge_get_rx_csum(struct net_device *netdev)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+	if (mgp->csum_flag)
+		return 1;
+	else
+		return 0;
+}
+
+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
+		mgp->csum_flag = 0;
+	return 0;
+}
+
+static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+	unsigned long flags = mgp->features & (NETIF_F_TSO6 | NETIF_F_TSO);
+
+	if (tso_enabled)
+		netdev->features |= flags;
+	else
+		netdev->features &= ~flags;
+	return 0;
+}
+
+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",
+	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
+	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
+	"tx_heartbeat_errors", "tx_window_errors",
+	/* device-specific stats */
+	"tx_boundary", "WC", "irq", "MSI", "MSIX",
+	"read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs",
+	"serial_number", "watchdog_resets",
+#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+	"dca_capable_firmware", "dca_device_present",
+#endif
+	"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"
+};
+
+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_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)
+{
+	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);
+		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 +
+		    mgp->num_slices * MYRI10GE_SLICE_STATS_LEN;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void
+myri10ge_get_ethtool_stats(struct net_device *netdev,
+			   struct ethtool_stats *stats, u64 * data)
+{
+	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++)
+		data[i] = ((unsigned long *)&mgp->stats)[i];
+
+	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;
+	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;
+	data[i++] = (unsigned int)mgp->serial_number;
+	data[i++] = (unsigned int)mgp->watchdog_resets;
+#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
+	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 */
+	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++] =
+	    (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(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);
+
+	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)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+	mgp->msg_enable = value;
+}
+
+static u32 myri10ge_get_msglevel(struct net_device *netdev)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+	return mgp->msg_enable;
+}
+
+const struct ethtool_ops myri10ge_ethtool_ops = {
+	.get_settings = myri10ge_get_settings,
+	.get_drvinfo = myri10ge_get_drvinfo,
+	.get_coalesce = myri10ge_get_coalesce,
+	.set_coalesce = myri10ge_set_coalesce,
+	.get_pauseparam = myri10ge_get_pauseparam,
+	.set_pauseparam = myri10ge_set_pauseparam,
+	.get_ringparam = myri10ge_get_ringparam,
+	.get_rx_csum = myri10ge_get_rx_csum,
+	.set_rx_csum = myri10ge_set_rx_csum,
+	.set_tx_csum = ethtool_op_set_tx_hw_csum,
+	.set_sg = ethtool_op_set_sg,
+	.set_tso = myri10ge_set_tso,
+	.get_link = ethtool_op_get_link,
+	.get_strings = myri10ge_get_strings,
+	.get_sset_count = myri10ge_get_sset_count,
+	.get_ethtool_stats = myri10ge_get_ethtool_stats,
+	.set_msglevel = myri10ge_set_msglevel,
+	.get_msglevel = myri10ge_get_msglevel
+};
diff --git a/drivers/net/myri10ge/myri10ge_firmware.c b/drivers/net/myri10ge/myri10ge_firmware.c
new file mode 100644
index 0000000..542fba0
--- /dev/null
+++ b/drivers/net/myri10ge/myri10ge_firmware.c
@@ -0,0 +1,309 @@
+/*************************************************************************
+ * myri10ge.c: Myricom Myri-10G Ethernet driver.
+ *
+ * Copyright (C) 2005 - 2008 Myricom, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Myricom, Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * If the eeprom on your board is not recent enough, you will need to get a
+ * newer firmware image at:
+ *   http://www.myri.com/scs/download-Myri10GE.html
+ *
+ * Contact Information:
+ *   <help@myri.com>
+ *   Myricom, Inc., 325N Santa Anita Avenue, Arcadia, CA 91006
+ *************************************************************************/
+
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/inet_lro.h>
+#include <linux/dca.h>
+#include <linux/io.h>
+#include <linux/ethtool.h>
+#include <linux/crc32.h>
+#include <linux/firmware.h>
+#include "myri10ge_mcp.h"
+#include "myri10ge_mcp_gen_header.h"
+#include "myri10ge.h"
+
+static int
+myri10ge_validate_firmware(struct myri10ge_priv *mgp,
+			   struct mcp_gen_header *hdr)
+{
+	struct device *dev = &mgp->pdev->dev;
+
+	/* check firmware type */
+	if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) {
+		dev_err(dev, "Bad firmware type: 0x%x\n", ntohl(hdr->mcp_type));
+		return -EINVAL;
+	}
+
+	/* save firmware version for ethtool */
+	strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version));
+
+	sscanf(mgp->fw_version, "%d.%d.%d", &mgp->fw_ver_major,
+	       &mgp->fw_ver_minor, &mgp->fw_ver_tiny);
+
+	if (!(mgp->fw_ver_major == MXGEFW_VERSION_MAJOR
+	      && mgp->fw_ver_minor == MXGEFW_VERSION_MINOR)) {
+		dev_err(dev, "Found firmware version %s\n", mgp->fw_version);
+		dev_err(dev, "Driver needs %d.%d\n", MXGEFW_VERSION_MAJOR,
+			MXGEFW_VERSION_MINOR);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size)
+{
+	unsigned crc, reread_crc;
+	const struct firmware *fw;
+	struct device *dev = &mgp->pdev->dev;
+	unsigned char *fw_readback;
+	struct mcp_gen_header *hdr;
+	size_t hdr_offset;
+	int status;
+	unsigned i;
+
+	if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) {
+		dev_err(dev, "Unable to load %s firmware image via hotplug\n",
+			mgp->fw_name);
+		status = -EINVAL;
+		goto abort_with_nothing;
+	}
+
+	/* check size */
+
+	if (fw->size >= mgp->sram_size - MYRI10GE_FW_OFFSET ||
+	    fw->size < MCP_HEADER_PTR_OFFSET + 4) {
+		dev_err(dev, "Firmware size invalid:%d\n", (int)fw->size);
+		status = -EINVAL;
+		goto abort_with_fw;
+	}
+
+	/* check id */
+	hdr_offset = ntohl(*(__be32 *) (fw->data + MCP_HEADER_PTR_OFFSET));
+	if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > fw->size) {
+		dev_err(dev, "Bad firmware file\n");
+		status = -EINVAL;
+		goto abort_with_fw;
+	}
+	hdr = (void *)(fw->data + hdr_offset);
+
+	status = myri10ge_validate_firmware(mgp, hdr);
+	if (status != 0)
+		goto abort_with_fw;
+
+	crc = crc32(~0, fw->data, fw->size);
+	for (i = 0; i < fw->size; i += 256) {
+		myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET + i,
+				  (__force u8 *) fw->data + i,
+				  min(256U, (unsigned)(fw->size - i)));
+		mb();
+		readb(mgp->sram);
+	}
+	fw_readback = vmalloc(fw->size);
+	if (!fw_readback) {
+		status = -ENOMEM;
+		goto abort_with_fw;
+	}
+	/* corruption checking is good for parity recovery and buggy chipset */
+	memcpy_fromio(fw_readback, mgp->sram + MYRI10GE_FW_OFFSET, fw->size);
+	reread_crc = crc32(~0, fw_readback, fw->size);
+	vfree(fw_readback);
+	if (crc != reread_crc) {
+		dev_err(dev, "CRC failed(fw-len=%u), got 0x%x (expect 0x%x)\n",
+			(unsigned)fw->size, reread_crc, crc);
+		status = -EIO;
+		goto abort_with_fw;
+	}
+	*size = (u32) fw->size;
+
+abort_with_fw:
+	release_firmware(fw);
+
+abort_with_nothing:
+	return status;
+}
+
+static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp)
+{
+	struct mcp_gen_header *hdr;
+	struct device *dev = &mgp->pdev->dev;
+	const size_t bytes = sizeof(struct mcp_gen_header);
+	size_t hdr_offset;
+	int status;
+
+	/* find running firmware header */
+	hdr_offset = swab32(readl(mgp->sram + MCP_HEADER_PTR_OFFSET));
+
+	if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > mgp->sram_size) {
+		dev_err(dev, "Running firmware has bad header offset (%d)\n",
+			(int)hdr_offset);
+		return -EIO;
+	}
+
+	/* copy header of running firmware from SRAM to host memory to
+	 * validate firmware */
+	hdr = kmalloc(bytes, GFP_KERNEL);
+	if (hdr == NULL) {
+		dev_err(dev, "could not malloc firmware hdr\n");
+		return -ENOMEM;
+	}
+	memcpy_fromio(hdr, mgp->sram + hdr_offset, bytes);
+	status = myri10ge_validate_firmware(mgp, hdr);
+	kfree(hdr);
+
+	/* check to see if adopted firmware has bug where adopting
+	 * it will cause broadcasts to be filtered unless the NIC
+	 * is kept in ALLMULTI mode */
+	if (mgp->fw_ver_major == 1 && mgp->fw_ver_minor == 4 &&
+	    mgp->fw_ver_tiny >= 4 && mgp->fw_ver_tiny <= 11) {
+		mgp->adopted_rx_filter_bug = 1;
+		dev_warn(dev, "Adopting fw %d.%d.%d: "
+			 "working around rx filter bug\n",
+			 mgp->fw_ver_major, mgp->fw_ver_minor,
+			 mgp->fw_ver_tiny);
+	}
+	return status;
+}
+
+static 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;
+}
+
+int myri10ge_load_firmware(struct myri10ge_priv *mgp, int adopt)
+{
+	char __iomem *submit;
+	__be32 buf[16] __attribute__ ((__aligned__(8)));
+	u32 dma_low, dma_high, size;
+	int status, i;
+
+	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
+		 * was a bad crc */
+		if (status == -EIO)
+			return status;
+
+		status = myri10ge_adopt_running_firmware(mgp);
+		if (status != 0) {
+			dev_err(&mgp->pdev->dev,
+				"failed to adopt running firmware\n");
+			return status;
+		}
+		dev_info(&mgp->pdev->dev,
+			 "Successfully adopted running firmware\n");
+		if (mgp->tx_boundary == 4096) {
+			dev_warn(&mgp->pdev->dev,
+				 "Using firmware currently running on NIC"
+				 ".  For optimal\n");
+			dev_warn(&mgp->pdev->dev,
+				 "performance consider loading optimized "
+				 "firmware\n");
+			dev_warn(&mgp->pdev->dev, "via hotplug\n");
+		}
+
+		mgp->fw_name = "adopted";
+		mgp->tx_boundary = 2048;
+		myri10ge_dummy_rdma(mgp, 1);
+		status = myri10ge_get_firmware_capabilities(mgp);
+		return status;
+	}
+
+	/* clear confirmation addr */
+	mgp->cmd->data = 0;
+	mb();
+
+	/* send a reload command to the bootstrap MCP, and wait for the
+	 *  response in the confirmation address.  The firmware should
+	 * write a -1 there to indicate it is alive and well
+	 */
+	dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
+	dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
+
+	buf[0] = htonl(dma_high);	/* confirm addr MSW */
+	buf[1] = htonl(dma_low);	/* confirm addr LSW */
+	buf[2] = MYRI10GE_NO_CONFIRM_DATA;	/* confirm data */
+
+	/* FIX: All newest firmware should un-protect the bottom of
+	 * the sram before handoff. However, the very first interfaces
+	 * do not. Therefore the handoff copy must skip the first 8 bytes
+	 */
+	buf[3] = htonl(MYRI10GE_FW_OFFSET + 8);	/* where the code starts */
+	buf[4] = htonl(size - 8);	/* length of code */
+	buf[5] = htonl(8);	/* where to copy to */
+	buf[6] = htonl(0);	/* where to jump to */
+
+	submit = mgp->sram + MXGEFW_BOOT_HANDOFF;
+
+	myri10ge_pio_copy(submit, &buf, sizeof(buf));
+	mb();
+	msleep(1);
+	mb();
+	i = 0;
+	while (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 9) {
+		msleep(1 << i);
+		i++;
+	}
+	if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA) {
+		dev_err(&mgp->pdev->dev, "handoff failed\n");
+		return -ENXIO;
+	}
+	myri10ge_dummy_rdma(mgp, 1);
+	status = myri10ge_get_firmware_capabilities(mgp);
+
+	return status;
+}
diff --git a/drivers/net/myri10ge/myri10ge_main.c b/drivers/net/myri10ge/myri10ge_main.c
index d9fcd2c..2f72db2 100644
--- a/drivers/net/myri10ge/myri10ge_main.c
+++ b/drivers/net/myri10ge/myri10ge_main.c
@@ -1,7 +1,7 @@
 /*************************************************************************
  * myri10ge.c: Myricom Myri-10G Ethernet driver.
  *
- * Copyright (C) 2005 - 2007 Myricom, Inc.
+ * Copyright (C) 2005 - 2008 Myricom, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -54,7 +54,6 @@
 #include <linux/inet.h>
 #include <linux/in.h>
 #include <linux/ethtool.h>
-#include <linux/firmware.h>
 #include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/vmalloc.h>
@@ -74,195 +73,19 @@
 
 #include "myri10ge_mcp.h"
 #include "myri10ge_mcp_gen_header.h"
-
-#define MYRI10GE_VERSION_STR "1.4.3-1.358"
+#include "myri10ge.h"
 
 MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
 MODULE_AUTHOR("Maintainer: help@myri.com");
 MODULE_VERSION(MYRI10GE_VERSION_STR);
 MODULE_LICENSE("Dual BSD/GPL");
 
-#define MYRI10GE_MAX_ETHER_MTU 9014
-
-#define MYRI10GE_ETH_STOPPED 0
-#define MYRI10GE_ETH_STOPPING 1
-#define MYRI10GE_ETH_STARTING 2
-#define MYRI10GE_ETH_RUNNING 3
-#define MYRI10GE_ETH_OPEN_FAILED 4
-
-#define MYRI10GE_EEPROM_STRINGS_SIZE 256
-#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2)
-#define MYRI10GE_MAX_LRO_DESCRIPTORS 8
-#define MYRI10GE_LRO_MAX_PKTS 64
-
-#define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff)
-#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
-
-#define MYRI10GE_ALLOC_ORDER 0
-#define MYRI10GE_ALLOC_SIZE ((1 << MYRI10GE_ALLOC_ORDER) * PAGE_SIZE)
-#define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1)
-
-#define MYRI10GE_MAX_SLICES 32
-
-struct myri10ge_rx_buffer_state {
-	struct page *page;
-	int page_offset;
-	 DECLARE_PCI_UNMAP_ADDR(bus)
-	 DECLARE_PCI_UNMAP_LEN(len)
-};
-
-struct myri10ge_tx_buffer_state {
-	struct sk_buff *skb;
-	int last;
-	 DECLARE_PCI_UNMAP_ADDR(bus)
-	 DECLARE_PCI_UNMAP_LEN(len)
-};
-
-struct myri10ge_cmd {
-	u32 data0;
-	u32 data1;
-	u32 data2;
-};
-
-struct myri10ge_rx_buf {
-	struct mcp_kreq_ether_recv __iomem *lanai;	/* lanai ptr for recv ring */
-	struct mcp_kreq_ether_recv *shadow;	/* host shadow of recv ring */
-	struct myri10ge_rx_buffer_state *info;
-	struct page *page;
-	dma_addr_t bus;
-	int page_offset;
-	int cnt;
-	int fill_cnt;
-	int alloc_fail;
-	int mask;		/* number of rx slots -1 */
-	int watchdog_needed;
-};
+char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat";
+char *myri10ge_fw_aligned = "myri10ge_eth_z8e.dat";
+char *myri10ge_fw_rss_unaligned = "myri10ge_rss_ethp_z8e.dat";
+char *myri10ge_fw_rss_aligned = "myri10ge_rss_eth_z8e.dat";
 
-struct myri10ge_tx_buf {
-	struct mcp_kreq_ether_send __iomem *lanai;	/* lanai ptr for sendq */
-	__be32 __iomem *send_go;	/* "go" doorbell ptr */
-	__be32 __iomem *send_stop;	/* "stop" doorbell ptr */
-	struct mcp_kreq_ether_send *req_list;	/* host shadow of sendq */
-	char *req_bytes;
-	struct myri10ge_tx_buffer_state *info;
-	int mask;		/* number of transmit slots -1  */
-	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;
-	int queue_active;
-};
-
-struct myri10ge_rx_done {
-	struct mcp_slot *entry;
-	dma_addr_t bus;
-	int cnt;
-	int idx;
-	struct net_lro_mgr lro_mgr;
-	struct net_lro_desc lro_desc[MYRI10GE_MAX_LRO_DESCRIPTORS];
-};
-
-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;
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
-	int cached_dca_tag;
-	int cpu;
-	__be32 __iomem *dca_tag;
-#endif
-	char irq_desc[32];
-};
-
-struct myri10ge_priv {
-	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;
-	int big_bytes;
-	int max_intr_slots;
-	struct net_device *dev;
-	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_deassert;
-	char *mac_addr_string;
-	struct mcp_cmd_response *cmd;
-	dma_addr_t cmd_bus;
-	struct pci_dev *pdev;
-	int msi_enabled;
-	int msix_enabled;
-	struct msix_entry *msix_vectors;
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
-	int dca_enabled;
-#endif
-	u32 link_state;
-	unsigned int rdma_tags_available;
-	int intr_coal_delay;
-	__be32 __iomem *intr_coal_delay_ptr;
-	int mtrr;
-	int wc_enabled;
-	int down_cnt;
-	wait_queue_head_t down_wq;
-	struct work_struct watchdog_work;
-	struct timer_list watchdog_timer;
-	int watchdog_resets;
-	int watchdog_pause;
-	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;
-	int fw_ver_tiny;
-	int adopted_rx_filter_bug;
-	u8 mac_addr[6];		/* eeprom mac address */
-	unsigned long serial_number;
-	int vendor_specific_offset;
-	int fw_multicast_support;
-	unsigned long features;
-	u32 max_tso6;
-	u32 read_dma;
-	u32 write_dma;
-	u32 read_write_dma;
-	u32 link_changes;
-	u32 msg_enable;
-};
-
-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;
+char *myri10ge_fw_name = NULL;
 module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name");
 
@@ -346,22 +169,10 @@ 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)
-#define MYRI10GE_LOWPART_TO_U32(X) ((u32)(X))
-
-#define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
-
 static void myri10ge_set_multicast_list(struct net_device *dev);
 static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev);
 
-static inline void put_be32(__be32 val, __be32 __iomem * p)
-{
-	__raw_writel((__force __u32) val, (__force void __iomem *)p);
-}
-
-static int
+int
 myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
 		  struct myri10ge_cmd *data, int atomic)
 {
@@ -492,7 +303,7 @@ abort:
  * chipsets resend dropped PCIe messages
  */
 
-static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable)
+void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable)
 {
 	char __iomem *submit;
 	__be32 buf[16] __attribute__ ((__aligned__(8)));
@@ -527,263 +338,6 @@ static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable)
 			(enable ? "enable" : "disable"));
 }
 
-static int
-myri10ge_validate_firmware(struct myri10ge_priv *mgp,
-			   struct mcp_gen_header *hdr)
-{
-	struct device *dev = &mgp->pdev->dev;
-
-	/* check firmware type */
-	if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) {
-		dev_err(dev, "Bad firmware type: 0x%x\n", ntohl(hdr->mcp_type));
-		return -EINVAL;
-	}
-
-	/* save firmware version for ethtool */
-	strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version));
-
-	sscanf(mgp->fw_version, "%d.%d.%d", &mgp->fw_ver_major,
-	       &mgp->fw_ver_minor, &mgp->fw_ver_tiny);
-
-	if (!(mgp->fw_ver_major == MXGEFW_VERSION_MAJOR
-	      && mgp->fw_ver_minor == MXGEFW_VERSION_MINOR)) {
-		dev_err(dev, "Found firmware version %s\n", mgp->fw_version);
-		dev_err(dev, "Driver needs %d.%d\n", MXGEFW_VERSION_MAJOR,
-			MXGEFW_VERSION_MINOR);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size)
-{
-	unsigned crc, reread_crc;
-	const struct firmware *fw;
-	struct device *dev = &mgp->pdev->dev;
-	unsigned char *fw_readback;
-	struct mcp_gen_header *hdr;
-	size_t hdr_offset;
-	int status;
-	unsigned i;
-
-	if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) {
-		dev_err(dev, "Unable to load %s firmware image via hotplug\n",
-			mgp->fw_name);
-		status = -EINVAL;
-		goto abort_with_nothing;
-	}
-
-	/* check size */
-
-	if (fw->size >= mgp->sram_size - MYRI10GE_FW_OFFSET ||
-	    fw->size < MCP_HEADER_PTR_OFFSET + 4) {
-		dev_err(dev, "Firmware size invalid:%d\n", (int)fw->size);
-		status = -EINVAL;
-		goto abort_with_fw;
-	}
-
-	/* check id */
-	hdr_offset = ntohl(*(__be32 *) (fw->data + MCP_HEADER_PTR_OFFSET));
-	if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > fw->size) {
-		dev_err(dev, "Bad firmware file\n");
-		status = -EINVAL;
-		goto abort_with_fw;
-	}
-	hdr = (void *)(fw->data + hdr_offset);
-
-	status = myri10ge_validate_firmware(mgp, hdr);
-	if (status != 0)
-		goto abort_with_fw;
-
-	crc = crc32(~0, fw->data, fw->size);
-	for (i = 0; i < fw->size; i += 256) {
-		myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET + i,
-				  fw->data + i,
-				  min(256U, (unsigned)(fw->size - i)));
-		mb();
-		readb(mgp->sram);
-	}
-	fw_readback = vmalloc(fw->size);
-	if (!fw_readback) {
-		status = -ENOMEM;
-		goto abort_with_fw;
-	}
-	/* corruption checking is good for parity recovery and buggy chipset */
-	memcpy_fromio(fw_readback, mgp->sram + MYRI10GE_FW_OFFSET, fw->size);
-	reread_crc = crc32(~0, fw_readback, fw->size);
-	vfree(fw_readback);
-	if (crc != reread_crc) {
-		dev_err(dev, "CRC failed(fw-len=%u), got 0x%x (expect 0x%x)\n",
-			(unsigned)fw->size, reread_crc, crc);
-		status = -EIO;
-		goto abort_with_fw;
-	}
-	*size = (u32) fw->size;
-
-abort_with_fw:
-	release_firmware(fw);
-
-abort_with_nothing:
-	return status;
-}
-
-static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp)
-{
-	struct mcp_gen_header *hdr;
-	struct device *dev = &mgp->pdev->dev;
-	const size_t bytes = sizeof(struct mcp_gen_header);
-	size_t hdr_offset;
-	int status;
-
-	/* find running firmware header */
-	hdr_offset = swab32(readl(mgp->sram + MCP_HEADER_PTR_OFFSET));
-
-	if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > mgp->sram_size) {
-		dev_err(dev, "Running firmware has bad header offset (%d)\n",
-			(int)hdr_offset);
-		return -EIO;
-	}
-
-	/* copy header of running firmware from SRAM to host memory to
-	 * validate firmware */
-	hdr = kmalloc(bytes, GFP_KERNEL);
-	if (hdr == NULL) {
-		dev_err(dev, "could not malloc firmware hdr\n");
-		return -ENOMEM;
-	}
-	memcpy_fromio(hdr, mgp->sram + hdr_offset, bytes);
-	status = myri10ge_validate_firmware(mgp, hdr);
-	kfree(hdr);
-
-	/* check to see if adopted firmware has bug where adopting
-	 * it will cause broadcasts to be filtered unless the NIC
-	 * is kept in ALLMULTI mode */
-	if (mgp->fw_ver_major == 1 && mgp->fw_ver_minor == 4 &&
-	    mgp->fw_ver_tiny >= 4 && mgp->fw_ver_tiny <= 11) {
-		mgp->adopted_rx_filter_bug = 1;
-		dev_warn(dev, "Adopting fw %d.%d.%d: "
-			 "working around rx filter bug\n",
-			 mgp->fw_ver_major, mgp->fw_ver_minor,
-			 mgp->fw_ver_tiny);
-	}
-	return status;
-}
-
-static 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, int adopt)
-{
-	char __iomem *submit;
-	__be32 buf[16] __attribute__ ((__aligned__(8)));
-	u32 dma_low, dma_high, size;
-	int status, i;
-
-	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
-		 * was a bad crc */
-		if (status == -EIO)
-			return status;
-
-		status = myri10ge_adopt_running_firmware(mgp);
-		if (status != 0) {
-			dev_err(&mgp->pdev->dev,
-				"failed to adopt running firmware\n");
-			return status;
-		}
-		dev_info(&mgp->pdev->dev,
-			 "Successfully adopted running firmware\n");
-		if (mgp->tx_boundary == 4096) {
-			dev_warn(&mgp->pdev->dev,
-				 "Using firmware currently running on NIC"
-				 ".  For optimal\n");
-			dev_warn(&mgp->pdev->dev,
-				 "performance consider loading optimized "
-				 "firmware\n");
-			dev_warn(&mgp->pdev->dev, "via hotplug\n");
-		}
-
-		mgp->fw_name = "adopted";
-		mgp->tx_boundary = 2048;
-		myri10ge_dummy_rdma(mgp, 1);
-		status = myri10ge_get_firmware_capabilities(mgp);
-		return status;
-	}
-
-	/* clear confirmation addr */
-	mgp->cmd->data = 0;
-	mb();
-
-	/* send a reload command to the bootstrap MCP, and wait for the
-	 *  response in the confirmation address.  The firmware should
-	 * write a -1 there to indicate it is alive and well
-	 */
-	dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
-	dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
-
-	buf[0] = htonl(dma_high);	/* confirm addr MSW */
-	buf[1] = htonl(dma_low);	/* confirm addr LSW */
-	buf[2] = MYRI10GE_NO_CONFIRM_DATA;	/* confirm data */
-
-	/* FIX: All newest firmware should un-protect the bottom of
-	 * the sram before handoff. However, the very first interfaces
-	 * do not. Therefore the handoff copy must skip the first 8 bytes
-	 */
-	buf[3] = htonl(MYRI10GE_FW_OFFSET + 8);	/* where the code starts */
-	buf[4] = htonl(size - 8);	/* length of code */
-	buf[5] = htonl(8);	/* where to copy to */
-	buf[6] = htonl(0);	/* where to jump to */
-
-	submit = mgp->sram + MXGEFW_BOOT_HANDOFF;
-
-	myri10ge_pio_copy(submit, &buf, sizeof(buf));
-	mb();
-	msleep(1);
-	mb();
-	i = 0;
-	while (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 9) {
-		msleep(1 << i);
-		i++;
-	}
-	if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA) {
-		dev_err(&mgp->pdev->dev, "handoff failed\n");
-		return -ENXIO;
-	}
-	myri10ge_dummy_rdma(mgp, 1);
-	status = myri10ge_get_firmware_capabilities(mgp);
-
-	return status;
-}
-
 static int myri10ge_update_mac_address(struct myri10ge_priv *mgp, u8 * addr)
 {
 	struct myri10ge_cmd cmd;
@@ -798,7 +352,7 @@ static int myri10ge_update_mac_address(struct myri10ge_priv *mgp, u8 * addr)
 	return status;
 }
 
-static int myri10ge_change_pause(struct myri10ge_priv *mgp, int pause)
+int myri10ge_change_pause(struct myri10ge_priv *mgp, int pause)
 {
 	struct myri10ge_cmd cmd;
 	int status, ctl;
@@ -1581,319 +1135,6 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
 	return (IRQ_HANDLED);
 }
 
-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;
-}
-
-static void
-myri10ge_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
-{
-	struct myri10ge_priv *mgp = netdev_priv(netdev);
-
-	strlcpy(info->driver, "myri10ge", sizeof(info->driver));
-	strlcpy(info->version, MYRI10GE_VERSION_STR, sizeof(info->version));
-	strlcpy(info->fw_version, mgp->fw_version, sizeof(info->fw_version));
-	strlcpy(info->bus_info, pci_name(mgp->pdev), sizeof(info->bus_info));
-}
-
-static int
-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;
-}
-
-static int
-myri10ge_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal)
-{
-	struct myri10ge_priv *mgp = netdev_priv(netdev);
-
-	mgp->intr_coal_delay = coal->rx_coalesce_usecs;
-	put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
-	return 0;
-}
-
-static void
-myri10ge_get_pauseparam(struct net_device *netdev,
-			struct ethtool_pauseparam *pause)
-{
-	struct myri10ge_priv *mgp = netdev_priv(netdev);
-
-	pause->autoneg = 0;
-	pause->rx_pause = mgp->pause;
-	pause->tx_pause = mgp->pause;
-}
-
-static int
-myri10ge_set_pauseparam(struct net_device *netdev,
-			struct ethtool_pauseparam *pause)
-{
-	struct myri10ge_priv *mgp = netdev_priv(netdev);
-
-	if (pause->tx_pause != mgp->pause)
-		return myri10ge_change_pause(mgp, pause->tx_pause);
-	if (pause->rx_pause != mgp->pause)
-		return myri10ge_change_pause(mgp, pause->tx_pause);
-	if (pause->autoneg != 0)
-		return -EINVAL;
-	return 0;
-}
-
-static void
-myri10ge_get_ringparam(struct net_device *netdev,
-		       struct ethtool_ringparam *ring)
-{
-	struct myri10ge_priv *mgp = netdev_priv(netdev);
-
-	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[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;
-	ring->tx_pending = ring->tx_max_pending;
-}
-
-static u32 myri10ge_get_rx_csum(struct net_device *netdev)
-{
-	struct myri10ge_priv *mgp = netdev_priv(netdev);
-
-	if (mgp->csum_flag)
-		return 1;
-	else
-		return 0;
-}
-
-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
-		mgp->csum_flag = 0;
-	return 0;
-}
-
-static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled)
-{
-	struct myri10ge_priv *mgp = netdev_priv(netdev);
-	unsigned long flags = mgp->features & (NETIF_F_TSO6 | NETIF_F_TSO);
-
-	if (tso_enabled)
-		netdev->features |= flags;
-	else
-		netdev->features &= ~flags;
-	return 0;
-}
-
-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",
-	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
-	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
-	"tx_heartbeat_errors", "tx_window_errors",
-	/* device-specific stats */
-	"tx_boundary", "WC", "irq", "MSI", "MSIX",
-	"read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs",
-	"serial_number", "watchdog_resets",
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
-	"dca_capable_firmware", "dca_device_present",
-#endif
-	"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"
-};
-
-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_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)
-{
-	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);
-		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 +
-		    mgp->num_slices * MYRI10GE_SLICE_STATS_LEN;
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
-static void
-myri10ge_get_ethtool_stats(struct net_device *netdev,
-			   struct ethtool_stats *stats, u64 * data)
-{
-	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++)
-		data[i] = ((unsigned long *)&mgp->stats)[i];
-
-	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;
-	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;
-	data[i++] = (unsigned int)mgp->serial_number;
-	data[i++] = (unsigned int)mgp->watchdog_resets;
-#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
-	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 */
-	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++] =
-	    (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(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);
-
-	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)
-{
-	struct myri10ge_priv *mgp = netdev_priv(netdev);
-	mgp->msg_enable = value;
-}
-
-static u32 myri10ge_get_msglevel(struct net_device *netdev)
-{
-	struct myri10ge_priv *mgp = netdev_priv(netdev);
-	return mgp->msg_enable;
-}
-
-static const struct ethtool_ops myri10ge_ethtool_ops = {
-	.get_settings = myri10ge_get_settings,
-	.get_drvinfo = myri10ge_get_drvinfo,
-	.get_coalesce = myri10ge_get_coalesce,
-	.set_coalesce = myri10ge_set_coalesce,
-	.get_pauseparam = myri10ge_get_pauseparam,
-	.set_pauseparam = myri10ge_set_pauseparam,
-	.get_ringparam = myri10ge_get_ringparam,
-	.get_rx_csum = myri10ge_get_rx_csum,
-	.set_rx_csum = myri10ge_set_rx_csum,
-	.set_tx_csum = ethtool_op_set_tx_hw_csum,
-	.set_sg = ethtool_op_set_sg,
-	.set_tso = myri10ge_set_tso,
-	.get_link = ethtool_op_get_link,
-	.get_strings = myri10ge_get_strings,
-	.get_sset_count = myri10ge_get_sset_count,
-	.get_ethtool_stats = myri10ge_get_ethtool_stats,
-	.set_msglevel = myri10ge_set_msglevel,
-	.get_msglevel = myri10ge_get_msglevel
-};
-
 static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss)
 {
 	struct myri10ge_priv *mgp = ss->mgp;
-- 
1.5.6.5




^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2008-09-29  1:34 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-29  1:30 [PATCH 0/3] myri10ge updates for 2.6.28 Brice Goglin
2008-09-29  1:34 ` [PATCH 1/3] myri10ge: add multiqueue TX Brice Goglin
2008-09-29  1:34 ` [PATCH 2/3] myri10ge: rename main file into myri10ge_main.c Brice Goglin
2008-09-29  1:34 ` [PATCH 3/3] myri10ge: split main file into pieces Brice Goglin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).