]> git.neil.brown.name Git - history.git/commitdiff
acenic gige net driver update: merge VLAN support from 2.4.x kernel
authorJeff Garzik <jgarzik@mandrakesoft.com>
Thu, 14 Mar 2002 22:35:21 +0000 (17:35 -0500)
committerJeff Garzik <jgarzik@mandrakesoft.com>
Thu, 14 Mar 2002 22:35:21 +0000 (17:35 -0500)
drivers/net/acenic.c
drivers/net/acenic.h

index c0cbb6ba45c82c0428410a36a019c74482a0fd90..7f9390dd4863f04ae46d65558528af1a61731c82 100644 (file)
@@ -65,6 +65,7 @@
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/sockios.h>
+#include <linux/if_vlan.h>
 
 #ifdef SIOCETHTOOL
 #include <linux/ethtool.h>
@@ -317,6 +318,12 @@ static inline void tasklet_init(struct tasklet_struct *tasklet,
 #define BOARD_IDX_STATIC       0
 #define BOARD_IDX_OVERFLOW     -1
 
+#if (defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)) && \
+       defined(NETIF_F_HW_VLAN_RX)
+#define ACENIC_DO_VLAN 1
+#else
+#define ACENIC_DO_VLAN 0
+#endif
 
 #include "acenic.h"
 
@@ -626,6 +633,11 @@ int __devinit acenic_probe (ACE_PROBE_ARG)
                dev->open = &ace_open;
                dev->hard_start_xmit = &ace_start_xmit;
                dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+#if ACENIC_DO_VLAN
+               dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+               dev->vlan_rx_register = ace_vlan_rx_register;
+               dev->vlan_rx_kill_vid = ace_vlan_rx_kill_vid;
+#endif
                if (1) {
                        static void ace_watchdog(struct net_device *dev);
                        dev->tx_timeout = &ace_watchdog;
@@ -1450,6 +1462,9 @@ static int __init ace_init(struct net_device *dev)
        set_aceaddr(&info->rx_std_ctrl.rngptr, ap->rx_ring_base_dma);
        info->rx_std_ctrl.max_len = ACE_STD_MTU + ETH_HLEN + 4;
        info->rx_std_ctrl.flags = RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
+#if ACENIC_DO_VLAN
+       info->rx_std_ctrl.flags |= RCB_FLG_VLAN_ASSIST;
+#endif
 
        memset(ap->rx_std_ring, 0,
               RX_STD_RING_ENTRIES * sizeof(struct rx_desc));
@@ -1465,6 +1480,9 @@ static int __init ace_init(struct net_device *dev)
                     (sizeof(struct rx_desc) * RX_STD_RING_ENTRIES)));
        info->rx_jumbo_ctrl.max_len = 0;
        info->rx_jumbo_ctrl.flags = RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
+#if ACENIC_DO_VLAN
+       info->rx_jumbo_ctrl.flags |= RCB_FLG_VLAN_ASSIST;
+#endif
 
        memset(ap->rx_jumbo_ring, 0,
               RX_JUMBO_RING_ENTRIES * sizeof(struct rx_desc));
@@ -1487,6 +1505,9 @@ static int __init ace_init(struct net_device *dev)
                info->rx_mini_ctrl.max_len = ACE_MINI_SIZE;
                info->rx_mini_ctrl.flags = 
                        RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
+#if ACENIC_DO_VLAN
+               info->rx_mini_ctrl.flags |= RCB_FLG_VLAN_ASSIST;
+#endif
 
                for (i = 0; i < RX_MINI_RING_ENTRIES; i++)
                        ap->rx_mini_ring[i].flags =
@@ -1542,6 +1563,9 @@ static int __init ace_init(struct net_device *dev)
                tmp |= RCB_FLG_TX_HOST_RING;
 #if TX_COAL_INTS_ONLY
        tmp |= RCB_FLG_COAL_INT_ONLY;
