diff options
Diffstat (limited to 'drivers/net/via-velocity.c')
-rw-r--r-- | drivers/net/via-velocity.c | 73 |
1 files changed, 44 insertions, 29 deletions
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 511a74c6e78b..fd1ff123efa0 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -72,6 +72,7 @@ #include <linux/mii.h> #include <linux/in.h> #include <linux/if_arp.h> +#include <linux/if_vlan.h> #include <linux/ip.h> #include <linux/tcp.h> #include <linux/udp.h> @@ -111,15 +112,6 @@ VELOCITY_PARAM(RxDescriptors, "Number of receive descriptors"); #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 @@ -147,13 +139,6 @@ VELOCITY_PARAM(rx_thresh, "Receive fifo threshold"); */ 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) . @@ -442,8 +427,7 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index, 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); @@ -465,6 +449,7 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index, static void velocity_init_cam_filter(struct velocity_info *vptr) { struct mac_regs __iomem * regs = vptr->mac_regs; + unsigned short vid; /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */ WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, ®s->MCFG); @@ -477,13 +462,19 @@ static void velocity_init_cam_filter(struct velocity_info *vptr) 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); + if (vptr->vlgrp) { + for (vid = 0; vid < VLAN_VID_MASK; vid++) { + if (vlan_group_get_device(vptr->vlgrp, vid)) { + /* If Tagging option is enabled and + VLAN ID is not zero, then + turn on MCFG_RTGOPT also */ + if (vid != 0) + WORD_REG_BITS_ON(MCFG_RTGOPT, ®s->MCFG); + + mac_set_cam(regs, 0, (u8 *) &vid, + VELOCITY_VLAN_ID_CAM); + } + } vptr->vCAMmask[0] |= 1; mac_set_cam_mask(regs, vptr->vCAMmask, VELOCITY_VLAN_ID_CAM); } else { @@ -494,6 +485,26 @@ static void velocity_init_cam_filter(struct velocity_info *vptr) } } +static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) +{ + struct velocity_info *vptr = netdev_priv(dev); + + spin_lock_irq(&vptr->lock); + velocity_init_cam_filter(vptr); + spin_unlock_irq(&vptr->lock); +} + +static void velocity_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) +{ + struct velocity_info *vptr = netdev_priv(dev); + + spin_lock_irq(&vptr->lock); + vlan_group_set_device(vptr->vlgrp, vid, NULL); + velocity_init_cam_filter(vptr); + spin_unlock_irq(&vptr->lock); +} + + /** * velocity_rx_reset - handle a receive reset * @vptr: velocity we are resetting @@ -790,13 +801,17 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi dev->do_ioctl = velocity_ioctl; dev->ethtool_ops = &velocity_ethtool_ops; dev->change_mtu = velocity_change_mtu; + + dev->vlan_rx_add_vid = velocity_vlan_rx_add_vid; + dev->vlan_rx_kill_vid = velocity_vlan_rx_kill_vid; + #ifdef VELOCITY_ZERO_COPY_SUPPORT dev->features |= NETIF_F_SG; #endif + dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER; - if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) { + if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) dev->features |= NETIF_F_IP_CSUM; - } ret = register_netdev(dev); if (ret < 0) @@ -1989,8 +2004,8 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev) td_ptr->tdesc1.CMDZ = 2; } - if (vptr->flags & VELOCITY_FLAGS_TAGGING) { - td_ptr->tdesc1.pqinf.VID = (vptr->options.vid & 0xfff); + if (vptr->vlgrp && vlan_tx_tag_present(skb)) { + td_ptr->tdesc1.pqinf.VID = vlan_tx_tag_get(skb); td_ptr->tdesc1.pqinf.priority = 0; td_ptr->tdesc1.pqinf.CFI = 0; td_ptr->tdesc1.TCR |= TCR0_VETAG; |