aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/myri10ge/myri10ge.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 10:37:28 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 10:37:28 -0700
commitd7e9660ad9d5e0845f52848bce31bcf5cdcdea6b (patch)
treec6c67d145771187b194d79d603742b31090a59d6 /drivers/net/myri10ge/myri10ge.c
parentb8cb48aae1b8c50b37dcb7710363aa69a7a0d9ca (diff)
parent13af7a6ea502fcdd4c0e3d7de6e332b102309491 (diff)
downloadkernel_samsung_smdk4412-d7e9660ad9d5e0845f52848bce31bcf5cdcdea6b.zip
kernel_samsung_smdk4412-d7e9660ad9d5e0845f52848bce31bcf5cdcdea6b.tar.gz
kernel_samsung_smdk4412-d7e9660ad9d5e0845f52848bce31bcf5cdcdea6b.tar.bz2
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1623 commits) netxen: update copyright netxen: fix tx timeout recovery netxen: fix file firmware leak netxen: improve pci memory access netxen: change firmware write size tg3: Fix return ring size breakage netxen: build fix for INET=n cdc-phonet: autoconfigure Phonet address Phonet: back-end for autoconfigured addresses Phonet: fix netlink address dump error handling ipv6: Add IFA_F_DADFAILED flag net: Add DEVTYPE support for Ethernet based devices mv643xx_eth.c: remove unused txq_set_wrr() ucc_geth: Fix hangs after switching from full to half duplex ucc_geth: Rearrange some code to avoid forward declarations phy/marvell: Make non-aneg speed/duplex forcing work for 88E1111 PHYs drivers/net/phy: introduce missing kfree drivers/net/wan: introduce missing kfree net: force bridge module(s) to be GPL Subject: [PATCH] appletalk: Fix skb leak when ipddp interface is not loaded ... Fixed up trivial conflicts: - arch/x86/include/asm/socket.h converted to <asm-generic/socket.h> in the x86 tree. The generic header has the same new #define's, so that works out fine. - drivers/net/tun.c fix conflict between 89f56d1e9 ("tun: reuse struct sock fields") that switched over to using 'tun->socket.sk' instead of the redundantly available (and thus removed) 'tun->sk', and 2b980dbd ("lsm: Add hooks to the TUN driver") which added a new 'tun->sk' use. Noted in 'next' by Stephen Rothwell.
Diffstat (limited to 'drivers/net/myri10ge/myri10ge.c')
-rw-r--r--drivers/net/myri10ge/myri10ge.c84
1 files changed, 58 insertions, 26 deletions
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 1f6e36e..6930c87 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -75,7 +75,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.5.0-1.418"
+#define MYRI10GE_VERSION_STR "1.5.0-1.432"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -188,6 +188,7 @@ struct myri10ge_slice_state {
dma_addr_t fw_stats_bus;
int watchdog_tx_done;
int watchdog_tx_req;
+ int watchdog_rx_done;
#ifdef CONFIG_MYRI10GE_DCA
int cached_dca_tag;
int cpu;
@@ -256,6 +257,7 @@ struct myri10ge_priv {
u32 link_changes;
u32 msg_enable;
unsigned int board_number;
+ int rebooted;
};
static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat";
@@ -358,7 +360,8 @@ MODULE_PARM_DESC(myri10ge_dca, "Enable DCA if possible");
#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 netdev_tx_t myri10ge_sw_tso(struct sk_buff *skb,
+ struct net_device *dev);
static inline void put_be32(__be32 val, __be32 __iomem * p)
{
@@ -2552,17 +2555,22 @@ static int myri10ge_close(struct net_device *dev)
netif_carrier_off(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);
- if (status)
- printk(KERN_ERR "myri10ge: %s: Couldn't bring down link\n",
- dev->name);
-
- wait_event_timeout(mgp->down_wq, old_down_cnt != mgp->down_cnt, HZ);
- if (old_down_cnt == mgp->down_cnt)
- printk(KERN_ERR "myri10ge: %s never got down irq\n", dev->name);
+ if (mgp->rebooted == 0) {
+ old_down_cnt = mgp->down_cnt;
+ mb();
+ status =
+ myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0);
+ if (status)
+ printk(KERN_ERR
+ "myri10ge: %s: Couldn't bring down link\n",
+ dev->name);
+ wait_event_timeout(mgp->down_wq, old_down_cnt != mgp->down_cnt,
+ HZ);
+ if (old_down_cnt == mgp->down_cnt)
+ printk(KERN_ERR "myri10ge: %s never got down irq\n",
+ dev->name);
+ }
netif_tx_disable(dev);
myri10ge_free_irq(mgp);
for (i = 0; i < mgp->num_slices; i++)
@@ -2649,7 +2657,8 @@ myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src,
* it and try again.
*/
-static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t myri10ge_xmit(struct sk_buff *skb,
+ struct net_device *dev)
{
struct myri10ge_priv *mgp = netdev_priv(dev);
struct myri10ge_slice_state *ss;
@@ -2748,7 +2757,7 @@ again:
/* The packet is gone, so we must
* return 0 */
ss->stats.tx_dropped += 1;
- return 0;
+ return NETDEV_TX_OK;
}
/* adjust the len to account for the zero pad
* so that the nic can know how long it is */
@@ -2892,7 +2901,7 @@ again:
tx->stop_queue++;
netif_tx_stop_queue(netdev_queue);
}
- return 0;
+ return NETDEV_TX_OK;
abort_linearize:
/* Free any DMA resources we've alloced and clear out the skb
@@ -2936,16 +2945,17 @@ abort_linearize:
drop:
dev_kfree_skb_any(skb);
ss->stats.tx_dropped += 1;
- return 0;
+ return NETDEV_TX_OK;
}
-static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t myri10ge_sw_tso(struct sk_buff *skb,
+ struct net_device *dev)
{
struct sk_buff *segs, *curr;
struct myri10ge_priv *mgp = netdev_priv(dev);
struct myri10ge_slice_state *ss;
- int status;
+ netdev_tx_t status;
segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6);
if (IS_ERR(segs))
@@ -2968,13 +2978,13 @@ static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev)
}
}
dev_kfree_skb_any(skb);
- return 0;
+ return NETDEV_TX_OK;
drop:
ss = &mgp->ss[skb_get_queue_mapping(skb)];
dev_kfree_skb_any(skb);
ss->stats.tx_dropped += 1;
- return 0;
+ return NETDEV_TX_OK;
}
static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
@@ -3427,12 +3437,13 @@ static void myri10ge_watchdog(struct work_struct *work)
container_of(work, struct myri10ge_priv, watchdog_work);
struct myri10ge_tx_buf *tx;
u32 reboot;
- int status;
+ int status, rebooted;
int i;
u16 cmd, vendor;
mgp->watchdog_resets++;
pci_read_config_word(mgp->pdev, PCI_COMMAND, &cmd);
+ rebooted = 0;
if ((cmd & PCI_COMMAND_MASTER) == 0) {
/* Bus master DMA disabled? Check to see
* if the card rebooted due to a parity error
@@ -3444,9 +3455,12 @@ static void myri10ge_watchdog(struct work_struct *work)
myri10ge_reset_recover ? " " : " not");
if (myri10ge_reset_recover == 0)
return;
-
+ rtnl_lock();
+ mgp->rebooted = 1;
+ rebooted = 1;
+ myri10ge_close(mgp->dev);
myri10ge_reset_recover--;
-
+ mgp->rebooted = 0;
/*
* A rebooted nic will come back with config space as
* it was after power was applied to PCIe bus.
@@ -3494,8 +3508,10 @@ static void myri10ge_watchdog(struct work_struct *work)
}
}
- rtnl_lock();
- myri10ge_close(mgp->dev);
+ if (!rebooted) {
+ rtnl_lock();
+ myri10ge_close(mgp->dev);
+ }
status = myri10ge_load_firmware(mgp, 1);
if (status != 0)
printk(KERN_ERR "myri10ge: %s: failed to load firmware\n",
@@ -3516,12 +3532,14 @@ static void myri10ge_watchdog_timer(unsigned long arg)
{
struct myri10ge_priv *mgp;
struct myri10ge_slice_state *ss;
- int i, reset_needed;
+ int i, reset_needed, busy_slice_cnt;
u32 rx_pause_cnt;
+ u16 cmd;
mgp = (struct myri10ge_priv *)arg;
rx_pause_cnt = ntohl(mgp->ss[0].fw_stats->dropped_pause);
+ busy_slice_cnt = 0;
for (i = 0, reset_needed = 0;
i < mgp->num_slices && reset_needed == 0; ++i) {
@@ -3559,8 +3577,22 @@ static void myri10ge_watchdog_timer(unsigned long arg)
reset_needed = 1;
}
}
+ if (ss->watchdog_tx_done != ss->tx.done ||
+ ss->watchdog_rx_done != ss->rx_done.cnt) {
+ busy_slice_cnt++;
+ }
ss->watchdog_tx_done = ss->tx.done;
ss->watchdog_tx_req = ss->tx.req;
+ ss->watchdog_rx_done = ss->rx_done.cnt;
+ }
+ /* if we've sent or received no traffic, poll the NIC to
+ * ensure it is still there. Otherwise, we risk not noticing
+ * an error in a timely fashion */
+ if (busy_slice_cnt == 0) {
+ pci_read_config_word(mgp->pdev, PCI_COMMAND, &cmd);
+ if ((cmd & PCI_COMMAND_MASTER) == 0) {
+ reset_needed = 1;
+ }
}
mgp->watchdog_pause = rx_pause_cnt;