Commit 426d488d authored by Jeff Garzik's avatar Jeff Garzik

acenic gige net driver update: merge VLAN support from 2.4.x kernel

parent 38171d07
......@@ -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 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
#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 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
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 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
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
......
......@@ -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_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment