struct vlan_priority_tci_mapping        *next;
 };
 
+
+/**
+ *     struct vlan_rx_stats - VLAN percpu rx stats
+ *     @rx_packets: number of received packets
+ *     @rx_bytes: number of received bytes
+ *     @multicast: number of received multicast packets
+ *     @rx_errors: number of errors
+ */
+struct vlan_rx_stats {
+       unsigned long rx_packets;
+       unsigned long rx_bytes;
+       unsigned long multicast;
+       unsigned long rx_errors;
+};
+
 /**
  *     struct vlan_dev_info - VLAN private device data
  *     @nr_ingress_mappings: number of ingress priority mappings
  *     @dent: proc dir entry
  *     @cnt_inc_headroom_on_tx: statistic - number of skb expansions on TX
  *     @cnt_encap_on_xmit: statistic - number of skb encapsulations on TX
+ *     @vlan_rx_stats: ptr to percpu rx stats
  */
 struct vlan_dev_info {
        unsigned int                            nr_ingress_mappings;
        struct proc_dir_entry                   *dent;
        unsigned long                           cnt_inc_headroom_on_tx;
        unsigned long                           cnt_encap_on_xmit;
+       struct vlan_rx_stats                    *vlan_rx_stats;
 };
 
 static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev)
 
 int vlan_hwaccel_do_receive(struct sk_buff *skb)
 {
        struct net_device *dev = skb->dev;
-       struct net_device_stats *stats;
+       struct vlan_rx_stats     *rx_stats;
 
        skb->dev = vlan_dev_info(dev)->real_dev;
        netif_nit_deliver(skb);
        skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
        skb->vlan_tci = 0;
 
-       stats = &dev->stats;
-       stats->rx_packets++;
-       stats->rx_bytes += skb->len;
+       rx_stats = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats,
+                              smp_processor_id());
+
+       rx_stats->rx_packets++;
+       rx_stats->rx_bytes += skb->len;
 
        switch (skb->pkt_type) {
        case PACKET_BROADCAST:
                break;
        case PACKET_MULTICAST:
-               stats->multicast++;
+               rx_stats->multicast++;
                break;
        case PACKET_OTHERHOST:
                /* Our lower layer thinks this is not local, let's make sure.
 
                  struct packet_type *ptype, struct net_device *orig_dev)
 {
        struct vlan_hdr *vhdr;
-       struct net_device_stats *stats;
+       struct vlan_rx_stats *rx_stats;
        u16 vlan_id;
        u16 vlan_tci;
 
                goto err_unlock;
        }
 
-       stats = &skb->dev->stats;
-       stats->rx_packets++;
-       stats->rx_bytes += skb->len;
+       rx_stats = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats,
+                              smp_processor_id());
+       rx_stats->rx_packets++;
+       rx_stats->rx_bytes += skb->len;
 
        skb_pull_rcsum(skb, VLAN_HLEN);
 
                break;
 
        case PACKET_MULTICAST:
-               stats->multicast++;
+               rx_stats->multicast++;
                break;
 
        case PACKET_OTHERHOST:
 
        skb = vlan_check_reorder_header(skb);
        if (!skb) {
-               stats->rx_errors++;
+               rx_stats->rx_errors++;
                goto err_unlock;
        }
 
                subclass = 1;
 
        vlan_dev_set_lockdep_class(dev, subclass);
+
+       vlan_dev_info(dev)->vlan_rx_stats = alloc_percpu(struct vlan_rx_stats);
+       if (!vlan_dev_info(dev)->vlan_rx_stats)
+               return -ENOMEM;
+
        return 0;
 }
 
        struct vlan_dev_info *vlan = vlan_dev_info(dev);
        int i;
 
+       free_percpu(vlan->vlan_rx_stats);
+       vlan->vlan_rx_stats = NULL;
        for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) {
                while ((pm = vlan->egress_priority_map[i]) != NULL) {
                        vlan->egress_priority_map[i] = pm->next;
        return dev_ethtool_get_flags(vlan->real_dev);
 }
 
+static struct net_device_stats *vlan_dev_get_stats(struct net_device *dev)
+{
+       struct net_device_stats *stats = &dev->stats;
+
+       dev_txq_stats_fold(dev, stats);
+
+       if (vlan_dev_info(dev)->vlan_rx_stats) {
+               struct vlan_rx_stats *p, rx = {0};
+               int i;
+
+               for_each_possible_cpu(i) {
+                       p = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats, i);
+                       rx.rx_packets += p->rx_packets;
+                       rx.rx_bytes   += p->rx_bytes;
+                       rx.rx_errors  += p->rx_errors;
+                       rx.multicast  += p->multicast;
+               }
+               stats->rx_packets = rx.rx_packets;
+               stats->rx_bytes   = rx.rx_bytes;
+               stats->rx_errors  = rx.rx_errors;
+               stats->multicast  = rx.multicast;
+       }
+       return stats;
+}
+
 static const struct ethtool_ops vlan_ethtool_ops = {
        .get_settings           = vlan_ethtool_get_settings,
        .get_drvinfo            = vlan_ethtool_get_drvinfo,
        .ndo_change_rx_flags    = vlan_dev_change_rx_flags,
        .ndo_do_ioctl           = vlan_dev_ioctl,
        .ndo_neigh_setup        = vlan_dev_neigh_setup,
+       .ndo_get_stats          = vlan_dev_get_stats,
 #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
        .ndo_fcoe_ddp_setup     = vlan_dev_fcoe_ddp_setup,
        .ndo_fcoe_ddp_done      = vlan_dev_fcoe_ddp_done,
        .ndo_change_rx_flags    = vlan_dev_change_rx_flags,
        .ndo_do_ioctl           = vlan_dev_ioctl,
        .ndo_neigh_setup        = vlan_dev_neigh_setup,
+       .ndo_get_stats          = vlan_dev_get_stats,
 #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
        .ndo_fcoe_ddp_setup     = vlan_dev_fcoe_ddp_setup,
        .ndo_fcoe_ddp_done      = vlan_dev_fcoe_ddp_done,