diff options
Diffstat (limited to 'drivers/net/s2io.c')
-rw-r--r-- | drivers/net/s2io.c | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index ee498d248d38..db3e394c740b 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include <linux/ethtool.h> | 55 | #include <linux/ethtool.h> |
56 | #include <linux/version.h> | 56 | #include <linux/version.h> |
57 | #include <linux/workqueue.h> | 57 | #include <linux/workqueue.h> |
58 | #include <linux/if_vlan.h> | ||
58 | 59 | ||
59 | #include <asm/system.h> | 60 | #include <asm/system.h> |
60 | #include <asm/uaccess.h> | 61 | #include <asm/uaccess.h> |
@@ -174,6 +175,30 @@ static char ethtool_stats_keys[][ETH_GSTRING_LEN] = { | |||
174 | timer.data = (unsigned long) arg; \ | 175 | timer.data = (unsigned long) arg; \ |
175 | mod_timer(&timer, (jiffies + exp)) \ | 176 | mod_timer(&timer, (jiffies + exp)) \ |
176 | 177 | ||
178 | /* Add the vlan */ | ||
179 | static void s2io_vlan_rx_register(struct net_device *dev, | ||
180 | struct vlan_group *grp) | ||
181 | { | ||
182 | nic_t *nic = dev->priv; | ||
183 | unsigned long flags; | ||
184 | |||
185 | spin_lock_irqsave(&nic->tx_lock, flags); | ||
186 | nic->vlgrp = grp; | ||
187 | spin_unlock_irqrestore(&nic->tx_lock, flags); | ||
188 | } | ||
189 | |||
190 | /* Unregister the vlan */ | ||
191 | static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid) | ||
192 | { | ||
193 | nic_t *nic = dev->priv; | ||
194 | unsigned long flags; | ||
195 | |||
196 | spin_lock_irqsave(&nic->tx_lock, flags); | ||
197 | if (nic->vlgrp) | ||
198 | nic->vlgrp->vlan_devices[vid] = NULL; | ||
199 | spin_unlock_irqrestore(&nic->tx_lock, flags); | ||
200 | } | ||
201 | |||
177 | /* | 202 | /* |
178 | * Constants to be programmed into the Xena's registers, to configure | 203 | * Constants to be programmed into the Xena's registers, to configure |
179 | * the XAUI. | 204 | * the XAUI. |
@@ -2803,6 +2828,8 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2803 | #ifdef NETIF_F_TSO | 2828 | #ifdef NETIF_F_TSO |
2804 | int mss; | 2829 | int mss; |
2805 | #endif | 2830 | #endif |
2831 | u16 vlan_tag = 0; | ||
2832 | int vlan_priority = 0; | ||
2806 | mac_info_t *mac_control; | 2833 | mac_info_t *mac_control; |
2807 | struct config_param *config; | 2834 | struct config_param *config; |
2808 | 2835 | ||
@@ -2821,6 +2848,13 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2821 | 2848 | ||
2822 | queue = 0; | 2849 | queue = 0; |
2823 | 2850 | ||
2851 | /* Get Fifo number to Transmit based on vlan priority */ | ||
2852 | if (sp->vlgrp && vlan_tx_tag_present(skb)) { | ||
2853 | vlan_tag = vlan_tx_tag_get(skb); | ||
2854 | vlan_priority = vlan_tag >> 13; | ||
2855 | queue = config->fifo_mapping[vlan_priority]; | ||
2856 | } | ||
2857 | |||
2824 | put_off = (u16) mac_control->fifos[queue].tx_curr_put_info.offset; | 2858 | put_off = (u16) mac_control->fifos[queue].tx_curr_put_info.offset; |
2825 | get_off = (u16) mac_control->fifos[queue].tx_curr_get_info.offset; | 2859 | get_off = (u16) mac_control->fifos[queue].tx_curr_get_info.offset; |
2826 | txdp = (TxD_t *) mac_control->fifos[queue].list_info[put_off]. | 2860 | txdp = (TxD_t *) mac_control->fifos[queue].list_info[put_off]. |
@@ -2857,6 +2891,11 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2857 | 2891 | ||
2858 | txdp->Control_2 |= config->tx_intr_type; | 2892 | txdp->Control_2 |= config->tx_intr_type; |
2859 | 2893 | ||
2894 | if (sp->vlgrp && vlan_tx_tag_present(skb)) { | ||
2895 | txdp->Control_2 |= TXD_VLAN_ENABLE; | ||
2896 | txdp->Control_2 |= TXD_VLAN_TAG(vlan_tag); | ||
2897 | } | ||
2898 | |||
2860 | txdp->Control_1 |= (TXD_BUFFER0_SIZE(frg_len) | | 2899 | txdp->Control_1 |= (TXD_BUFFER0_SIZE(frg_len) | |
2861 | TXD_GATHER_CODE_FIRST); | 2900 | TXD_GATHER_CODE_FIRST); |
2862 | txdp->Control_1 |= TXD_LIST_OWN_XENA; | 2901 | txdp->Control_1 |= TXD_LIST_OWN_XENA; |
@@ -4653,10 +4692,23 @@ static int rx_osm_handler(ring_info_t *ring_data, RxD_t * rxdp) | |||
4653 | 4692 | ||
4654 | skb->protocol = eth_type_trans(skb, dev); | 4693 | skb->protocol = eth_type_trans(skb, dev); |
4655 | #ifdef CONFIG_S2IO_NAPI | 4694 | #ifdef CONFIG_S2IO_NAPI |
4656 | netif_receive_skb(skb); | 4695 | if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { |
4696 | /* Queueing the vlan frame to the upper layer */ | ||
4697 | vlan_hwaccel_receive_skb(skb, sp->vlgrp, | ||
4698 | RXD_GET_VLAN_TAG(rxdp->Control_2)); | ||
4699 | } else { | ||
4700 | netif_receive_skb(skb); | ||
4701 | } | ||
4657 | #else | 4702 | #else |
4658 | netif_rx(skb); | 4703 | if (sp->vlgrp && RXD_GET_VLAN_TAG(rxdp->Control_2)) { |
4704 | /* Queueing the vlan frame to the upper layer */ | ||
4705 | vlan_hwaccel_rx(skb, sp->vlgrp, | ||
4706 | RXD_GET_VLAN_TAG(rxdp->Control_2)); | ||
4707 | } else { | ||
4708 | netif_rx(skb); | ||
4709 | } | ||
4659 | #endif | 4710 | #endif |
4711 | |||
4660 | dev->last_rx = jiffies; | 4712 | dev->last_rx = jiffies; |
4661 | atomic_dec(&sp->rx_bufs_left[ring_no]); | 4713 | atomic_dec(&sp->rx_bufs_left[ring_no]); |
4662 | return SUCCESS; | 4714 | return SUCCESS; |
@@ -4954,6 +5006,9 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) | |||
4954 | dev->do_ioctl = &s2io_ioctl; | 5006 | dev->do_ioctl = &s2io_ioctl; |
4955 | dev->change_mtu = &s2io_change_mtu; | 5007 | dev->change_mtu = &s2io_change_mtu; |
4956 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 5008 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
5009 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | ||
5010 | dev->vlan_rx_register = s2io_vlan_rx_register; | ||
5011 | dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid; | ||
4957 | 5012 | ||
4958 | /* | 5013 | /* |
4959 | * will use eth_mac_addr() for dev->set_mac_address | 5014 | * will use eth_mac_addr() for dev->set_mac_address |