diff --git a/[refs] b/[refs] index 0b675f120089..2ef552213447 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 11a100f844f6096787ab20e19f17d72abc957a8f +refs/heads/master: 8fa7425c6394117a541de82826d128d6c3d9161b diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.c index aa9f31eadab2..eebaf43f66b2 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -101,17 +101,13 @@ int iwl_rfkill_init(struct iwl_priv *priv) ret = rfkill_register(priv->rfkill_mngr.rfkill); if (ret) { IWL_ERROR("Unable to register rfkill: %d\n", ret); - goto unregister_rfkill; + goto free_rfkill; } IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); return ret; -unregister_rfkill: - rfkill_unregister(priv->rfkill_mngr.rfkill); - priv->rfkill_mngr.rfkill = NULL; - -freed_rfkill: +free_rfkill: if (priv->rfkill_mngr.rfkill != NULL) rfkill_free(priv->rfkill_mngr.rfkill); priv->rfkill_mngr.rfkill = NULL; diff --git a/trunk/include/linux/if_vlan.h b/trunk/include/linux/if_vlan.h index 93f5d9b0e9f9..d36515dae62f 100644 --- a/trunk/include/linux/if_vlan.h +++ b/trunk/include/linux/if_vlan.h @@ -185,10 +185,22 @@ static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, u16 vlan_tci) { struct vlan_ethhdr *veth; - if (skb_cow_head(skb, VLAN_HLEN) < 0) { - kfree_skb(skb); - return NULL; + if (skb_headroom(skb) < VLAN_HLEN) { + struct sk_buff *sk_tmp = skb; + skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN); + kfree_skb(sk_tmp); + if (!skb) { + printk(KERN_ERR "vlan: failed to realloc headroom\n"); + return NULL; + } + } else { + skb = skb_unshare(skb, GFP_ATOMIC); + if (!skb) { + printk(KERN_ERR "vlan: failed to unshare skbuff\n"); + return NULL; + } } + veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN); /* Move the mac addresses to the beginning of the new header. */ diff --git a/trunk/net/8021q/vlan_dev.c b/trunk/net/8021q/vlan_dev.c index b6e52c025fd8..2ccac6bea57e 100644 --- a/trunk/net/8021q/vlan_dev.c +++ b/trunk/net/8021q/vlan_dev.c @@ -74,8 +74,11 @@ static int vlan_dev_rebuild_header(struct sk_buff *skb) static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) { if (vlan_dev_info(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) { - if (skb_cow(skb, skb_headroom(skb)) < 0) - skb = NULL; + if (skb_shared(skb) || skb_cloned(skb)) { + struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); + kfree_skb(skb); + skb = nskb; + } if (skb) { /* Lifted from Gleb's VLAN code... */ memmove(skb->data - ETH_HLEN, @@ -259,14 +262,12 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, u16 vlan_tci = 0; int rc = 0; int build_vlan_header = 0; + struct net_device *vdev = dev; pr_debug("%s: skb: %p type: %hx len: %u vlan_id: %hx, daddr: %p\n", __func__, skb, type, len, vlan_dev_info(dev)->vlan_id, daddr); - if (WARN_ON(skb_headroom(skb) < dev->hard_header_len)) - return -ENOSPC; - /* build vlan header only if re_order_header flag is NOT set. This * fixes some programs that get confused when they see a VLAN device * sending a frame that is VLAN encoded (the consensus is that the VLAN @@ -315,6 +316,29 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, dev = vlan_dev_info(dev)->real_dev; + /* MPLS can send us skbuffs w/out enough space. This check will grow + * the skb if it doesn't have enough headroom. Not a beautiful solution, + * so I'll tick a counter so that users can know it's happening... + * If they care... + */ + + /* NOTE: This may still break if the underlying device is not the final + * device (and thus there are more headers to add...) It should work for + * good-ole-ethernet though. + */ + if (skb_headroom(skb) < dev->hard_header_len) { + struct sk_buff *sk_tmp = skb; + skb = skb_realloc_headroom(sk_tmp, dev->hard_header_len); + kfree_skb(sk_tmp); + if (skb == NULL) { + struct net_device_stats *stats = &vdev->stats; + stats->tx_dropped++; + return -ENOMEM; + } + vlan_dev_info(vdev)->cnt_inc_headroom_on_tx++; + pr_debug("%s: %s: had to grow skb\n", __func__, vdev->name); + } + if (build_vlan_header) { /* Now make the underlying real hard header */ rc = dev_hard_header(skb, dev, ETH_P_8021Q, daddr, saddr,