Messages in this thread Patch in this message | | | Date | Tue, 9 Nov 2004 01:00:06 +0100 | From | Francois Romieu <> | Subject | Re: ZyXEL GN650-T |
| |
seby@focomunicatii.ro <seby@focomunicatii.ro> : [...] > I just bouth a zyxel GN650T network card .. and it sems that vlan's don't > work on this card .. anybody had this problems with this card ..
Patch below against 2.6.10-rc1-bk15 + Jeff's netdev should convert the driver to the in-kernel vlan API.
I'd be surprized it does from the first try though.
Please keep netdev CCed.
diff -puN drivers/net/via-velocity.c~via-velocity-300 drivers/net/via-velocity.c --- linux-2.6.10-rc1/drivers/net/via-velocity.c~via-velocity-300 2004-11-08 00:59:23.000000000 +0100 +++ linux-2.6.10-rc1-fr/drivers/net/via-velocity.c 2004-11-09 00:56:08.000000000 +0100 @@ -73,6 +73,7 @@ #include <linux/reboot.h> #include <linux/ethtool.h> #include <linux/mii.h> +#include <linux/if_vlan.h> #include <linux/in.h> #include <linux/if_arp.h> #include <linux/ip.h> @@ -114,15 +115,6 @@ VELOCITY_PARAM(RxDescriptors, "Number of #define TX_DESC_DEF 64 VELOCITY_PARAM(TxDescriptors, "Number of transmit descriptors"); -#define VLAN_ID_MIN 0 -#define VLAN_ID_MAX 4095 -#define VLAN_ID_DEF 0 -/* VID_setting[] is used for setting the VID of NIC. - 0: default VID. - 1-4094: other VIDs. -*/ -VELOCITY_PARAM(VID_setting, "802.1Q VLAN ID"); - #define RX_THRESH_MIN 0 #define RX_THRESH_MAX 3 #define RX_THRESH_DEF 0 @@ -150,13 +142,6 @@ VELOCITY_PARAM(rx_thresh, "Receive fifo */ VELOCITY_PARAM(DMA_length, "DMA length"); -#define TAGGING_DEF 0 -/* enable_tagging[] is used for enabling 802.1Q VID tagging. - 0: disable VID seeting(default). - 1: enable VID setting. -*/ -VELOCITY_PARAM(enable_tagging, "Enable 802.1Q tagging"); - #define IP_ALIG_DEF 0 /* IP_byte_align[] is used for IP header DWORD byte aligned 0: indicate the IP header won't be DWORD byte aligned.(Default) . @@ -275,6 +260,130 @@ static struct notifier_block velocity_in static spinlock_t velocity_dev_list_lock = SPIN_LOCK_UNLOCKED; 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) +{ + return (vptr->vlgrp && vlan_tx_tag_present(skb)) ? + 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) +{ + int ret; + + if (vptr->vlgrp && (rd->rdesc0.RSR & RSR_VTAG)) { + u16 vlan_tag = rd->rdesc1.u.pqinf.VID; + + /* FIXME: should be NAPI dependant */ + vlan_hwaccel_receive_skb(skb, vptr->vlgrp, vlan_tag); + ret = 0; + } else + ret = -1; + 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 sk_buff *skb) +{ + return -1; +} + +#endif + static void velocity_register_notifier(void) { register_inetaddr_notifier(&velocity_inetaddr_notifier); @@ -440,8 +549,6 @@ static void __devinit velocity_get_optio velocity_set_int_opt(&opts->DMA_length, DMA_length[index], DMA_LENGTH_MIN, DMA_LENGTH_MAX, DMA_LENGTH_DEF, "DMA_length", devname); velocity_set_int_opt(&opts->numrx, RxDescriptors[index], RX_DESC_MIN, RX_DESC_MAX, RX_DESC_DEF, "RxDescriptors", devname); velocity_set_int_opt(&opts->numtx, TxDescriptors[index], TX_DESC_MIN, TX_DESC_MAX, TX_DESC_DEF, "TxDescriptors", devname); - velocity_set_int_opt(&opts->vid, VID_setting[index], VLAN_ID_MIN, VLAN_ID_MAX, VLAN_ID_DEF, "VID_setting", devname); - velocity_set_bool_opt(&opts->flags, enable_tagging[index], TAGGING_DEF, VELOCITY_FLAGS_TAGGING, "enable_tagging", devname); velocity_set_bool_opt(&opts->flags, txcsum_offload[index], TX_CSUM_DEF, VELOCITY_FLAGS_TX_CSUM, "txcsum_offload", devname); velocity_set_int_opt(&opts->flow_cntl, flow_control[index], FLOW_CNTL_MIN, FLOW_CNTL_MAX, FLOW_CNTL_DEF, "flow_control", devname); velocity_set_bool_opt(&opts->flags, IP_byte_align[index], IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, "IP_byte_align", devname); @@ -463,6 +570,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 = 0; /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */ WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, ®s->MCFG); @@ -475,21 +583,9 @@ static void velocity_init_cam_filter(str 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 = 0; - mac_set_cam(regs, 0, (u8 *) &temp, VELOCITY_VLAN_ID_CAM); - temp = 1; - mac_set_cam_mask(regs, (u8 *) &temp, VELOCITY_VLAN_ID_CAM); - } + mac_set_cam(regs, 0, (u8 *) &temp, VELOCITY_VLAN_ID_CAM); + temp++; + mac_set_cam_mask(regs, (u8 *) &temp, VELOCITY_VLAN_ID_CAM); } /** @@ -791,6 +887,13 @@ static int __devinit velocity_found1(str dev->features |= NETIF_F_SG; #endif +#ifdef CONFIG_VIA_VELOCITY_VLAN + dev->vlan_rx_register = velocity_vlan_rx_register; + dev->vlan_rx_kill_vid = velocity_vlan_rx_kill_vid; + dev->vlan_rx_add_vid = velocity_vlan_rx_add_vid; + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; +#endif + if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) { dev->features |= NETIF_F_HW_CSUM; } @@ -1427,7 +1530,8 @@ static int velocity_receive_frame(struct skb->protocol = eth_type_trans(skb, skb->dev); stats->rx_bytes += pkt_len; - netif_rx(skb); + if (velocity_rx_vlan_skb(vptr, rd, skb) < 0) + netif_rx(skb); return 0; } @@ -1985,12 +2089,10 @@ static int velocity_xmit(struct sk_buff td_ptr->tdesc1.CMDZ = 2; } - if (vptr->flags & VELOCITY_FLAGS_TAGGING) { - td_ptr->tdesc1.pqinf.VID = (vptr->options.vid & 0xfff); - td_ptr->tdesc1.pqinf.priority = 0; - td_ptr->tdesc1.pqinf.CFI = 0; - td_ptr->tdesc1.TCR |= TCR0_VETAG; - } + td_ptr->tdesc1.u.pqinf.VID = velocity_tx_vlan_tag(vptr, skb); + td_ptr->tdesc1.u.pqinf.CFI = 0; + td_ptr->tdesc1.u.pqinf.priority = 0; + td_ptr->tdesc1.TCR |= vlan_tx_tag_present(skb) ? TCR0_VETAG : 0x00; /* * Handle hardware checksum diff -puN drivers/net/via-velocity.h~via-velocity-300 drivers/net/via-velocity.h --- linux-2.6.10-rc1/drivers/net/via-velocity.h~via-velocity-300 2004-11-08 00:59:23.000000000 +0100 +++ linux-2.6.10-rc1-fr/drivers/net/via-velocity.h 2004-11-09 00:57:13.000000000 +0100 @@ -201,8 +201,17 @@ struct rdesc0 { u16 owner:1; /* Who owns this buffer ? */ }; +struct pqinf { /* Priority queue info */ + u16 VID:12; + u16 CFI:1; + u16 priority:3; +} __attribute__ ((__packed__)); + struct rdesc1 { - u16 PQTAG; + union { + u16 vlan_tag; + struct pqinf pqinf; + } u; u8 CSM; u8 IPKT; }; @@ -227,14 +236,11 @@ struct tdesc0 { u16 owner:1; /* Who owns the buffer */ }; -struct pqinf { /* Priority queue info */ - u16 VID:12; - u16 CFI:1; - u16 priority:3; -} __attribute__ ((__packed__)); - struct tdesc1 { - struct pqinf pqinf; + union { + u16 vlan_tag; + struct pqinf pqinf; + } u; u8 TCR; u8 TCPLS:2; u8 reserved:2; @@ -1796,7 +1802,9 @@ struct velocity_info { u32 ticks; u32 rx_bytes; - +#ifdef CONFIG_VIA_VELOCITY_VLAN + struct vlan_group *vlgrp; +#endif }; /** diff -puN drivers/net/Kconfig~via-velocity-300 drivers/net/Kconfig --- linux-2.6.10-rc1/drivers/net/Kconfig~via-velocity-300 2004-11-08 00:59:23.000000000 +0100 +++ linux-2.6.10-rc1-fr/drivers/net/Kconfig 2004-11-08 01:00:20.000000000 +0100 @@ -2070,6 +2070,15 @@ config VIA_VELOCITY To compile this driver as a module, choose M here. The module will be called via-velocity. +config VIA_VELOCITY_VLAN + bool "VLAN support" + depends on VIA_VELOCITY && VLAN_8021Q + ---help--- + Say Y here for the via-velocity driver to support the functions + required by the kernel 802.1Q code. + + If in doubt, say Y. + config TIGON3 tristate "Broadcom Tigon3 support" depends on PCI _ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |