aboutsummaryrefslogtreecommitdiffstats
path: root/net/8021q/vlan_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/8021q/vlan_dev.c')
-rw-r--r--net/8021q/vlan_dev.c72
1 files changed, 61 insertions, 11 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 4198ec5c8ab..b7889782047 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -140,7 +140,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
140 struct packet_type *ptype, struct net_device *orig_dev) 140 struct packet_type *ptype, struct net_device *orig_dev)
141{ 141{
142 struct vlan_hdr *vhdr; 142 struct vlan_hdr *vhdr;
143 struct net_device_stats *stats; 143 struct vlan_rx_stats *rx_stats;
144 u16 vlan_id; 144 u16 vlan_id;
145 u16 vlan_tci; 145 u16 vlan_tci;
146 146
@@ -163,9 +163,10 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
163 goto err_unlock; 163 goto err_unlock;
164 } 164 }
165 165
166 stats = &skb->dev->stats; 166 rx_stats = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats,
167 stats->rx_packets++; 167 smp_processor_id());
168 stats->rx_bytes += skb->len; 168 rx_stats->rx_packets++;
169 rx_stats->rx_bytes += skb->len;
169 170
170 skb_pull_rcsum(skb, VLAN_HLEN); 171 skb_pull_rcsum(skb, VLAN_HLEN);
171 172
@@ -180,7 +181,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
180 break; 181 break;
181 182
182 case PACKET_MULTICAST: 183 case PACKET_MULTICAST:
183 stats->multicast++; 184 rx_stats->multicast++;
184 break; 185 break;
185 186
186 case PACKET_OTHERHOST: 187 case PACKET_OTHERHOST:
@@ -200,7 +201,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
200 201
201 skb = vlan_check_reorder_header(skb); 202 skb = vlan_check_reorder_header(skb);
202 if (!skb) { 203 if (!skb) {
203 stats->rx_errors++; 204 rx_stats->rx_errors++;
204 goto err_unlock; 205 goto err_unlock;
205 } 206 }
206 207
@@ -332,7 +333,7 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,
332 } else 333 } else
333 txq->tx_dropped++; 334 txq->tx_dropped++;
334 335
335 return NETDEV_TX_OK; 336 return ret;
336} 337}
337 338
338static netdev_tx_t vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, 339static netdev_tx_t vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb,
@@ -358,7 +359,7 @@ static netdev_tx_t vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb,
358 } else 359 } else
359 txq->tx_dropped++; 360 txq->tx_dropped++;
360 361
361 return NETDEV_TX_OK; 362 return ret;
362} 363}
363 364
364static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu) 365static int vlan_dev_change_mtu(struct net_device *dev, int new_mtu)
@@ -393,7 +394,7 @@ int vlan_dev_set_egress_priority(const struct net_device *dev,
393 struct vlan_dev_info *vlan = vlan_dev_info(dev); 394 struct vlan_dev_info *vlan = vlan_dev_info(dev);
394 struct vlan_priority_tci_mapping *mp = NULL; 395 struct vlan_priority_tci_mapping *mp = NULL;
395 struct vlan_priority_tci_mapping *np; 396 struct vlan_priority_tci_mapping *np;
396 u32 vlan_qos = (vlan_prio << 13) & 0xE000; 397 u32 vlan_qos = (vlan_prio << VLAN_PRIO_SHIFT) & VLAN_PRIO_MASK;
397 398
398 /* See if a priority mapping exists.. */ 399 /* See if a priority mapping exists.. */
399 mp = vlan->egress_priority_map[skb_prio & 0xF]; 400 mp = vlan->egress_priority_map[skb_prio & 0xF];
@@ -430,7 +431,8 @@ int vlan_dev_change_flags(const struct net_device *dev, u32 flags, u32 mask)
430 struct vlan_dev_info *vlan = vlan_dev_info(dev); 431 struct vlan_dev_info *vlan = vlan_dev_info(dev);
431 u32 old_flags = vlan->flags; 432 u32 old_flags = vlan->flags;
432 433
433 if (mask & ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP)) 434 if (mask & ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP |
435 VLAN_FLAG_LOOSE_BINDING))
434 return -EINVAL; 436 return -EINVAL;
435 437
436 vlan->flags = (old_flags & ~mask) | (flags & mask); 438 vlan->flags = (old_flags & ~mask) | (flags & mask);
@@ -455,7 +457,8 @@ static int vlan_dev_open(struct net_device *dev)
455 struct net_device *real_dev = vlan->real_dev; 457 struct net_device *real_dev = vlan->real_dev;
456 int err; 458 int err;
457 459
458 if (!(real_dev->flags & IFF_UP)) 460 if (!(real_dev->flags & IFF_UP) &&
461 !(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
459 return -ENETDOWN; 462 return -ENETDOWN;
460 463
461 if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) { 464 if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) {
@@ -626,6 +629,17 @@ static int vlan_dev_fcoe_disable(struct net_device *dev)
626 rc = ops->ndo_fcoe_disable(real_dev); 629 rc = ops->ndo_fcoe_disable(real_dev);
627 return rc; 630 return rc;
628} 631}
632
633static int vlan_dev_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type)
634{
635 struct net_device *real_dev = vlan_dev_info(dev)->real_dev;
636 const struct net_device_ops *ops = real_dev->netdev_ops;
637 int rc = -EINVAL;
638
639 if (ops->ndo_fcoe_get_wwn)
640 rc = ops->ndo_fcoe_get_wwn(real_dev, wwn, type);
641 return rc;
642}
629#endif 643#endif
630 644
631static void vlan_dev_change_rx_flags(struct net_device *dev, int change) 645static void vlan_dev_change_rx_flags(struct net_device *dev, int change)
@@ -720,6 +734,11 @@ static int vlan_dev_init(struct net_device *dev)
720 subclass = 1; 734 subclass = 1;
721 735
722 vlan_dev_set_lockdep_class(dev, subclass); 736 vlan_dev_set_lockdep_class(dev, subclass);
737
738 vlan_dev_info(dev)->vlan_rx_stats = alloc_percpu(struct vlan_rx_stats);
739 if (!vlan_dev_info(dev)->vlan_rx_stats)
740 return -ENOMEM;
741
723 return 0; 742 return 0;
724} 743}
725 744
@@ -729,6 +748,8 @@ static void vlan_dev_uninit(struct net_device *dev)
729 struct vlan_dev_info *vlan = vlan_dev_info(dev); 748 struct vlan_dev_info *vlan = vlan_dev_info(dev);
730 int i; 749 int i;
731 750
751 free_percpu(vlan->vlan_rx_stats);
752 vlan->vlan_rx_stats = NULL;
732 for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) { 753 for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) {
733 while ((pm = vlan->egress_priority_map[i]) != NULL) { 754 while ((pm = vlan->egress_priority_map[i]) != NULL) {
734 vlan->egress_priority_map[i] = pm->next; 755 vlan->egress_priority_map[i] = pm->next;
@@ -764,6 +785,31 @@ static u32 vlan_ethtool_get_flags(struct net_device *dev)
764 return dev_ethtool_get_flags(vlan->real_dev); 785 return dev_ethtool_get_flags(vlan->real_dev);
765} 786}
766 787
788static struct net_device_stats *vlan_dev_get_stats(struct net_device *dev)
789{
790 struct net_device_stats *stats = &dev->stats;
791
792 dev_txq_stats_fold(dev, stats);
793
794 if (vlan_dev_info(dev)->vlan_rx_stats) {
795 struct vlan_rx_stats *p, rx = {0};
796 int i;
797
798 for_each_possible_cpu(i) {
799 p = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats, i);
800 rx.rx_packets += p->rx_packets;
801 rx.rx_bytes += p->rx_bytes;
802 rx.rx_errors += p->rx_errors;
803 rx.multicast += p->multicast;
804 }
805 stats->rx_packets = rx.rx_packets;
806 stats->rx_bytes = rx.rx_bytes;
807 stats->rx_errors = rx.rx_errors;
808 stats->multicast = rx.multicast;
809 }
810 return stats;
811}
812
767static const struct ethtool_ops vlan_ethtool_ops = { 813static const struct ethtool_ops vlan_ethtool_ops = {
768 .get_settings = vlan_ethtool_get_settings, 814 .get_settings = vlan_ethtool_get_settings,
769 .get_drvinfo = vlan_ethtool_get_drvinfo, 815 .get_drvinfo = vlan_ethtool_get_drvinfo,
@@ -786,11 +832,13 @@ static const struct net_device_ops vlan_netdev_ops = {
786 .ndo_change_rx_flags = vlan_dev_change_rx_flags, 832 .ndo_change_rx_flags = vlan_dev_change_rx_flags,
787 .ndo_do_ioctl = vlan_dev_ioctl, 833 .ndo_do_ioctl = vlan_dev_ioctl,
788 .ndo_neigh_setup = vlan_dev_neigh_setup, 834 .ndo_neigh_setup = vlan_dev_neigh_setup,
835 .ndo_get_stats = vlan_dev_get_stats,
789#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) 836#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
790 .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup, 837 .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup,
791 .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done, 838 .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done,
792 .ndo_fcoe_enable = vlan_dev_fcoe_enable, 839 .ndo_fcoe_enable = vlan_dev_fcoe_enable,
793 .ndo_fcoe_disable = vlan_dev_fcoe_disable, 840 .ndo_fcoe_disable = vlan_dev_fcoe_disable,
841 .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn,
794#endif 842#endif
795}; 843};
796 844
@@ -808,11 +856,13 @@ static const struct net_device_ops vlan_netdev_accel_ops = {
808 .ndo_change_rx_flags = vlan_dev_change_rx_flags, 856 .ndo_change_rx_flags = vlan_dev_change_rx_flags,
809 .ndo_do_ioctl = vlan_dev_ioctl, 857 .ndo_do_ioctl = vlan_dev_ioctl,
810 .ndo_neigh_setup = vlan_dev_neigh_setup, 858 .ndo_neigh_setup = vlan_dev_neigh_setup,
859 .ndo_get_stats = vlan_dev_get_stats,
811#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) 860#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
812 .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup, 861 .ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup,
813 .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done, 862 .ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done,
814 .ndo_fcoe_enable = vlan_dev_fcoe_enable, 863 .ndo_fcoe_enable = vlan_dev_fcoe_enable,
815 .ndo_fcoe_disable = vlan_dev_fcoe_disable, 864 .ndo_fcoe_disable = vlan_dev_fcoe_disable,
865 .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn,
816#endif 866#endif
817}; 867};
818 868