+#endif
+#if ACENIC_DO_VLAN
+       tmp |= RCB_FLG_VLAN_ASSIST;
 #endif
        info->tx_ctrl.flags = tmp;
 
@@ -1568,7 +1592,7 @@ static int __init ace_init(struct net_device *dev)
        ace_set_rxtx_parms(dev, 0);
 
        if (board_idx == BOARD_IDX_OVERFLOW) {
-               printk(KERN_WARNING "%s: more than %i NICs detected, "
+               printk(KERN_WARNING "%s: more then %i NICs detected, "
                       "ignoring module parameters!\n",
                       dev->name, ACE_MAX_MOD_PARMS);
        } else if (board_idx >= 0) {
@@ -2157,6 +2181,14 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
 }
 
 
+#if ACENIC_DO_VLAN
+static int ace_vlan_rx(struct ace_private *ap, struct sk_buff *skb, u16 vlan_tag)
+{
+       return vlan_hwaccel_rx(skb, ap->vlgrp, vlan_tag);
+}
+#endif
+
+
 static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
 {
        struct ace_private *ap = dev->priv;
@@ -2241,7 +2273,15 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
                        skb->ip_summed = CHECKSUM_NONE;
                }
 
-               netif_rx(skb);          /* send it up */
+               /* send it up */
+
+#if ACENIC_DO_VLAN
+               if (ap->vlgrp != NULL &&
+                   (bd_flags & BD_FLG_VLAN_TAG)) {
+                       ace_vlan_rx(ap, skb, retdesc->vlan);
+               } else
+#endif
+                       netif_rx(skb);
 
                dev->last_rx = jiffies;
                ap->stats.rx_packets++;
@@ -2465,6 +2505,37 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
 }
 
 
+#if ACENIC_DO_VLAN
+static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
+{
+       struct ace_private *ap = dev->priv;
+       unsigned long flags;
+
+       save_flags(flags);
+       cli();
+
+       ap->vlgrp = grp;
+
+       restore_flags(flags);
+}
+
+
+static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+{
+       struct ace_private *ap = dev->priv;
+       unsigned long flags;
+
+       save_flags(flags);
+       cli();
+
+       if (ap->vlgrp)
+               ap->vlgrp->vlan_devices[vid] = NULL;
+
+       restore_flags(flags);
+}
+#endif /* ACENIC_DO_VLAN */
+
+
 static int ace_open(struct net_device *dev)
 {
        struct ace_private *ap;
@@ -2629,20 +2700,27 @@ ace_map_tx_skb(struct ace_private *ap, struct sk_buff *skb,
 
 
 static inline void
-ace_load_tx_bd(struct ace_private *ap, struct tx_desc *desc,
-              u64 addr, u32 flagsize)
+ace_load_tx_bd(struct ace_private *ap, struct tx_desc *desc, u64 addr,
+              u32 flagsize, u32 vlan_tag)
 {
 #if !USE_TX_COAL_NOW
        flagsize &= ~BD_FLG_COAL_NOW;
 #endif
+
        if (!ACE_IS_TIGON_I(ap)) {
                writel(addr >> 32, &desc->addr.addrhi);
                writel(addr & 0xffffffff, &desc->addr.addrlo);
                writel(flagsize, &desc->flagsize);
+#if ACENIC_DO_VLAN
+               writel(vlan_tag, &desc->vlanres);
+#endif
        } else {
                desc->addr.addrhi = addr >> 32;
                desc->addr.addrlo = addr;
                desc->flagsize = flagsize;
+#if ACENIC_DO_VLAN
+               desc->vlanres = vlan_tag;
+#endif
        }
 }
 
@@ -2671,11 +2749,18 @@ restart:
 #endif
        {
                dma_addr_t mapping;
+               u32 vlan_tag = 0;
 
                mapping = ace_map_tx_skb(ap, skb, skb, idx);
                flagsize = (skb->len << 16) | (BD_FLG_END);
                if (skb->ip_summed == CHECKSUM_HW)
                        flagsize |= BD_FLG_TCP_UDP_SUM;
+#if ACENIC_DO_VLAN
+               if (vlan_tx_tag_present(skb)) {
+                       flagsize |= BD_FLG_VLAN_TAG;
+                       vlan_tag = vlan_tx_tag_get(skb);
+               }
+#endif
                desc = ap->tx_ring + idx;
                idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
 
@@ -2683,19 +2768,26 @@ restart:
                if (tx_ring_full(ap, ap->tx_ret_csm, idx))
                        flagsize |= BD_FLG_COAL_NOW;
 
-               ace_load_tx_bd(ap, desc, mapping, flagsize);
+               ace_load_tx_bd(ap, desc, mapping, flagsize, vlan_tag);
        }
 #if MAX_SKB_FRAGS
        else {
                dma_addr_t mapping;
+               u32 vlan_tag = 0;
                int i, len = 0;
 
                mapping = ace_map_tx_skb(ap, skb, NULL, idx);
                flagsize = ((skb->len - skb->data_len) << 16);
                if (skb->ip_summed == CHECKSUM_HW)
                        flagsize |= BD_FLG_TCP_UDP_SUM;
+#if ACENIC_DO_VLAN
+               if (vlan_tx_tag_present(skb)) {
+                       flagsize |= BD_FLG_VLAN_TAG;
+                       vlan_tag = vlan_tx_tag_get(skb);
+               }
+#endif
 
-               ace_load_tx_bd(ap, ap->tx_ring + idx, mapping, flagsize);
+               ace_load_tx_bd(ap, ap->tx_ring + idx, mapping, flagsize, vlan_tag);
 
                idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap);
 
@@ -2731,7 +2823,7 @@ restart:
                        }
                        pci_unmap_addr_set(info, mapping, mapping);
                        pci_unmap_len_set(info, maplen, frag->size);
-                       ace_load_tx_bd(ap, desc, mapping, flagsize);
+                       ace_load_tx_bd(ap, desc, mapping, flagsize, vlan_tag);
                }
        }
 #endif
