diff options
author | Francois Romieu <romieu@fr.zoreil.com> | 2008-04-24 17:32:33 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-04-25 02:45:23 -0400 |
commit | d4f73c8e459d355e10051174d859ffd0ef5764c0 (patch) | |
tree | d41fba7b3878b8ac39fece05ae5818e6e1932ddd | |
parent | 9f3f7910c67adfb520bbae3d8b16985439a97198 (diff) |
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>
-rw-r--r-- | drivers/net/via-velocity.c | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index ed1afaf683a4..6b8d882d197b 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c | |||
@@ -605,7 +605,6 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index, | |||
605 | static void velocity_init_cam_filter(struct velocity_info *vptr) | 605 | static void velocity_init_cam_filter(struct velocity_info *vptr) |
606 | { | 606 | { |
607 | struct mac_regs __iomem * regs = vptr->mac_regs; | 607 | struct mac_regs __iomem * regs = vptr->mac_regs; |
608 | unsigned short vid; | ||
609 | 608 | ||
610 | /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */ | 609 | /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */ |
611 | WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, ®s->MCFG); | 610 | WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, ®s->MCFG); |
@@ -617,29 +616,33 @@ static void velocity_init_cam_filter(struct velocity_info *vptr) | |||
617 | mac_set_vlan_cam_mask(regs, vptr->vCAMmask); | 616 | mac_set_vlan_cam_mask(regs, vptr->vCAMmask); |
618 | mac_set_cam_mask(regs, vptr->mCAMmask); | 617 | mac_set_cam_mask(regs, vptr->mCAMmask); |
619 | 618 | ||
620 | /* Enable first VCAM */ | 619 | /* Enable VCAMs */ |
621 | if (vptr->vlgrp) { | 620 | if (vptr->vlgrp) { |
622 | for (vid = 0; vid < VLAN_VID_MASK; vid++) { | 621 | unsigned int vid, i = 0; |
623 | if (vlan_group_get_device(vptr->vlgrp, vid)) { | 622 | |
624 | /* If Tagging option is enabled and | 623 | if (!vlan_group_get_device(vptr->vlgrp, 0)) |
625 | VLAN ID is not zero, then | 624 | WORD_REG_BITS_ON(MCFG_RTGOPT, ®s->MCFG); |
626 | turn on MCFG_RTGOPT also */ | ||
627 | if (vid != 0) | ||
628 | WORD_REG_BITS_ON(MCFG_RTGOPT, ®s->MCFG); | ||
629 | 625 | ||
630 | mac_set_vlan_cam(regs, 0, (u8 *) &vid); | 626 | for (vid = 1; (vid < VLAN_VID_MASK); vid++) { |
627 | if (vlan_group_get_device(vptr->vlgrp, vid)) { | ||
628 | mac_set_vlan_cam(regs, i, (u8 *) &vid); | ||
629 | vptr->vCAMmask[i / 8] |= 0x1 << (i % 8); | ||
630 | if (++i >= VCAM_SIZE) | ||
631 | break; | ||
631 | } | 632 | } |
632 | } | 633 | } |
633 | vptr->vCAMmask[0] |= 1; | ||
634 | mac_set_vlan_cam_mask(regs, vptr->vCAMmask); | 634 | mac_set_vlan_cam_mask(regs, vptr->vCAMmask); |
635 | } else { | ||
636 | u16 temp = 0; | ||
637 | mac_set_vlan_cam(regs, 0, (u8 *) &temp); | ||
638 | temp = 1; | ||
639 | mac_set_vlan_cam_mask(regs, (u8 *) &temp); | ||
640 | } | 635 | } |
641 | } | 636 | } |
642 | 637 | ||
638 | static void velocity_vlan_rx_register(struct net_device *dev, | ||
639 | struct vlan_group *grp) | ||
640 | { | ||
641 | struct velocity_info *vptr = netdev_priv(dev); | ||
642 | |||
643 | vptr->vlgrp = grp; | ||
644 | } | ||
645 | |||
643 | static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) | 646 | static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) |
644 | { | 647 | { |
645 | struct velocity_info *vptr = netdev_priv(dev); | 648 | struct velocity_info *vptr = netdev_priv(dev); |
@@ -959,11 +962,13 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi | |||
959 | 962 | ||
960 | dev->vlan_rx_add_vid = velocity_vlan_rx_add_vid; | 963 | dev->vlan_rx_add_vid = velocity_vlan_rx_add_vid; |
961 | dev->vlan_rx_kill_vid = velocity_vlan_rx_kill_vid; | 964 | dev->vlan_rx_kill_vid = velocity_vlan_rx_kill_vid; |
965 | dev->vlan_rx_register = velocity_vlan_rx_register; | ||
962 | 966 | ||
963 | #ifdef VELOCITY_ZERO_COPY_SUPPORT | 967 | #ifdef VELOCITY_ZERO_COPY_SUPPORT |
964 | dev->features |= NETIF_F_SG; | 968 | dev->features |= NETIF_F_SG; |
965 | #endif | 969 | #endif |
966 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER; | 970 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | |
971 | NETIF_F_HW_VLAN_RX; | ||
967 | 972 | ||
968 | if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) | 973 | if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) |
969 | dev->features |= NETIF_F_IP_CSUM; | 974 | dev->features |= NETIF_F_IP_CSUM; |
@@ -1597,8 +1602,13 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx) | |||
1597 | skb_put(skb, pkt_len - 4); | 1602 | skb_put(skb, pkt_len - 4); |
1598 | skb->protocol = eth_type_trans(skb, vptr->dev); | 1603 | skb->protocol = eth_type_trans(skb, vptr->dev); |
1599 | 1604 | ||
1605 | if (vptr->vlgrp && (rd->rdesc0.RSR & RSR_DETAG)) { | ||
1606 | vlan_hwaccel_rx(skb, vptr->vlgrp, | ||
1607 | swab16(le16_to_cpu(rd->rdesc1.PQTAG))); | ||
1608 | } else | ||
1609 | netif_rx(skb); | ||
1610 | |||
1600 | stats->rx_bytes += pkt_len; | 1611 | stats->rx_bytes += pkt_len; |
1601 | netif_rx(skb); | ||
1602 | 1612 | ||
1603 | return 0; | 1613 | return 0; |
1604 | } | 1614 | } |