Merge tag 'rpmsg-v5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/andersson...
[linux-2.6-microblaze.git] / drivers / net / hyperv / netvsc_drv.c
index e8fce6d..39dddcd 100644 (file)
@@ -435,7 +435,7 @@ static u32 init_page_array(void *hdr, u32 len, struct sk_buff *skb,
                skb_frag_t *frag = skb_shinfo(skb)->frags + i;
 
                slots_used += fill_pg_buf(skb_frag_page(frag),
-                                       frag->page_offset,
+                                       skb_frag_off(frag),
                                        skb_frag_size(frag), &pb[slots_used]);
        }
        return slots_used;
@@ -449,7 +449,7 @@ static int count_skb_frag_slots(struct sk_buff *skb)
        for (i = 0; i < frags; i++) {
                skb_frag_t *frag = skb_shinfo(skb)->frags + i;
                unsigned long size = skb_frag_size(frag);
-               unsigned long offset = frag->page_offset;
+               unsigned long offset = skb_frag_off(frag);
 
                /* Skip unused frames from start of page */
                offset &= ~PAGE_MASK;
@@ -1785,13 +1785,15 @@ static int netvsc_set_features(struct net_device *ndev,
        netdev_features_t change = features ^ ndev->features;
        struct net_device_context *ndevctx = netdev_priv(ndev);
        struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
+       struct net_device *vf_netdev = rtnl_dereference(ndevctx->vf_netdev);
        struct ndis_offload_params offloads;
+       int ret = 0;
 
        if (!nvdev || nvdev->destroy)
                return -ENODEV;
 
        if (!(change & NETIF_F_LRO))
-               return 0;
+               goto syncvf;
 
        memset(&offloads, 0, sizeof(struct ndis_offload_params));
 
@@ -1803,7 +1805,19 @@ static int netvsc_set_features(struct net_device *ndev,
                offloads.rsc_ip_v6 = NDIS_OFFLOAD_PARAMETERS_RSC_DISABLED;
        }
 
-       return rndis_filter_set_offload_params(ndev, nvdev, &offloads);
+       ret = rndis_filter_set_offload_params(ndev, nvdev, &offloads);
+
+       if (ret)
+               features ^= NETIF_F_LRO;
+
+syncvf:
+       if (!vf_netdev)
+               return ret;
+
+       vf_netdev->wanted_features = features;
+       netdev_update_features(vf_netdev);
+
+       return ret;
 }
 
 static u32 netvsc_get_msglevel(struct net_device *ndev)
@@ -2181,6 +2195,10 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
 
        dev_hold(vf_netdev);
        rcu_assign_pointer(net_device_ctx->vf_netdev, vf_netdev);
+
+       vf_netdev->wanted_features = ndev->features;
+       netdev_update_features(vf_netdev);
+
        return NOTIFY_OK;
 }
 
@@ -2313,8 +2331,8 @@ static int netvsc_probe(struct hv_device *dev,
 
        /* hw_features computed in rndis_netdev_set_hwcaps() */
        net->features = net->hw_features |
-               NETIF_F_HIGHDMA | NETIF_F_SG |
-               NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
+               NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_CTAG_TX |
+               NETIF_F_HW_VLAN_CTAG_RX;
        net->vlan_features = net->features;
 
        netdev_lockdep_set_classes(net);