|
@@ -95,6 +95,8 @@
|
|
* of nv_remove
|
|
* of nv_remove
|
|
* 0.42: 06 Aug 2005: Fix lack of link speed initialization
|
|
* 0.42: 06 Aug 2005: Fix lack of link speed initialization
|
|
* in the second (and later) nv_open call
|
|
* in the second (and later) nv_open call
|
|
|
|
+ * 0.43: 10 Aug 2005: Add support for tx checksum.
|
|
|
|
+ * 0.44: 20 Aug 2005: Add support for scatter gather and segmentation.
|
|
*
|
|
*
|
|
* Known bugs:
|
|
* Known bugs:
|
|
* We suspect that on some hardware no TX done interrupts are generated.
|
|
* We suspect that on some hardware no TX done interrupts are generated.
|
|
@@ -106,7 +108,7 @@
|
|
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
|
|
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
|
|
* superfluous timer interrupts from the nic.
|
|
* superfluous timer interrupts from the nic.
|
|
*/
|
|
*/
|
|
-#define FORCEDETH_VERSION "0.41"
|
|
|
|
|
|
+#define FORCEDETH_VERSION "0.44"
|
|
#define DRV_NAME "forcedeth"
|
|
#define DRV_NAME "forcedeth"
|
|
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/module.h>
|
|
@@ -145,6 +147,7 @@
|
|
#define DEV_NEED_LINKTIMER 0x0002 /* poll link settings. Relies on the timer irq */
|
|
#define DEV_NEED_LINKTIMER 0x0002 /* poll link settings. Relies on the timer irq */
|
|
#define DEV_HAS_LARGEDESC 0x0004 /* device supports jumbo frames and needs packet format 2 */
|
|
#define DEV_HAS_LARGEDESC 0x0004 /* device supports jumbo frames and needs packet format 2 */
|
|
#define DEV_HAS_HIGH_DMA 0x0008 /* device supports 64bit dma */
|
|
#define DEV_HAS_HIGH_DMA 0x0008 /* device supports 64bit dma */
|
|
|
|
+#define DEV_HAS_CHECKSUM 0x0010 /* device supports tx and rx checksum offloads */
|
|
|
|
|
|
enum {
|
|
enum {
|
|
NvRegIrqStatus = 0x000,
|
|
NvRegIrqStatus = 0x000,
|
|
@@ -241,6 +244,9 @@ enum {
|
|
#define NVREG_TXRXCTL_IDLE 0x0008
|
|
#define NVREG_TXRXCTL_IDLE 0x0008
|
|
#define NVREG_TXRXCTL_RESET 0x0010
|
|
#define NVREG_TXRXCTL_RESET 0x0010
|
|
#define NVREG_TXRXCTL_RXCHECK 0x0400
|
|
#define NVREG_TXRXCTL_RXCHECK 0x0400
|
|
|
|
+#define NVREG_TXRXCTL_DESC_1 0
|
|
|
|
+#define NVREG_TXRXCTL_DESC_2 0x02100
|
|
|
|
+#define NVREG_TXRXCTL_DESC_3 0x02200
|
|
NvRegMIIStatus = 0x180,
|
|
NvRegMIIStatus = 0x180,
|
|
#define NVREG_MIISTAT_ERROR 0x0001
|
|
#define NVREG_MIISTAT_ERROR 0x0001
|
|
#define NVREG_MIISTAT_LINKCHANGE 0x0008
|
|
#define NVREG_MIISTAT_LINKCHANGE 0x0008
|
|
@@ -335,6 +341,10 @@ typedef union _ring_type {
|
|
/* error and valid are the same for both */
|
|
/* error and valid are the same for both */
|
|
#define NV_TX2_ERROR (1<<30)
|
|
#define NV_TX2_ERROR (1<<30)
|
|
#define NV_TX2_VALID (1<<31)
|
|
#define NV_TX2_VALID (1<<31)
|
|
|
|
+#define NV_TX2_TSO (1<<28)
|
|
|
|
+#define NV_TX2_TSO_SHIFT 14
|
|
|
|
+#define NV_TX2_CHECKSUM_L3 (1<<27)
|
|
|
|
+#define NV_TX2_CHECKSUM_L4 (1<<26)
|
|
|
|
|
|
#define NV_RX_DESCRIPTORVALID (1<<16)
|
|
#define NV_RX_DESCRIPTORVALID (1<<16)
|
|
#define NV_RX_MISSEDFRAME (1<<17)
|
|
#define NV_RX_MISSEDFRAME (1<<17)
|
|
@@ -417,14 +427,14 @@ typedef union _ring_type {
|
|
|
|
|
|
/*
|
|
/*
|
|
* desc_ver values:
|
|
* desc_ver values:
|
|
- * This field has two purposes:
|
|
|
|
- * - Newer nics uses a different ring layout. The layout is selected by
|
|
|
|
- * comparing np->desc_ver with DESC_VER_xy.
|
|
|
|
- * - It contains bits that are forced on when writing to NvRegTxRxControl.
|
|
|
|
|
|
+ * The nic supports three different descriptor types:
|
|
|
|
+ * - DESC_VER_1: Original
|
|
|
|
+ * - DESC_VER_2: support for jumbo frames.
|
|
|
|
+ * - DESC_VER_3: 64-bit format.
|
|
*/
|
|
*/
|
|
-#define DESC_VER_1 0x0
|
|
|
|
-#define DESC_VER_2 (0x02100|NVREG_TXRXCTL_RXCHECK)
|
|
|
|
-#define DESC_VER_3 (0x02200|NVREG_TXRXCTL_RXCHECK)
|
|
|
|
|
|
+#define DESC_VER_1 1
|
|
|
|
+#define DESC_VER_2 2
|
|
|
|
+#define DESC_VER_3 3
|
|
|
|
|
|
/* PHY defines */
|
|
/* PHY defines */
|
|
#define PHY_OUI_MARVELL 0x5043
|
|
#define PHY_OUI_MARVELL 0x5043
|
|
@@ -491,6 +501,7 @@ struct fe_priv {
|
|
u32 orig_mac[2];
|
|
u32 orig_mac[2];
|
|
u32 irqmask;
|
|
u32 irqmask;
|
|
u32 desc_ver;
|
|
u32 desc_ver;
|
|
|
|
+ u32 txrxctl_bits;
|
|
|
|
|
|
void __iomem *base;
|
|
void __iomem *base;
|
|
|
|
|
|
@@ -534,7 +545,7 @@ static inline struct fe_priv *get_nvpriv(struct net_device *dev)
|
|
|
|
|
|
static inline u8 __iomem *get_hwbase(struct net_device *dev)
|
|
static inline u8 __iomem *get_hwbase(struct net_device *dev)
|
|
{
|
|
{
|
|
- return get_nvpriv(dev)->base;
|
|
|
|
|
|
+ return ((struct fe_priv *)netdev_priv(dev))->base;
|
|
}
|
|
}
|
|
|
|
|
|
static inline void pci_push(u8 __iomem *base)
|
|
static inline void pci_push(u8 __iomem *base)
|
|
@@ -623,7 +634,7 @@ static int mii_rw(struct net_device *dev, int addr, int miireg, int value)
|
|
|
|
|
|
static int phy_reset(struct net_device *dev)
|
|
static int phy_reset(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u32 miicontrol;
|
|
u32 miicontrol;
|
|
unsigned int tries = 0;
|
|
unsigned int tries = 0;
|
|
|
|
|
|
@@ -726,7 +737,7 @@ static int phy_init(struct net_device *dev)
|
|
|
|
|
|
static void nv_start_rx(struct net_device *dev)
|
|
static void nv_start_rx(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
|
|
|
|
dprintk(KERN_DEBUG "%s: nv_start_rx\n", dev->name);
|
|
dprintk(KERN_DEBUG "%s: nv_start_rx\n", dev->name);
|
|
@@ -782,14 +793,14 @@ static void nv_stop_tx(struct net_device *dev)
|
|
|
|
|
|
static void nv_txrx_reset(struct net_device *dev)
|
|
static void nv_txrx_reset(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
|
|
|
|
dprintk(KERN_DEBUG "%s: nv_txrx_reset\n", dev->name);
|
|
dprintk(KERN_DEBUG "%s: nv_txrx_reset\n", dev->name);
|
|
- writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl);
|
|
|
|
|
|
+ writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
|
|
pci_push(base);
|
|
pci_push(base);
|
|
udelay(NV_TXRX_RESET_DELAY);
|
|
udelay(NV_TXRX_RESET_DELAY);
|
|
- writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl);
|
|
|
|
|
|
+ writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl);
|
|
pci_push(base);
|
|
pci_push(base);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -801,7 +812,7 @@ static void nv_txrx_reset(struct net_device *dev)
|
|
*/
|
|
*/
|
|
static struct net_device_stats *nv_get_stats(struct net_device *dev)
|
|
static struct net_device_stats *nv_get_stats(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
|
|
|
|
/* It seems that the nic always generates interrupts and doesn't
|
|
/* It seems that the nic always generates interrupts and doesn't
|
|
* accumulate errors internally. Thus the current values in np->stats
|
|
* accumulate errors internally. Thus the current values in np->stats
|
|
@@ -817,7 +828,7 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev)
|
|
*/
|
|
*/
|
|
static int nv_alloc_rx(struct net_device *dev)
|
|
static int nv_alloc_rx(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
unsigned int refill_rx = np->refill_rx;
|
|
unsigned int refill_rx = np->refill_rx;
|
|
int nr;
|
|
int nr;
|
|
|
|
|
|
@@ -861,7 +872,7 @@ static int nv_alloc_rx(struct net_device *dev)
|
|
static void nv_do_rx_refill(unsigned long data)
|
|
static void nv_do_rx_refill(unsigned long data)
|
|
{
|
|
{
|
|
struct net_device *dev = (struct net_device *) data;
|
|
struct net_device *dev = (struct net_device *) data;
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
|
|
|
|
disable_irq(dev->irq);
|
|
disable_irq(dev->irq);
|
|
if (nv_alloc_rx(dev)) {
|
|
if (nv_alloc_rx(dev)) {
|
|
@@ -875,7 +886,7 @@ static void nv_do_rx_refill(unsigned long data)
|
|
|
|
|
|
static void nv_init_rx(struct net_device *dev)
|
|
static void nv_init_rx(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
int i;
|
|
int i;
|
|
|
|
|
|
np->cur_rx = RX_RING;
|
|
np->cur_rx = RX_RING;
|
|
@@ -889,15 +900,17 @@ static void nv_init_rx(struct net_device *dev)
|
|
|
|
|
|
static void nv_init_tx(struct net_device *dev)
|
|
static void nv_init_tx(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
int i;
|
|
int i;
|
|
|
|
|
|
np->next_tx = np->nic_tx = 0;
|
|
np->next_tx = np->nic_tx = 0;
|
|
- for (i = 0; i < TX_RING; i++)
|
|
|
|
|
|
+ for (i = 0; i < TX_RING; i++) {
|
|
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
|
|
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
|
|
np->tx_ring.orig[i].FlagLen = 0;
|
|
np->tx_ring.orig[i].FlagLen = 0;
|
|
else
|
|
else
|
|
np->tx_ring.ex[i].FlagLen = 0;
|
|
np->tx_ring.ex[i].FlagLen = 0;
|
|
|
|
+ np->tx_skbuff[i] = NULL;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
static int nv_init_ring(struct net_device *dev)
|
|
static int nv_init_ring(struct net_device *dev)
|
|
@@ -907,21 +920,44 @@ static int nv_init_ring(struct net_device *dev)
|
|
return nv_alloc_rx(dev);
|
|
return nv_alloc_rx(dev);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void nv_release_txskb(struct net_device *dev, unsigned int skbnr)
|
|
|
|
+{
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
|
|
+ struct sk_buff *skb = np->tx_skbuff[skbnr];
|
|
|
|
+ unsigned int j, entry, fragments;
|
|
|
|
+
|
|
|
|
+ dprintk(KERN_INFO "%s: nv_release_txskb for skbnr %d, skb %p\n",
|
|
|
|
+ dev->name, skbnr, np->tx_skbuff[skbnr]);
|
|
|
|
+
|
|
|
|
+ entry = skbnr;
|
|
|
|
+ if ((fragments = skb_shinfo(skb)->nr_frags) != 0) {
|
|
|
|
+ for (j = fragments; j >= 1; j--) {
|
|
|
|
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[j-1];
|
|
|
|
+ pci_unmap_page(np->pci_dev, np->tx_dma[entry],
|
|
|
|
+ frag->size,
|
|
|
|
+ PCI_DMA_TODEVICE);
|
|
|
|
+ entry = (entry - 1) % TX_RING;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ pci_unmap_single(np->pci_dev, np->tx_dma[entry],
|
|
|
|
+ skb->len - skb->data_len,
|
|
|
|
+ PCI_DMA_TODEVICE);
|
|
|
|
+ dev_kfree_skb_irq(skb);
|
|
|
|
+ np->tx_skbuff[skbnr] = NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
static void nv_drain_tx(struct net_device *dev)
|
|
static void nv_drain_tx(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
- int i;
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
|
|
+ unsigned int i;
|
|
|
|
+
|
|
for (i = 0; i < TX_RING; i++) {
|
|
for (i = 0; i < TX_RING; i++) {
|
|
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
|
|
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
|
|
np->tx_ring.orig[i].FlagLen = 0;
|
|
np->tx_ring.orig[i].FlagLen = 0;
|
|
else
|
|
else
|
|
np->tx_ring.ex[i].FlagLen = 0;
|
|
np->tx_ring.ex[i].FlagLen = 0;
|
|
if (np->tx_skbuff[i]) {
|
|
if (np->tx_skbuff[i]) {
|
|
- pci_unmap_single(np->pci_dev, np->tx_dma[i],
|
|
|
|
- np->tx_skbuff[i]->len,
|
|
|
|
- PCI_DMA_TODEVICE);
|
|
|
|
- dev_kfree_skb(np->tx_skbuff[i]);
|
|
|
|
- np->tx_skbuff[i] = NULL;
|
|
|
|
|
|
+ nv_release_txskb(dev, i);
|
|
np->stats.tx_dropped++;
|
|
np->stats.tx_dropped++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -929,7 +965,7 @@ static void nv_drain_tx(struct net_device *dev)
|
|
|
|
|
|
static void nv_drain_rx(struct net_device *dev)
|
|
static void nv_drain_rx(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
int i;
|
|
int i;
|
|
for (i = 0; i < RX_RING; i++) {
|
|
for (i = 0; i < RX_RING; i++) {
|
|
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
|
|
if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
|
|
@@ -959,28 +995,69 @@ static void drain_ring(struct net_device *dev)
|
|
*/
|
|
*/
|
|
static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
- int nr = np->next_tx % TX_RING;
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
|
|
+ u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
|
|
|
|
+ unsigned int fragments = skb_shinfo(skb)->nr_frags;
|
|
|
|
+ unsigned int nr = (np->next_tx + fragments) % TX_RING;
|
|
|
|
+ unsigned int i;
|
|
|
|
+
|
|
|
|
+ spin_lock_irq(&np->lock);
|
|
|
|
+
|
|
|
|
+ if ((np->next_tx - np->nic_tx + fragments) > TX_LIMIT_STOP) {
|
|
|
|
+ spin_unlock_irq(&np->lock);
|
|
|
|
+ netif_stop_queue(dev);
|
|
|
|
+ return NETDEV_TX_BUSY;
|
|
|
|
+ }
|
|
|
|
|
|
np->tx_skbuff[nr] = skb;
|
|
np->tx_skbuff[nr] = skb;
|
|
- np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data,skb->len,
|
|
|
|
- PCI_DMA_TODEVICE);
|
|
|
|
|
|
+
|
|
|
|
+ if (fragments) {
|
|
|
|
+ dprintk(KERN_DEBUG "%s: nv_start_xmit: buffer contains %d fragments\n", dev->name, fragments);
|
|
|
|
+ /* setup descriptors in reverse order */
|
|
|
|
+ for (i = fragments; i >= 1; i--) {
|
|
|
|
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
|
|
|
|
+ np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset, frag->size,
|
|
|
|
+ PCI_DMA_TODEVICE);
|
|
|
|
|
|
- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
|
|
|
|
|
|
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
|
|
|
|
+ np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
|
|
|
|
+ np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
|
|
|
|
+ } else {
|
|
|
|
+ np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
|
|
|
|
+ np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
|
|
|
|
+ np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (frag->size-1) | np->tx_flags | tx_flags_extra);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ nr = (nr - 1) % TX_RING;
|
|
|
|
+
|
|
|
|
+ if (np->desc_ver == DESC_VER_1)
|
|
|
|
+ tx_flags_extra &= ~NV_TX_LASTPACKET;
|
|
|
|
+ else
|
|
|
|
+ tx_flags_extra &= ~NV_TX2_LASTPACKET;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+#ifdef NETIF_F_TSO
|
|
|
|
+ if (skb_shinfo(skb)->tso_size)
|
|
|
|
+ tx_flags_extra |= NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT);
|
|
|
|
+ else
|
|
|
|
+#endif
|
|
|
|
+ tx_flags_extra |= (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
|
|
|
|
+
|
|
|
|
+ np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data, skb->len-skb->data_len,
|
|
|
|
+ PCI_DMA_TODEVICE);
|
|
|
|
+
|
|
|
|
+ if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
|
|
np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
|
|
np->tx_ring.orig[nr].PacketBuffer = cpu_to_le32(np->tx_dma[nr]);
|
|
- else {
|
|
|
|
|
|
+ np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
|
|
|
|
+ } else {
|
|
np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
|
|
np->tx_ring.ex[nr].PacketBufferHigh = cpu_to_le64(np->tx_dma[nr]) >> 32;
|
|
np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
|
|
np->tx_ring.ex[nr].PacketBufferLow = cpu_to_le64(np->tx_dma[nr]) & 0x0FFFFFFFF;
|
|
- }
|
|
|
|
|
|
+ np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-skb->data_len-1) | np->tx_flags | tx_flags_extra);
|
|
|
|
+ }
|
|
|
|
|
|
- spin_lock_irq(&np->lock);
|
|
|
|
- wmb();
|
|
|
|
- if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
|
|
|
|
- np->tx_ring.orig[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
|
|
|
|
- else
|
|
|
|
- np->tx_ring.ex[nr].FlagLen = cpu_to_le32( (skb->len-1) | np->tx_flags );
|
|
|
|
- dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission.\n",
|
|
|
|
- dev->name, np->next_tx);
|
|
|
|
|
|
+ dprintk(KERN_DEBUG "%s: nv_start_xmit: packet packet %d queued for transmission. tx_flags_extra: %x\n",
|
|
|
|
+ dev->name, np->next_tx, tx_flags_extra);
|
|
{
|
|
{
|
|
int j;
|
|
int j;
|
|
for (j=0; j<64; j++) {
|
|
for (j=0; j<64; j++) {
|
|
@@ -991,15 +1068,13 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
dprintk("\n");
|
|
dprintk("\n");
|
|
}
|
|
}
|
|
|
|
|
|
- np->next_tx++;
|
|
|
|
|
|
+ np->next_tx += 1 + fragments;
|
|
|
|
|
|
dev->trans_start = jiffies;
|
|
dev->trans_start = jiffies;
|
|
- if (np->next_tx - np->nic_tx >= TX_LIMIT_STOP)
|
|
|
|
- netif_stop_queue(dev);
|
|
|
|
spin_unlock_irq(&np->lock);
|
|
spin_unlock_irq(&np->lock);
|
|
- writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
|
|
|
|
|
|
+ writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
|
|
pci_push(get_hwbase(dev));
|
|
pci_push(get_hwbase(dev));
|
|
- return 0;
|
|
|
|
|
|
+ return NETDEV_TX_OK;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1009,9 +1084,10 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
*/
|
|
*/
|
|
static void nv_tx_done(struct net_device *dev)
|
|
static void nv_tx_done(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u32 Flags;
|
|
u32 Flags;
|
|
- int i;
|
|
|
|
|
|
+ unsigned int i;
|
|
|
|
+ struct sk_buff *skb;
|
|
|
|
|
|
while (np->nic_tx != np->next_tx) {
|
|
while (np->nic_tx != np->next_tx) {
|
|
i = np->nic_tx % TX_RING;
|
|
i = np->nic_tx % TX_RING;
|
|
@@ -1026,35 +1102,38 @@ static void nv_tx_done(struct net_device *dev)
|
|
if (Flags & NV_TX_VALID)
|
|
if (Flags & NV_TX_VALID)
|
|
break;
|
|
break;
|
|
if (np->desc_ver == DESC_VER_1) {
|
|
if (np->desc_ver == DESC_VER_1) {
|
|
- if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
|
|
|
|
- NV_TX_UNDERFLOW|NV_TX_ERROR)) {
|
|
|
|
- if (Flags & NV_TX_UNDERFLOW)
|
|
|
|
- np->stats.tx_fifo_errors++;
|
|
|
|
- if (Flags & NV_TX_CARRIERLOST)
|
|
|
|
- np->stats.tx_carrier_errors++;
|
|
|
|
- np->stats.tx_errors++;
|
|
|
|
- } else {
|
|
|
|
- np->stats.tx_packets++;
|
|
|
|
- np->stats.tx_bytes += np->tx_skbuff[i]->len;
|
|
|
|
|
|
+ if (Flags & NV_TX_LASTPACKET) {
|
|
|
|
+ skb = np->tx_skbuff[i];
|
|
|
|
+ if (Flags & (NV_TX_RETRYERROR|NV_TX_CARRIERLOST|NV_TX_LATECOLLISION|
|
|
|
|
+ NV_TX_UNDERFLOW|NV_TX_ERROR)) {
|
|
|
|
+ if (Flags & NV_TX_UNDERFLOW)
|
|
|
|
+ np->stats.tx_fifo_errors++;
|
|
|
|
+ if (Flags & NV_TX_CARRIERLOST)
|
|
|
|
+ np->stats.tx_carrier_errors++;
|
|
|
|
+ np->stats.tx_errors++;
|
|
|
|
+ } else {
|
|
|
|
+ np->stats.tx_packets++;
|
|
|
|
+ np->stats.tx_bytes += skb->len;
|
|
|
|
+ }
|
|
|
|
+ nv_release_txskb(dev, i);
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
|
|
|
|
- NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
|
|
|
|
- if (Flags & NV_TX2_UNDERFLOW)
|
|
|
|
- np->stats.tx_fifo_errors++;
|
|
|
|
- if (Flags & NV_TX2_CARRIERLOST)
|
|
|
|
- np->stats.tx_carrier_errors++;
|
|
|
|
- np->stats.tx_errors++;
|
|
|
|
- } else {
|
|
|
|
- np->stats.tx_packets++;
|
|
|
|
- np->stats.tx_bytes += np->tx_skbuff[i]->len;
|
|
|
|
|
|
+ if (Flags & NV_TX2_LASTPACKET) {
|
|
|
|
+ skb = np->tx_skbuff[i];
|
|
|
|
+ if (Flags & (NV_TX2_RETRYERROR|NV_TX2_CARRIERLOST|NV_TX2_LATECOLLISION|
|
|
|
|
+ NV_TX2_UNDERFLOW|NV_TX2_ERROR)) {
|
|
|
|
+ if (Flags & NV_TX2_UNDERFLOW)
|
|
|
|
+ np->stats.tx_fifo_errors++;
|
|
|
|
+ if (Flags & NV_TX2_CARRIERLOST)
|
|
|
|
+ np->stats.tx_carrier_errors++;
|
|
|
|
+ np->stats.tx_errors++;
|
|
|
|
+ } else {
|
|
|
|
+ np->stats.tx_packets++;
|
|
|
|
+ np->stats.tx_bytes += skb->len;
|
|
|
|
+ }
|
|
|
|
+ nv_release_txskb(dev, i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- pci_unmap_single(np->pci_dev, np->tx_dma[i],
|
|
|
|
- np->tx_skbuff[i]->len,
|
|
|
|
- PCI_DMA_TODEVICE);
|
|
|
|
- dev_kfree_skb_irq(np->tx_skbuff[i]);
|
|
|
|
- np->tx_skbuff[i] = NULL;
|
|
|
|
np->nic_tx++;
|
|
np->nic_tx++;
|
|
}
|
|
}
|
|
if (np->next_tx - np->nic_tx < TX_LIMIT_START)
|
|
if (np->next_tx - np->nic_tx < TX_LIMIT_START)
|
|
@@ -1067,7 +1146,7 @@ static void nv_tx_done(struct net_device *dev)
|
|
*/
|
|
*/
|
|
static void nv_tx_timeout(struct net_device *dev)
|
|
static void nv_tx_timeout(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
|
|
|
|
printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name,
|
|
printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name,
|
|
@@ -1200,7 +1279,7 @@ static int nv_getlen(struct net_device *dev, void *packet, int datalen)
|
|
|
|
|
|
static void nv_rx_process(struct net_device *dev)
|
|
static void nv_rx_process(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u32 Flags;
|
|
u32 Flags;
|
|
|
|
|
|
for (;;) {
|
|
for (;;) {
|
|
@@ -1355,7 +1434,7 @@ static void set_bufsize(struct net_device *dev)
|
|
*/
|
|
*/
|
|
static int nv_change_mtu(struct net_device *dev, int new_mtu)
|
|
static int nv_change_mtu(struct net_device *dev, int new_mtu)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
int old_mtu;
|
|
int old_mtu;
|
|
|
|
|
|
if (new_mtu < 64 || new_mtu > np->pkt_limit)
|
|
if (new_mtu < 64 || new_mtu > np->pkt_limit)
|
|
@@ -1408,7 +1487,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu)
|
|
writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
|
|
writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
|
|
base + NvRegRingSizes);
|
|
base + NvRegRingSizes);
|
|
pci_push(base);
|
|
pci_push(base);
|
|
- writel(NVREG_TXRXCTL_KICK|np->desc_ver, get_hwbase(dev) + NvRegTxRxControl);
|
|
|
|
|
|
+ writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
|
|
pci_push(base);
|
|
pci_push(base);
|
|
|
|
|
|
/* restart rx engine */
|
|
/* restart rx engine */
|
|
@@ -1440,7 +1519,7 @@ static void nv_copy_mac_to_hw(struct net_device *dev)
|
|
*/
|
|
*/
|
|
static int nv_set_mac_address(struct net_device *dev, void *addr)
|
|
static int nv_set_mac_address(struct net_device *dev, void *addr)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
struct sockaddr *macaddr = (struct sockaddr*)addr;
|
|
struct sockaddr *macaddr = (struct sockaddr*)addr;
|
|
|
|
|
|
if(!is_valid_ether_addr(macaddr->sa_data))
|
|
if(!is_valid_ether_addr(macaddr->sa_data))
|
|
@@ -1475,7 +1554,7 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
|
|
*/
|
|
*/
|
|
static void nv_set_multicast(struct net_device *dev)
|
|
static void nv_set_multicast(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
u32 addr[2];
|
|
u32 addr[2];
|
|
u32 mask[2];
|
|
u32 mask[2];
|
|
@@ -1535,7 +1614,7 @@ static void nv_set_multicast(struct net_device *dev)
|
|
|
|
|
|
static int nv_update_linkspeed(struct net_device *dev)
|
|
static int nv_update_linkspeed(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
int adv, lpa;
|
|
int adv, lpa;
|
|
int newls = np->linkspeed;
|
|
int newls = np->linkspeed;
|
|
@@ -1705,7 +1784,7 @@ static void nv_link_irq(struct net_device *dev)
|
|
static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
|
|
static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
|
|
{
|
|
{
|
|
struct net_device *dev = (struct net_device *) data;
|
|
struct net_device *dev = (struct net_device *) data;
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
u32 events;
|
|
u32 events;
|
|
int i;
|
|
int i;
|
|
@@ -1777,7 +1856,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
|
|
static void nv_do_nic_poll(unsigned long data)
|
|
static void nv_do_nic_poll(unsigned long data)
|
|
{
|
|
{
|
|
struct net_device *dev = (struct net_device *) data;
|
|
struct net_device *dev = (struct net_device *) data;
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
|
|
|
|
disable_irq(dev->irq);
|
|
disable_irq(dev->irq);
|
|
@@ -1801,7 +1880,7 @@ static void nv_poll_controller(struct net_device *dev)
|
|
|
|
|
|
static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
|
|
static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
strcpy(info->driver, "forcedeth");
|
|
strcpy(info->driver, "forcedeth");
|
|
strcpy(info->version, FORCEDETH_VERSION);
|
|
strcpy(info->version, FORCEDETH_VERSION);
|
|
strcpy(info->bus_info, pci_name(np->pci_dev));
|
|
strcpy(info->bus_info, pci_name(np->pci_dev));
|
|
@@ -1809,7 +1888,7 @@ static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
|
|
|
|
|
|
static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
|
|
static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
wolinfo->supported = WAKE_MAGIC;
|
|
wolinfo->supported = WAKE_MAGIC;
|
|
|
|
|
|
spin_lock_irq(&np->lock);
|
|
spin_lock_irq(&np->lock);
|
|
@@ -1820,7 +1899,7 @@ static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
|
|
|
|
|
|
static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
|
|
static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
|
|
|
|
spin_lock_irq(&np->lock);
|
|
spin_lock_irq(&np->lock);
|
|
@@ -2021,7 +2100,7 @@ static int nv_get_regs_len(struct net_device *dev)
|
|
|
|
|
|
static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
|
|
static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
u32 *rbuf = buf;
|
|
u32 *rbuf = buf;
|
|
int i;
|
|
int i;
|
|
@@ -2035,7 +2114,7 @@ static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void
|
|
|
|
|
|
static int nv_nway_reset(struct net_device *dev)
|
|
static int nv_nway_reset(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
spin_lock_irq(&np->lock);
|
|
spin_lock_irq(&np->lock);
|
|
@@ -2065,11 +2144,12 @@ static struct ethtool_ops ops = {
|
|
.get_regs_len = nv_get_regs_len,
|
|
.get_regs_len = nv_get_regs_len,
|
|
.get_regs = nv_get_regs,
|
|
.get_regs = nv_get_regs,
|
|
.nway_reset = nv_nway_reset,
|
|
.nway_reset = nv_nway_reset,
|
|
|
|
+ .get_perm_addr = ethtool_op_get_perm_addr,
|
|
};
|
|
};
|
|
|
|
|
|
static int nv_open(struct net_device *dev)
|
|
static int nv_open(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
u8 __iomem *base = get_hwbase(dev);
|
|
int ret, oom, i;
|
|
int ret, oom, i;
|
|
|
|
|
|
@@ -2114,9 +2194,9 @@ static int nv_open(struct net_device *dev)
|
|
/* 5) continue setup */
|
|
/* 5) continue setup */
|
|
writel(np->linkspeed, base + NvRegLinkSpeed);
|
|
writel(np->linkspeed, base + NvRegLinkSpeed);
|
|
writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
|
|
writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3);
|
|
- writel(np->desc_ver, base + NvRegTxRxControl);
|
|
|
|
|
|
+ writel(np->txrxctl_bits, base + NvRegTxRxControl);
|
|
pci_push(base);
|
|
pci_push(base);
|
|
- writel(NVREG_TXRXCTL_BIT1|np->desc_ver, base + NvRegTxRxControl);
|
|
|
|
|
|
+ writel(NVREG_TXRXCTL_BIT1|np->txrxctl_bits, base + NvRegTxRxControl);
|
|
reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
|
|
reg_delay(dev, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31,
|
|
NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
|
|
NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX,
|
|
KERN_INFO "open: SetupReg5, Bit 31 remained off\n");
|
|
KERN_INFO "open: SetupReg5, Bit 31 remained off\n");
|
|
@@ -2205,7 +2285,7 @@ out_drain:
|
|
|
|
|
|
static int nv_close(struct net_device *dev)
|
|
static int nv_close(struct net_device *dev)
|
|
{
|
|
{
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
u8 __iomem *base;
|
|
u8 __iomem *base;
|
|
|
|
|
|
spin_lock_irq(&np->lock);
|
|
spin_lock_irq(&np->lock);
|
|
@@ -2261,7 +2341,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
|
|
if (!dev)
|
|
if (!dev)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
- np = get_nvpriv(dev);
|
|
|
|
|
|
+ np = netdev_priv(dev);
|
|
np->pci_dev = pci_dev;
|
|
np->pci_dev = pci_dev;
|
|
spin_lock_init(&np->lock);
|
|
spin_lock_init(&np->lock);
|
|
SET_MODULE_OWNER(dev);
|
|
SET_MODULE_OWNER(dev);
|
|
@@ -2313,19 +2393,32 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
|
|
if (pci_set_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
|
|
if (pci_set_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
|
|
printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
|
|
printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
|
|
pci_name(pci_dev));
|
|
pci_name(pci_dev));
|
|
|
|
+ } else {
|
|
|
|
+ dev->features |= NETIF_F_HIGHDMA;
|
|
}
|
|
}
|
|
|
|
+ np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
|
|
} else if (id->driver_data & DEV_HAS_LARGEDESC) {
|
|
} else if (id->driver_data & DEV_HAS_LARGEDESC) {
|
|
/* packet format 2: supports jumbo frames */
|
|
/* packet format 2: supports jumbo frames */
|
|
np->desc_ver = DESC_VER_2;
|
|
np->desc_ver = DESC_VER_2;
|
|
|
|
+ np->txrxctl_bits = NVREG_TXRXCTL_DESC_2;
|
|
} else {
|
|
} else {
|
|
/* original packet format */
|
|
/* original packet format */
|
|
np->desc_ver = DESC_VER_1;
|
|
np->desc_ver = DESC_VER_1;
|
|
|
|
+ np->txrxctl_bits = NVREG_TXRXCTL_DESC_1;
|
|
}
|
|
}
|
|
|
|
|
|
np->pkt_limit = NV_PKTLIMIT_1;
|
|
np->pkt_limit = NV_PKTLIMIT_1;
|
|
if (id->driver_data & DEV_HAS_LARGEDESC)
|
|
if (id->driver_data & DEV_HAS_LARGEDESC)
|
|
np->pkt_limit = NV_PKTLIMIT_2;
|
|
np->pkt_limit = NV_PKTLIMIT_2;
|
|
|
|
|
|
|
|
+ if (id->driver_data & DEV_HAS_CHECKSUM) {
|
|
|
|
+ np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
|
|
|
|
+ dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
|
|
|
|
+#ifdef NETIF_F_TSO
|
|
|
|
+ dev->features |= NETIF_F_TSO;
|
|
|
|
+#endif
|
|
|
|
+ }
|
|
|
|
+
|
|
err = -ENOMEM;
|
|
err = -ENOMEM;
|
|
np->base = ioremap(addr, NV_PCI_REGSZ);
|
|
np->base = ioremap(addr, NV_PCI_REGSZ);
|
|
if (!np->base)
|
|
if (!np->base)
|
|
@@ -2377,8 +2470,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
|
|
dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
|
|
dev->dev_addr[3] = (np->orig_mac[0] >> 16) & 0xff;
|
|
dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff;
|
|
dev->dev_addr[4] = (np->orig_mac[0] >> 8) & 0xff;
|
|
dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff;
|
|
dev->dev_addr[5] = (np->orig_mac[0] >> 0) & 0xff;
|
|
|
|
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
|
|
|
|
|
- if (!is_valid_ether_addr(dev->dev_addr)) {
|
|
|
|
|
|
+ if (!is_valid_ether_addr(dev->perm_addr)) {
|
|
/*
|
|
/*
|
|
* Bad mac address. At least one bios sets the mac address
|
|
* Bad mac address. At least one bios sets the mac address
|
|
* to 01:23:45:67:89:ab
|
|
* to 01:23:45:67:89:ab
|
|
@@ -2403,9 +2497,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
|
|
np->wolenabled = 0;
|
|
np->wolenabled = 0;
|
|
|
|
|
|
if (np->desc_ver == DESC_VER_1) {
|
|
if (np->desc_ver == DESC_VER_1) {
|
|
- np->tx_flags = NV_TX_LASTPACKET|NV_TX_VALID;
|
|
|
|
|
|
+ np->tx_flags = NV_TX_VALID;
|
|
} else {
|
|
} else {
|
|
- np->tx_flags = NV_TX2_LASTPACKET|NV_TX2_VALID;
|
|
|
|
|
|
+ np->tx_flags = NV_TX2_VALID;
|
|
}
|
|
}
|
|
np->irqmask = NVREG_IRQMASK_WANTED;
|
|
np->irqmask = NVREG_IRQMASK_WANTED;
|
|
if (id->driver_data & DEV_NEED_TIMERIRQ)
|
|
if (id->driver_data & DEV_NEED_TIMERIRQ)
|
|
@@ -2494,7 +2588,7 @@ out:
|
|
static void __devexit nv_remove(struct pci_dev *pci_dev)
|
|
static void __devexit nv_remove(struct pci_dev *pci_dev)
|
|
{
|
|
{
|
|
struct net_device *dev = pci_get_drvdata(pci_dev);
|
|
struct net_device *dev = pci_get_drvdata(pci_dev);
|
|
- struct fe_priv *np = get_nvpriv(dev);
|
|
|
|
|
|
+ struct fe_priv *np = netdev_priv(dev);
|
|
|
|
|
|
unregister_netdev(dev);
|
|
unregister_netdev(dev);
|
|
|
|
|
|
@@ -2525,35 +2619,35 @@ static struct pci_device_id pci_tbl[] = {
|
|
},
|
|
},
|
|
{ /* nForce3 Ethernet Controller */
|
|
{ /* nForce3 Ethernet Controller */
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_4),
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_4),
|
|
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
|
|
|
|
|
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
|
|
},
|
|
},
|
|
{ /* nForce3 Ethernet Controller */
|
|
{ /* nForce3 Ethernet Controller */
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_5),
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_5),
|
|
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
|
|
|
|
|
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
|
|
},
|
|
},
|
|
{ /* nForce3 Ethernet Controller */
|
|
{ /* nForce3 Ethernet Controller */
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_6),
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_6),
|
|
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
|
|
|
|
|
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
|
|
},
|
|
},
|
|
{ /* nForce3 Ethernet Controller */
|
|
{ /* nForce3 Ethernet Controller */
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_7),
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_7),
|
|
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
|
|
|
|
|
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM,
|
|
},
|
|
},
|
|
{ /* CK804 Ethernet Controller */
|
|
{ /* CK804 Ethernet Controller */
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8),
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8),
|
|
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
|
|
|
|
|
|
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
|
|
},
|
|
},
|
|
{ /* CK804 Ethernet Controller */
|
|
{ /* CK804 Ethernet Controller */
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9),
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9),
|
|
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
|
|
|
|
|
|
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
|
|
},
|
|
},
|
|
{ /* MCP04 Ethernet Controller */
|
|
{ /* MCP04 Ethernet Controller */
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10),
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10),
|
|
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
|
|
|
|
|
|
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
|
|
},
|
|
},
|
|
{ /* MCP04 Ethernet Controller */
|
|
{ /* MCP04 Ethernet Controller */
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11),
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11),
|
|
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
|
|
|
|
|
|
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
|
|
},
|
|
},
|
|
{ /* MCP51 Ethernet Controller */
|
|
{ /* MCP51 Ethernet Controller */
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
|
|
@@ -2565,11 +2659,11 @@ static struct pci_device_id pci_tbl[] = {
|
|
},
|
|
},
|
|
{ /* MCP55 Ethernet Controller */
|
|
{ /* MCP55 Ethernet Controller */
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
|
|
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
|
|
|
|
|
|
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
|
|
},
|
|
},
|
|
{ /* MCP55 Ethernet Controller */
|
|
{ /* MCP55 Ethernet Controller */
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
|
|
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
|
|
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA,
|
|
|
|
|
|
+ .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA,
|
|
},
|
|
},
|
|
{0,},
|
|
{0,},
|
|
};
|
|
};
|