aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAyaz Abdulla <aabdulla@nvidia.com>2006-02-04 13:13:17 -0500
committerJeff Garzik <jgarzik@pobox.com>2006-02-20 05:59:18 -0500
commitee407b02f3f1992bc746876c26f8175c8783562b (patch)
treea005421bd26f8ca0178d4e9a3a7a79486a45f9de /drivers
parentbd71c2b17468a2531fb4c81ec1d73520845e97e1 (diff)
[PATCH] forcedeth: Add vlan support
This forcedeth patch adds support for vlan stripping/inserting in hardware. Signed-off-By: Ayaz Abdulla <aabdulla@nvidia.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/forcedeth.c76
1 files changed, 71 insertions, 5 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 3682ec61e8a8..0fbe342c2ac9 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -102,6 +102,7 @@
102 * 0.47: 26 Oct 2005: Add phyaddr 0 in phy scan. 102 * 0.47: 26 Oct 2005: Add phyaddr 0 in phy scan.
103 * 0.48: 24 Dec 2005: Disable TSO, bugfix for pci_map_single 103 * 0.48: 24 Dec 2005: Disable TSO, bugfix for pci_map_single
104 * 0.49: 10 Dec 2005: Fix tso for large buffers. 104 * 0.49: 10 Dec 2005: Fix tso for large buffers.
105 * 0.50: 20 Jan 2006: Add 8021pq tagging support.
105 * 106 *
106 * Known bugs: 107 * Known bugs:
107 * We suspect that on some hardware no TX done interrupts are generated. 108 * We suspect that on some hardware no TX done interrupts are generated.
@@ -113,7 +114,7 @@
113 * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few 114 * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
114 * superfluous timer interrupts from the nic. 115 * superfluous timer interrupts from the nic.
115 */ 116 */
116#define FORCEDETH_VERSION "0.49" 117#define FORCEDETH_VERSION "0.50"
117#define DRV_NAME "forcedeth" 118#define DRV_NAME "forcedeth"
118 119
119#include <linux/module.h> 120#include <linux/module.h>
@@ -153,6 +154,7 @@
153#define DEV_HAS_LARGEDESC 0x0004 /* device supports jumbo frames and needs packet format 2 */ 154#define DEV_HAS_LARGEDESC 0x0004 /* device supports jumbo frames and needs packet format 2 */
154#define DEV_HAS_HIGH_DMA 0x0008 /* device supports 64bit dma */ 155#define DEV_HAS_HIGH_DMA 0x0008 /* device supports 64bit dma */
155#define DEV_HAS_CHECKSUM 0x0010 /* device supports tx and rx checksum offloads */ 156#define DEV_HAS_CHECKSUM 0x0010 /* device supports tx and rx checksum offloads */
157#define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */
156 158
157enum { 159enum {
158 NvRegIrqStatus = 0x000, 160 NvRegIrqStatus = 0x000,
@@ -254,6 +256,8 @@ enum {
254#define NVREG_TXRXCTL_DESC_1 0 256#define NVREG_TXRXCTL_DESC_1 0
255#define NVREG_TXRXCTL_DESC_2 0x02100 257#define NVREG_TXRXCTL_DESC_2 0x02100
256#define NVREG_TXRXCTL_DESC_3 0x02200 258#define NVREG_TXRXCTL_DESC_3 0x02200
259#define NVREG_TXRXCTL_VLANSTRIP 0x00040
260#define NVREG_TXRXCTL_VLANINS 0x00080
257 NvRegMIIStatus = 0x180, 261 NvRegMIIStatus = 0x180,
258#define NVREG_MIISTAT_ERROR 0x0001 262#define NVREG_MIISTAT_ERROR 0x0001
259#define NVREG_MIISTAT_LINKCHANGE 0x0008 263#define NVREG_MIISTAT_LINKCHANGE 0x0008
@@ -303,6 +307,8 @@ enum {
303#define NVREG_POWERSTATE_D1 0x0001 307#define NVREG_POWERSTATE_D1 0x0001
304#define NVREG_POWERSTATE_D2 0x0002 308#define NVREG_POWERSTATE_D2 0x0002
305#define NVREG_POWERSTATE_D3 0x0003 309#define NVREG_POWERSTATE_D3 0x0003
310 NvRegVlanControl = 0x300,
311#define NVREG_VLANCONTROL_ENABLE 0x2000
306}; 312};
307 313
308/* Big endian: should work, but is untested */ 314/* Big endian: should work, but is untested */
@@ -314,7 +320,7 @@ struct ring_desc {
314struct ring_desc_ex { 320struct ring_desc_ex {
315 u32 PacketBufferHigh; 321 u32 PacketBufferHigh;
316 u32 PacketBufferLow; 322 u32 PacketBufferLow;
317 u32 Reserved; 323 u32 TxVlan;
318 u32 FlagLen; 324 u32 FlagLen;
319}; 325};
320 326
@@ -355,6 +361,8 @@ typedef union _ring_type {
355#define NV_TX2_CHECKSUM_L3 (1<<27) 361#define NV_TX2_CHECKSUM_L3 (1<<27)
356#define NV_TX2_CHECKSUM_L4 (1<<26) 362#define NV_TX2_CHECKSUM_L4 (1<<26)
357 363
364#define NV_TX3_VLAN_TAG_PRESENT (1<<18)
365
358#define NV_RX_DESCRIPTORVALID (1<<16) 366#define NV_RX_DESCRIPTORVALID (1<<16)
359#define NV_RX_MISSEDFRAME (1<<17) 367#define NV_RX_MISSEDFRAME (1<<17)
360#define NV_RX_SUBSTRACT1 (1<<18) 368#define NV_RX_SUBSTRACT1 (1<<18)
@@ -385,6 +393,9 @@ typedef union _ring_type {
385#define NV_RX2_ERROR (1<<30) 393#define NV_RX2_ERROR (1<<30)
386#define NV_RX2_AVAIL (1<<31) 394#define NV_RX2_AVAIL (1<<31)
387 395
396#define NV_RX3_VLAN_TAG_PRESENT (1<<16)
397#define NV_RX3_VLAN_TAG_MASK (0x0000FFFF)
398
388/* Miscelaneous hardware related defines: */ 399/* Miscelaneous hardware related defines: */
389#define NV_PCI_REGSZ 0x270 400#define NV_PCI_REGSZ 0x270
390 401
@@ -511,6 +522,7 @@ struct fe_priv {
511 u32 irqmask; 522 u32 irqmask;
512 u32 desc_ver; 523 u32 desc_ver;
513 u32 txrxctl_bits; 524 u32 txrxctl_bits;
525 u32 vlanctl_bits;
514 526
515 void __iomem *base; 527 void __iomem *base;
516 528
@@ -540,6 +552,9 @@ struct fe_priv {
540 dma_addr_t tx_dma[TX_RING]; 552 dma_addr_t tx_dma[TX_RING];
541 unsigned int tx_dma_len[TX_RING]; 553 unsigned int tx_dma_len[TX_RING];
542 u32 tx_flags; 554 u32 tx_flags;
555
556 /* vlan fields */
557 struct vlan_group *vlangrp;
543}; 558};
544 559
545/* 560/*
@@ -1031,6 +1046,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
1031 u32 bcnt; 1046 u32 bcnt;
1032 u32 size = skb->len-skb->data_len; 1047 u32 size = skb->len-skb->data_len;
1033 u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0); 1048 u32 entries = (size >> NV_TX2_TSO_MAX_SHIFT) + ((size & (NV_TX2_TSO_MAX_SIZE-1)) ? 1 : 0);
1049 u32 tx_flags_vlan = 0;
1034 1050
1035 /* add fragments to entries count */ 1051 /* add fragments to entries count */
1036 for (i = 0; i < fragments; i++) { 1052 for (i = 0; i < fragments; i++) {
@@ -1111,10 +1127,16 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
1111#endif 1127#endif
1112 tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0); 1128 tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
1113 1129
1130 /* vlan tag */
1131 if (np->vlangrp && vlan_tx_tag_present(skb)) {
1132 tx_flags_vlan = NV_TX3_VLAN_TAG_PRESENT | vlan_tx_tag_get(skb);
1133 }
1134
1114 /* set tx flags */ 1135 /* set tx flags */
1115 if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) { 1136 if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
1116 np->tx_ring.orig[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra); 1137 np->tx_ring.orig[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra);
1117 } else { 1138 } else {
1139 np->tx_ring.ex[start_nr].TxVlan = cpu_to_le32(tx_flags_vlan);
1118 np->tx_ring.ex[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra); 1140 np->tx_ring.ex[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra);
1119 } 1141 }
1120 1142
@@ -1342,6 +1364,8 @@ static void nv_rx_process(struct net_device *dev)
1342{ 1364{
1343 struct fe_priv *np = netdev_priv(dev); 1365 struct fe_priv *np = netdev_priv(dev);
1344 u32 Flags; 1366 u32 Flags;
1367 u32 vlanflags = 0;
1368
1345 1369
1346 for (;;) { 1370 for (;;) {
1347 struct sk_buff *skb; 1371 struct sk_buff *skb;
@@ -1357,6 +1381,7 @@ static void nv_rx_process(struct net_device *dev)
1357 } else { 1381 } else {
1358 Flags = le32_to_cpu(np->rx_ring.ex[i].FlagLen); 1382 Flags = le32_to_cpu(np->rx_ring.ex[i].FlagLen);
1359 len = nv_descr_getlength_ex(&np->rx_ring.ex[i], np->desc_ver); 1383 len = nv_descr_getlength_ex(&np->rx_ring.ex[i], np->desc_ver);
1384 vlanflags = le32_to_cpu(np->rx_ring.ex[i].PacketBufferLow);
1360 } 1385 }
1361 1386
1362 dprintk(KERN_DEBUG "%s: nv_rx_process: looking at packet %d, Flags 0x%x.\n", 1387 dprintk(KERN_DEBUG "%s: nv_rx_process: looking at packet %d, Flags 0x%x.\n",
@@ -1474,7 +1499,11 @@ static void nv_rx_process(struct net_device *dev)
1474 skb->protocol = eth_type_trans(skb, dev); 1499 skb->protocol = eth_type_trans(skb, dev);
1475 dprintk(KERN_DEBUG "%s: nv_rx_process: packet %d with %d bytes, proto %d accepted.\n", 1500 dprintk(KERN_DEBUG "%s: nv_rx_process: packet %d with %d bytes, proto %d accepted.\n",
1476 dev->name, np->cur_rx, len, skb->protocol); 1501 dev->name, np->cur_rx, len, skb->protocol);
1477 netif_rx(skb); 1502 if (np->vlangrp && (vlanflags & NV_RX3_VLAN_TAG_PRESENT)) {
1503 vlan_hwaccel_rx(skb, np->vlangrp, vlanflags & NV_RX3_VLAN_TAG_MASK);
1504 } else {
1505 netif_rx(skb);
1506 }
1478 dev->last_rx = jiffies; 1507 dev->last_rx = jiffies;
1479 np->stats.rx_packets++; 1508 np->stats.rx_packets++;
1480 np->stats.rx_bytes += len; 1509 np->stats.rx_bytes += len;
@@ -2217,6 +2246,34 @@ static struct ethtool_ops ops = {
2217 .get_perm_addr = ethtool_op_get_perm_addr, 2246 .get_perm_addr = ethtool_op_get_perm_addr,
2218}; 2247};
2219 2248
2249static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
2250{
2251 struct fe_priv *np = get_nvpriv(dev);
2252
2253 spin_lock_irq(&np->lock);
2254
2255 /* save vlan group */
2256 np->vlangrp = grp;
2257
2258 if (grp) {
2259 /* enable vlan on MAC */
2260 np->txrxctl_bits |= NVREG_TXRXCTL_VLANSTRIP | NVREG_TXRXCTL_VLANINS;
2261 } else {
2262 /* disable vlan on MAC */
2263 np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANSTRIP;
2264 np->txrxctl_bits &= ~NVREG_TXRXCTL_VLANINS;
2265 }
2266
2267 writel(np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
2268
2269 spin_unlock_irq(&np->lock);
2270};
2271
2272static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
2273{
2274 /* nothing to do */
2275};
2276
2220static int nv_open(struct net_device *dev) 2277static int nv_open(struct net_device *dev)
2221{ 2278{
2222 struct fe_priv *np = netdev_priv(dev); 2279 struct fe_priv *np = netdev_priv(dev);
@@ -2265,6 +2322,7 @@ static int nv_open(struct net_device *dev)
2265 writel(np->linkspeed, base + NvRegLinkSpeed); 2322 writel(np->linkspeed, base + NvRegLinkSpeed);
2266 writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3); 2323 writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
2267 writel(np->txrxctl_bits, base + NvRegTxRxControl); 2324 writel(np->txrxctl_bits, base + NvRegTxRxControl);
2325 writel(np->vlanctl_bits, base + NvRegVlanControl);
2268 pci_push(base); 2326 pci_push(base);
2269 writel(NVREG_TXRXCTL_BIT1|np->txrxctl_bits, base + NvRegTxRxControl); 2327 writel(NVREG_TXRXCTL_BIT1|np->txrxctl_bits, base + NvRegTxRxControl);
2270 reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, 2328 reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
@@ -2496,6 +2554,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
2496#endif 2554#endif
2497 } 2555 }
2498 2556
2557 np->vlanctl_bits = 0;
2558 if (id->driver_data & DEV_HAS_VLAN) {
2559 np->vlanctl_bits = NVREG_VLANCONTROL_ENABLE;
2560 dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX;
2561 dev->vlan_rx_register = nv_vlan_rx_register;
2562 dev->vlan_rx_kill_vid = nv_vlan_rx_kill_vid;
2563 }
2564
2499 err = -ENOMEM; 2565 err = -ENOMEM;
2500 np->base = ioremap(addr, NV_PCI_REGSZ); 2566 np->base = ioremap(addr, NV_PCI_REGSZ);
2501 if (!np->base) 2567 if (!np->base)
@@ -2737,11 +2803,11 @@ static struct pci_device_id pci_tbl[] = {
2737 }, 2803 },
2738 { /* MCP55 Ethernet Controller */ 2804 { /* MCP55 Ethernet Controller */
2739 PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), 2805 PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
2740 .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA, 2806 .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN,
2741 }, 2807 },
2742 { /* MCP55 Ethernet Controller */ 2808 { /* MCP55 Ethernet Controller */
2743 PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), 2809 PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
2744 .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA, 2810 .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN,
2745 }, 2811 },
2746 {0,}, 2812 {0,},
2747}; 2813};