index a268f063ce0d01da7b49c940fab1ea4939ac6908..8933695b83a93c335a9d456efc6ae2ead0890450 100644 (file)
@@ -417,7 +417,16 @@ struct cmd {
 #define BD_FLG_TCP_UDP_SUM     0x01
 #define BD_FLG_IP_SUM          0x02
 #define BD_FLG_END             0x04
+#define BD_FLG_MORE            0x08
 #define BD_FLG_JUMBO           0x10
+#define BD_FLG_UCAST           0x20
+#define BD_FLG_MCAST           0x40
+#define BD_FLG_BCAST           0x60
+#define BD_FLG_TYP_MASK                0x60
+#define BD_FLG_IP_FRAG         0x80
+#define BD_FLG_IP_FRAG_END     0x100
+#define BD_FLG_VLAN_TAG                0x200
+#define BD_FLG_FRAME_ERROR     0x400
 #define BD_FLG_COAL_NOW                0x800
 #define BD_FLG_MINI            0x1000
 
@@ -633,6 +642,10 @@ struct ace_private
        struct ace_skb          *skb;
        dma_addr_t              info_dma;       /* 32/64 bit */
 
+#if ACENIC_DO_VLAN
+       struct vlan_group       *vlgrp;
+#endif
+
        int                     version, link;
        int                     promisc, mcast_all;
 
@@ -760,5 +773,9 @@ static void ace_free_descriptors(struct net_device *dev);
 static void ace_init_cleanup(struct net_device *dev);
 static struct net_device_stats *ace_get_stats(struct net_device *dev);
 static int read_eeprom_byte(struct net_device *dev, unsigned long offset);
+#if ACENIC_DO_VLAN
+static void ace_vlan_rx_register(struct net_device *dev, struct vlan_group *grp);
+static void ace_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid);
+#endif
 
 #endif /* _ACENIC_H_ */