Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

via-velocity: fix vlan receipt

- vlans were using a single CAM register (see mac_set_vlan_cam)
- setting the address filtering registers for vlans is not
needed when there is no vlan

The non-tagged interface is filtered out as soon as a tagged
(!= 0) interface is created. Its traffic appears again when an
zero-tagged interface is created.

Tested on Via Epia SN (VT6130 chipset) with several vlans whose
tag was above or beyond 255.

Signed-off-by: Séguier Régis <rseguier@e-teleport.net>
Acked-by: Francois Romieu <romieu@fr.zoreil.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>

authored by

Francois Romieu and committed by
Jeff Garzik
d4f73c8e 9f3f7910

+28 -18
+28 -18
drivers/net/via-velocity.c
··· 605 605 static void velocity_init_cam_filter(struct velocity_info *vptr) 606 606 { 607 607 struct mac_regs __iomem * regs = vptr->mac_regs; 608 - unsigned short vid; 609 608 610 609 /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */ 611 610 WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG); ··· 616 617 mac_set_vlan_cam_mask(regs, vptr->vCAMmask); 617 618 mac_set_cam_mask(regs, vptr->mCAMmask); 618 619 619 - /* Enable first VCAM */ 620 + /* Enable VCAMs */ 620 621 if (vptr->vlgrp) { 621 - for (vid = 0; vid < VLAN_VID_MASK; vid++) { 622 - if (vlan_group_get_device(vptr->vlgrp, vid)) { 623 - /* If Tagging option is enabled and 624 - VLAN ID is not zero, then 625 - turn on MCFG_RTGOPT also */ 626 - if (vid != 0) 627 - WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG); 622 + unsigned int vid, i = 0; 628 623 629 - mac_set_vlan_cam(regs, 0, (u8 *) &vid); 624 + if (!vlan_group_get_device(vptr->vlgrp, 0)) 625 + WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG); 626 + 627 + for (vid = 1; (vid < VLAN_VID_MASK); vid++) { 628 + if (vlan_group_get_device(vptr->vlgrp, vid)) { 629 + mac_set_vlan_cam(regs, i, (u8 *) &vid); 630 + vptr->vCAMmask[i / 8] |= 0x1 << (i % 8); 631 + if (++i >= VCAM_SIZE) 632 + break; 630 633 } 631 634 } 632 - vptr->vCAMmask[0] |= 1; 633 635 mac_set_vlan_cam_mask(regs, vptr->vCAMmask); 634 - } else { 635 - u16 temp = 0; 636 - mac_set_vlan_cam(regs, 0, (u8 *) &temp); 637 - temp = 1; 638 - mac_set_vlan_cam_mask(regs, (u8 *) &temp); 639 636 } 637 + } 638 + 639 + static void velocity_vlan_rx_register(struct net_device *dev, 640 + struct vlan_group *grp) 641 + { 642 + struct velocity_info *vptr = netdev_priv(dev); 643 + 644 + vptr->vlgrp = grp; 640 645 } 641 646 642 647 static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) ··· 962 959 963 960 dev->vlan_rx_add_vid = velocity_vlan_rx_add_vid; 964 961 dev->vlan_rx_kill_vid = velocity_vlan_rx_kill_vid; 962 + dev->vlan_rx_register = velocity_vlan_rx_register; 965 963 966 964 #ifdef VELOCITY_ZERO_COPY_SUPPORT 967 965 dev->features |= NETIF_F_SG; 968 966 #endif 969 - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER; 967 + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | 968 + NETIF_F_HW_VLAN_RX; 970 969 971 970 if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) 972 971 dev->features |= NETIF_F_IP_CSUM; ··· 1602 1597 skb_put(skb, pkt_len - 4); 1603 1598 skb->protocol = eth_type_trans(skb, vptr->dev); 1604 1599 1600 + if (vptr->vlgrp && (rd->rdesc0.RSR & RSR_DETAG)) { 1601 + vlan_hwaccel_rx(skb, vptr->vlgrp, 1602 + swab16(le16_to_cpu(rd->rdesc1.PQTAG))); 1603 + } else 1604 + netif_rx(skb); 1605 + 1605 1606 stats->rx_bytes += pkt_len; 1606 - netif_rx(skb); 1607 1607 1608 1608 return 0; 1609 1609 }