summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-18 03:22:24 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-18 03:22:24 +0100
commitc579bc7e316e7e3f3b56df5e17f623325caa9783 (patch)
treefd057d71e237552436fb98f4bfb435b5c8e45787 /drivers
parentMerge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/ke... (diff)
parentnetfilter: ctnetlink: fix race between delete and timeout expiration (diff)
downloadlinux-c579bc7e316e7e3f3b56df5e17f623325caa9783.tar.xz
linux-c579bc7e316e7e3f3b56df5e17f623325caa9783.zip
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking changes from David Miller: "1) icmp6_dst_alloc() returns NULL instead of ERR_PTR() leading to crashes, particularly during shutdown. Reported by Dave Jones and fixed by Eric Dumazet. 2) hyperv and wimax/i2400m return NETDEV_TX_BUSY when they have already freed the SKB, which causes crashes as to the caller this means requeue the packet. Fixes from Eric Dumazet. 3) usbnet driver doesn't allocate the right amount of headroom on fresh RX SKBs, fix from Eric Dumazet. 4) Fix regression in ip6_mc_find_dev_rcu(), as an RCU lookup it abolutely should not take a reference to 'dev', this leads to leaks. Fix from RonQing Li. 5) Fix netfilter ctnetlink race between delete and timeout expiration. From Pablo Neira Ayuso. 6) Revert SFQ change which causes regressions, specifically queueing to tail can lead to unavoidable flow starvation. From Eric Dumazet. 7) Fix a memory leak and a crash on corrupt firmware files in bnx2x, from Michal Schmidt." * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: netfilter: ctnetlink: fix race between delete and timeout expiration ipv6: Don't dev_hold(dev) in ip6_mc_find_dev_rcu. wimax/i2400m: fix erroneous NETDEV_TX_BUSY use net/hyperv: fix erroneous NETDEV_TX_BUSY use net/usbnet: reserve headroom on rx skbs bnx2x: fix memory leak in bnx2x_init_firmware() bnx2x: fix a crash on corrupt firmware file sch_sfq: revert dont put new flow at the end of flows ipv6: fix icmp6_dst_alloc()
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c51
-rw-r--r--drivers/net/hyperv/netvsc_drv.c4
-rw-r--r--drivers/net/usb/usbnet.c4
-rw-r--r--drivers/net/wimax/i2400m/netdev.c30
4 files changed, 39 insertions, 50 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 254521319150..b69f8762b339 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -10824,38 +10824,36 @@ do { \
int bnx2x_init_firmware(struct bnx2x *bp)
{
+ const char *fw_file_name;
struct bnx2x_fw_file_hdr *fw_hdr;
int rc;
+ if (bp->firmware)
+ return 0;
- if (!bp->firmware) {
- const char *fw_file_name;
-
- if (CHIP_IS_E1(bp))
- fw_file_name = FW_FILE_NAME_E1;
- else if (CHIP_IS_E1H(bp))
- fw_file_name = FW_FILE_NAME_E1H;
- else if (!CHIP_IS_E1x(bp))
- fw_file_name = FW_FILE_NAME_E2;
- else {
- BNX2X_ERR("Unsupported chip revision\n");
- return -EINVAL;
- }
- BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
+ if (CHIP_IS_E1(bp))
+ fw_file_name = FW_FILE_NAME_E1;
+ else if (CHIP_IS_E1H(bp))
+ fw_file_name = FW_FILE_NAME_E1H;
+ else if (!CHIP_IS_E1x(bp))
+ fw_file_name = FW_FILE_NAME_E2;
+ else {
+ BNX2X_ERR("Unsupported chip revision\n");
+ return -EINVAL;
+ }
+ BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
- rc = request_firmware(&bp->firmware, fw_file_name,
- &bp->pdev->dev);
- if (rc) {
- BNX2X_ERR("Can't load firmware file %s\n",
- fw_file_name);
- goto request_firmware_exit;
- }
+ rc = request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev);
+ if (rc) {
+ BNX2X_ERR("Can't load firmware file %s\n",
+ fw_file_name);
+ goto request_firmware_exit;
+ }
- rc = bnx2x_check_firmware(bp);
- if (rc) {
- BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name);
- goto request_firmware_exit;
- }
+ rc = bnx2x_check_firmware(bp);
+ if (rc) {
+ BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name);
+ goto request_firmware_exit;
}
fw_hdr = (struct bnx2x_fw_file_hdr *)bp->firmware->data;
@@ -10901,6 +10899,7 @@ init_ops_alloc_err:
kfree(bp->init_data);
request_firmware_exit:
release_firmware(bp->firmware);
+ bp->firmware = NULL;
return rc;
}
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index bf01841bda5b..610860f28968 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -166,7 +166,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
dev_kfree_skb(skb);
net->stats.tx_dropped++;
- return NETDEV_TX_BUSY;
+ return NETDEV_TX_OK;
}
packet->extension = (void *)(unsigned long)packet +
@@ -226,7 +226,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
dev_kfree_skb_any(skb);
}
- return ret ? NETDEV_TX_BUSY : NETDEV_TX_OK;
+ return NETDEV_TX_OK;
}
/*
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 81b96e303757..59681f01a54e 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -328,13 +328,13 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
unsigned long lockflags;
size_t size = dev->rx_urb_size;
- if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) {
+ skb = __netdev_alloc_skb_ip_align(dev->net, size, flags);
+ if (!skb) {
netif_dbg(dev, rx_err, dev->net, "no rx skb\n");
usbnet_defer_kevent (dev, EVENT_RX_MEMORY);
usb_free_urb (urb);
return -ENOMEM;
}
- skb_reserve (skb, NET_IP_ALIGN);
entry = (struct skb_data *) skb->cb;
entry->urb = urb;
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c
index 64a110604ad3..63e4b709efa9 100644
--- a/drivers/net/wimax/i2400m/netdev.c
+++ b/drivers/net/wimax/i2400m/netdev.c
@@ -367,38 +367,28 @@ netdev_tx_t i2400m_hard_start_xmit(struct sk_buff *skb,
{
struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
struct device *dev = i2400m_dev(i2400m);
- int result;
+ int result = -1;
d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev);
- if (skb_header_cloned(skb)) {
- /*
- * Make tcpdump/wireshark happy -- if they are
- * running, the skb is cloned and we will overwrite
- * the mac fields in i2400m_tx_prep_header. Expand
- * seems to fix this...
- */
- result = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
- if (result) {
- result = NETDEV_TX_BUSY;
- goto error_expand;
- }
- }
+
+ if (skb_header_cloned(skb) &&
+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+ goto drop;
if (i2400m->state == I2400M_SS_IDLE)
result = i2400m_net_wake_tx(i2400m, net_dev, skb);
else
result = i2400m_net_tx(i2400m, net_dev, skb);
- if (result < 0)
+ if (result < 0) {
+drop:
net_dev->stats.tx_dropped++;
- else {
+ } else {
net_dev->stats.tx_packets++;
net_dev->stats.tx_bytes += skb->len;
}
- result = NETDEV_TX_OK;
-error_expand:
- kfree_skb(skb);
+ dev_kfree_skb(skb);
d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result);
- return result;
+ return NETDEV_TX_OK;
}