Subject: [PATCH] via-velocity: classical linux vlan api - step by step This one won't break... --- drivers/net/via-velocity.c | 123 ++++++++++++++++++++++++++++++++++++++------ 1 files changed, 106 insertions(+), 17 deletions(-) applies-to: 93c86234fd8a407ceb0b298ea5e300ca562e74a9 b6abc58dbcc5a49165aca530ac10b2b4929c1ece diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 7cb4fda..1610e4c 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -275,6 +275,7 @@ static struct notifier_block velocity_in static DEFINE_SPINLOCK(velocity_dev_list_lock); static LIST_HEAD(velocity_dev_list); +#ifdef CONFIG_VIA_VELOCITY_VLAN static inline u16 velocity_tx_vlan_tag(struct velocity_info *vptr, struct sk_buff *skb) { @@ -282,6 +283,91 @@ static inline u16 velocity_tx_vlan_tag(s vlan_tx_tag_get(skb) : 0x00; } +static void velocity_vlan_rx_register(struct net_device *dev, + struct vlan_group *grp) +{ + struct velocity_info *vptr = netdev_priv(dev); + struct mac_regs __iomem *regs = vptr->mac_regs; + unsigned long flags; + + spin_lock_irqsave(&vptr->lock, flags); + vptr->vlgrp = grp; + if (vptr->vlgrp) + WORD_REG_BITS_ON(MCFG_RTGOPT, ®s->MCFG); + else + WORD_REG_BITS_OFF(MCFG_RTGOPT, ®s->MCFG); + spin_unlock_irqrestore(&vptr->lock, flags); +} + +static void velocity_vlan_rx_add_vid(struct net_device *dev, + unsigned short vid) +{ + struct velocity_info *vptr = netdev_priv(dev); + struct mac_regs __iomem *regs = vptr->mac_regs; + unsigned long flags; + u16 slot; + + spin_lock_irqsave(&vptr->lock, flags); + + for (slot = 0; slot < VCAM_SIZE; slot++) { + u8 bit = vptr->mCAMmask[slot / 8] & (1 << (slot & 7)); + + if (!bit) + break; + } + + if (slot == VCAM_SIZE) { + printk(KERN_ERR "%s: no free hardware filter for VLAN %04d\n", + dev->name, vid); + goto out_unlock; + } + + vptr->mCAMmask[slot / 8] |= 1 << (slot & 7); + + mac_set_cam(regs, slot, (u8 *) &vid, VELOCITY_VLAN_ID_CAM); + mac_set_cam_mask(regs, vptr->vCAMmask, VELOCITY_VLAN_ID_CAM); + +out_unlock: + spin_unlock_irqrestore(&vptr->lock, flags); +} + +static void velocity_vlan_rx_kill_vid(struct net_device *dev, + unsigned short vid) +{ + struct velocity_info *vptr = netdev_priv(dev); + struct mac_regs __iomem *regs = vptr->mac_regs; + unsigned long flags; + u16 slot, hw_vid; + + spin_lock_irqsave(&vptr->lock, flags); + if (!vptr->vlgrp) + goto out_unlock; + + vptr->vlgrp->vlan_devices[vid] = NULL; + + for (slot = 0; slot < VCAM_SIZE; slot++) { + u8 bit = vptr->mCAMmask[slot / 8] & (1 << (slot & 7)); + + if (!bit) + continue; + mac_get_cam(regs, slot, (u8 *) &hw_vid, VELOCITY_VLAN_ID_CAM); + if (hw_vid == vid) + break; + } + + if (slot == VCAM_SIZE) { + printk(KERN_ERR "%s: no hardware filter found for VLAN %04d\n", + dev->name, vid); + goto out_unlock; + } + + vptr->mCAMmask[slot / 8] &= ~(1 << (slot & 7)); + mac_set_cam_mask(regs, vptr->vCAMmask, VELOCITY_VLAN_ID_CAM); + +out_unlock: + spin_unlock_irqrestore(&vptr->lock, flags); +} + static int velocity_rx_vlan_skb(struct velocity_info *vptr, struct rx_desc *rd, struct sk_buff *skb) { @@ -295,6 +381,22 @@ static int velocity_rx_vlan_skb(struct v return ret; } +#else + +static inline u16 velocity_tx_vlan_tag(struct velocity_info *vptr, + struct sk_buff *skb) +{ + return 0; +} + +static int velocity_rx_vlan_skb(struct velocity_info *vptr, struct rx_desc *rd, + struct sk_buff *skb) +{ + return -1; +} + +#endif + static void velocity_register_notifier(void) { register_inetaddr_notifier(&velocity_inetaddr_notifier); @@ -483,6 +585,7 @@ static void __devinit velocity_get_optio static void velocity_init_cam_filter(struct velocity_info *vptr) { struct mac_regs __iomem * regs = vptr->mac_regs; + u16 temp[4] = { 0, }; /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */ WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, ®s->MCFG); @@ -494,23 +597,9 @@ static void velocity_init_cam_filter(str mac_set_cam_mask(regs, vptr->vCAMmask, VELOCITY_VLAN_ID_CAM); mac_set_cam_mask(regs, vptr->mCAMmask, VELOCITY_MULTICAST_CAM); - /* Enable first VCAM */ - if (vptr->flags & VELOCITY_FLAGS_TAGGING) { - /* If Tagging option is enabled and VLAN ID is not zero, then - turn on MCFG_RTGOPT also */ - if (vptr->options.vid != 0) - WORD_REG_BITS_ON(MCFG_RTGOPT, ®s->MCFG); - - mac_set_cam(regs, 0, (u8 *) & (vptr->options.vid), VELOCITY_VLAN_ID_CAM); - vptr->vCAMmask[0] |= 1; - mac_set_cam_mask(regs, vptr->vCAMmask, VELOCITY_VLAN_ID_CAM); - } else { - u16 temp[4] = { 0, }; - - mac_set_cam(regs, 0, (u8 *) temp, VELOCITY_VLAN_ID_CAM); - temp[0] = 1; - mac_set_cam_mask(regs, (u8 *) temp, VELOCITY_VLAN_ID_CAM); - } + mac_set_cam(regs, 0, (u8 *) temp, VELOCITY_VLAN_ID_CAM); + temp[0] = 1; + mac_set_cam_mask(regs, (u8 *) temp, VELOCITY_VLAN_ID_CAM); } /** --- 0.99.9a