Commit eb91f61b authored by Ayaz Abdulla's avatar Ayaz Abdulla Committed by Jeff Garzik

[PATCH] forcedeth: add support for flow control

This patch adds flow control support for tx and rx pause frames in
forcedeth.
Signed-Off-By: default avatarAyaz Abdulla <aabdulla@nvidia.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 48cf270e
...@@ -107,6 +107,7 @@ ...@@ -107,6 +107,7 @@
* 0.52: 20 Jan 2006: Add MSI/MSIX support. * 0.52: 20 Jan 2006: Add MSI/MSIX support.
* 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset. * 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset.
* 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup. * 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup.
* 0.55: 22 Mar 2006: Add flow control (pause frame).
* *
* 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.
...@@ -118,7 +119,7 @@ ...@@ -118,7 +119,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.54" #define FORCEDETH_VERSION "0.55"
#define DRV_NAME "forcedeth" #define DRV_NAME "forcedeth"
#include <linux/module.h> #include <linux/module.h>
...@@ -163,6 +164,7 @@ ...@@ -163,6 +164,7 @@
#define DEV_HAS_MSI 0x0040 /* device supports MSI */ #define DEV_HAS_MSI 0x0040 /* device supports MSI */
#define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ #define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */
#define DEV_HAS_POWER_CNTRL 0x0100 /* device supports power savings */ #define DEV_HAS_POWER_CNTRL 0x0100 /* device supports power savings */
#define DEV_HAS_PAUSEFRAME_TX 0x0200 /* device supports tx pause frames */
enum { enum {
NvRegIrqStatus = 0x000, NvRegIrqStatus = 0x000,
...@@ -203,6 +205,7 @@ enum { ...@@ -203,6 +205,7 @@ enum {
NvRegMSIIrqMask = 0x030, NvRegMSIIrqMask = 0x030,
#define NVREG_MSI_VECTOR_0_ENABLED 0x01 #define NVREG_MSI_VECTOR_0_ENABLED 0x01
NvRegMisc1 = 0x080, NvRegMisc1 = 0x080,
#define NVREG_MISC1_PAUSE_TX 0x01
#define NVREG_MISC1_HD 0x02 #define NVREG_MISC1_HD 0x02
#define NVREG_MISC1_FORCE 0x3b0f3c #define NVREG_MISC1_FORCE 0x3b0f3c
...@@ -214,7 +217,8 @@ enum { ...@@ -214,7 +217,8 @@ enum {
#define NVREG_XMITSTAT_BUSY 0x01 #define NVREG_XMITSTAT_BUSY 0x01
NvRegPacketFilterFlags = 0x8c, NvRegPacketFilterFlags = 0x8c,
#define NVREG_PFF_ALWAYS 0x7F0008 #define NVREG_PFF_PAUSE_RX 0x08
#define NVREG_PFF_ALWAYS 0x7F0000
#define NVREG_PFF_PROMISC 0x80 #define NVREG_PFF_PROMISC 0x80
#define NVREG_PFF_MYADDR 0x20 #define NVREG_PFF_MYADDR 0x20
...@@ -277,6 +281,9 @@ enum { ...@@ -277,6 +281,9 @@ enum {
#define NVREG_TXRXCTL_VLANINS 0x00080 #define NVREG_TXRXCTL_VLANINS 0x00080
NvRegTxRingPhysAddrHigh = 0x148, NvRegTxRingPhysAddrHigh = 0x148,
NvRegRxRingPhysAddrHigh = 0x14C, NvRegRxRingPhysAddrHigh = 0x14C,
NvRegTxPauseFrame = 0x170,
#define NVREG_TX_PAUSEFRAME_DISABLE 0x1ff0080
#define NVREG_TX_PAUSEFRAME_ENABLE 0x0c00030
NvRegMIIStatus = 0x180, NvRegMIIStatus = 0x180,
#define NVREG_MIISTAT_ERROR 0x0001 #define NVREG_MIISTAT_ERROR 0x0001
#define NVREG_MIISTAT_LINKCHANGE 0x0008 #define NVREG_MIISTAT_LINKCHANGE 0x0008
...@@ -506,13 +513,10 @@ typedef union _ring_type { ...@@ -506,13 +513,10 @@ typedef union _ring_type {
#define PHY_1000 0x2 #define PHY_1000 0x2
#define PHY_HALF 0x100 #define PHY_HALF 0x100
/* FIXME: MII defines that should be added to <linux/mii.h> */ #define NV_PAUSEFRAME_RX_CAPABLE 0x0001
#define MII_1000BT_CR 0x09 #define NV_PAUSEFRAME_TX_CAPABLE 0x0002
#define MII_1000BT_SR 0x0a #define NV_PAUSEFRAME_RX_ENABLE 0x0004
#define ADVERTISE_1000FULL 0x0200 #define NV_PAUSEFRAME_TX_ENABLE 0x0008
#define ADVERTISE_1000HALF 0x0100
#define LPA_1000FULL 0x0800
#define LPA_1000HALF 0x0400
/* MSI/MSI-X defines */ /* MSI/MSI-X defines */
#define NV_MSI_X_MAX_VECTORS 8 #define NV_MSI_X_MAX_VECTORS 8
...@@ -602,6 +606,9 @@ struct fe_priv { ...@@ -602,6 +606,9 @@ struct fe_priv {
/* msi/msi-x fields */ /* msi/msi-x fields */
u32 msi_flags; u32 msi_flags;
struct msix_entry msi_x_entry[NV_MSI_X_MAX_VECTORS]; struct msix_entry msi_x_entry[NV_MSI_X_MAX_VECTORS];
/* flow control */
u32 pause_flags;
}; };
/* /*
...@@ -860,7 +867,7 @@ static int phy_init(struct net_device *dev) ...@@ -860,7 +867,7 @@ static int phy_init(struct net_device *dev)
/* set advertise register */ /* set advertise register */
reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|0x800|0x400); reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|ADVERTISE_PAUSE_ASYM|ADVERTISE_PAUSE_CAP);
if (mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg)) { if (mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg)) {
printk(KERN_INFO "%s: phy write to advertise failed.\n", pci_name(np->pci_dev)); printk(KERN_INFO "%s: phy write to advertise failed.\n", pci_name(np->pci_dev));
return PHY_ERROR; return PHY_ERROR;
...@@ -873,14 +880,14 @@ static int phy_init(struct net_device *dev) ...@@ -873,14 +880,14 @@ static int phy_init(struct net_device *dev)
mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ); mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
if (mii_status & PHY_GIGABIT) { if (mii_status & PHY_GIGABIT) {
np->gigabit = PHY_GIGABIT; np->gigabit = PHY_GIGABIT;
mii_control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ); mii_control_1000 = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
mii_control_1000 &= ~ADVERTISE_1000HALF; mii_control_1000 &= ~ADVERTISE_1000HALF;
if (phyinterface & PHY_RGMII) if (phyinterface & PHY_RGMII)
mii_control_1000 |= ADVERTISE_1000FULL; mii_control_1000 |= ADVERTISE_1000FULL;
else else
mii_control_1000 &= ~ADVERTISE_1000FULL; mii_control_1000 &= ~ADVERTISE_1000FULL;
if (mii_rw(dev, np->phyaddr, MII_1000BT_CR, mii_control_1000)) { if (mii_rw(dev, np->phyaddr, MII_CTRL1000, mii_control_1000)) {
printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
return PHY_ERROR; return PHY_ERROR;
} }
...@@ -918,6 +925,8 @@ static int phy_init(struct net_device *dev) ...@@ -918,6 +925,8 @@ static int phy_init(struct net_device *dev)
return PHY_ERROR; return PHY_ERROR;
} }
} }
/* some phys clear out pause advertisment on reset, set it back */
mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg);
/* restart auto negotiation */ /* restart auto negotiation */
mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
...@@ -1550,7 +1559,6 @@ static void nv_rx_process(struct net_device *dev) ...@@ -1550,7 +1559,6 @@ static void nv_rx_process(struct net_device *dev)
u32 Flags; u32 Flags;
u32 vlanflags = 0; u32 vlanflags = 0;
for (;;) { for (;;) {
struct sk_buff *skb; struct sk_buff *skb;
int len; int len;
...@@ -1901,7 +1909,9 @@ static int nv_update_linkspeed(struct net_device *dev) ...@@ -1901,7 +1909,9 @@ static int nv_update_linkspeed(struct net_device *dev)
{ {
struct fe_priv *np = netdev_priv(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 = 0;
int lpa = 0;
int adv_lpa, adv_pause, lpa_pause;
int newls = np->linkspeed; int newls = np->linkspeed;
int newdup = np->duplex; int newdup = np->duplex;
int mii_status; int mii_status;
...@@ -1954,8 +1964,8 @@ static int nv_update_linkspeed(struct net_device *dev) ...@@ -1954,8 +1964,8 @@ static int nv_update_linkspeed(struct net_device *dev)
retval = 1; retval = 1;
if (np->gigabit == PHY_GIGABIT) { if (np->gigabit == PHY_GIGABIT) {
control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ); control_1000 = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
status_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_SR, MII_READ); status_1000 = mii_rw(dev, np->phyaddr, MII_STAT1000, MII_READ);
if ((control_1000 & ADVERTISE_1000FULL) && if ((control_1000 & ADVERTISE_1000FULL) &&
(status_1000 & LPA_1000FULL)) { (status_1000 & LPA_1000FULL)) {
...@@ -1973,21 +1983,21 @@ static int nv_update_linkspeed(struct net_device *dev) ...@@ -1973,21 +1983,21 @@ static int nv_update_linkspeed(struct net_device *dev)
dev->name, adv, lpa); dev->name, adv, lpa);
/* FIXME: handle parallel detection properly */ /* FIXME: handle parallel detection properly */
lpa = lpa & adv; adv_lpa = lpa & adv;
if (lpa & LPA_100FULL) { if (adv_lpa & LPA_100FULL) {
newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100; newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
newdup = 1; newdup = 1;
} else if (lpa & LPA_100HALF) { } else if (adv_lpa & LPA_100HALF) {
newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100; newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
newdup = 0; newdup = 0;
} else if (lpa & LPA_10FULL) { } else if (adv_lpa & LPA_10FULL) {
newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
newdup = 1; newdup = 1;
} else if (lpa & LPA_10HALF) { } else if (adv_lpa & LPA_10HALF) {
newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
newdup = 0; newdup = 0;
} else { } else {
dprintk(KERN_DEBUG "%s: bad ability %04x - falling back to 10HD.\n", dev->name, lpa); dprintk(KERN_DEBUG "%s: bad ability %04x - falling back to 10HD.\n", dev->name, adv_lpa);
newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
newdup = 0; newdup = 0;
} }
...@@ -2030,6 +2040,56 @@ static int nv_update_linkspeed(struct net_device *dev) ...@@ -2030,6 +2040,56 @@ static int nv_update_linkspeed(struct net_device *dev)
writel(np->linkspeed, base + NvRegLinkSpeed); writel(np->linkspeed, base + NvRegLinkSpeed);
pci_push(base); pci_push(base);
/* setup pause frame based on advertisement and link partner */
np->pause_flags &= ~(NV_PAUSEFRAME_TX_ENABLE | NV_PAUSEFRAME_RX_ENABLE);
if (np->duplex != 0) {
adv_pause = adv & (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM);
lpa_pause = lpa & (LPA_PAUSE_CAP| LPA_PAUSE_ASYM);
switch (adv_pause) {
case (ADVERTISE_PAUSE_CAP):
if (lpa_pause & LPA_PAUSE_CAP) {
np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE | NV_PAUSEFRAME_RX_ENABLE;
}
break;
case (ADVERTISE_PAUSE_ASYM):
if (lpa_pause == (LPA_PAUSE_CAP| LPA_PAUSE_ASYM))
{
np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
}
break;
case (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM):
if (lpa_pause & LPA_PAUSE_CAP)
{
np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE | NV_PAUSEFRAME_RX_ENABLE;
}
if (lpa_pause == LPA_PAUSE_ASYM)
{
np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
}
break;
}
}
if (np->pause_flags & NV_PAUSEFRAME_RX_CAPABLE) {
u32 pff = readl(base + NvRegPacketFilterFlags) & ~NVREG_PFF_PAUSE_RX;
if (np->pause_flags & NV_PAUSEFRAME_RX_ENABLE)
writel(pff|NVREG_PFF_PAUSE_RX, base + NvRegPacketFilterFlags);
else
writel(pff, base + NvRegPacketFilterFlags);
}
if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE) {
u32 regmisc = readl(base + NvRegMisc1) & ~NVREG_MISC1_PAUSE_TX;
if (np->pause_flags & NV_PAUSEFRAME_TX_ENABLE) {
writel(NVREG_TX_PAUSEFRAME_ENABLE, base + NvRegTxPauseFrame);
writel(regmisc|NVREG_MISC1_PAUSE_TX, base + NvRegMisc1);
} else {
writel(NVREG_TX_PAUSEFRAME_DISABLE, base + NvRegTxPauseFrame);
writel(regmisc, base + NvRegMisc1);
}
}
return retval; return retval;
} }
...@@ -2441,7 +2501,7 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ...@@ -2441,7 +2501,7 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
if (adv & ADVERTISE_100FULL) if (adv & ADVERTISE_100FULL)
ecmd->advertising |= ADVERTISED_100baseT_Full; ecmd->advertising |= ADVERTISED_100baseT_Full;
if (np->autoneg && np->gigabit == PHY_GIGABIT) { if (np->autoneg && np->gigabit == PHY_GIGABIT) {
adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ); adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
if (adv & ADVERTISE_1000FULL) if (adv & ADVERTISE_1000FULL)
ecmd->advertising |= ADVERTISED_1000baseT_Full; ecmd->advertising |= ADVERTISED_1000baseT_Full;
} }
...@@ -2505,23 +2565,23 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ...@@ -2505,23 +2565,23 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
/* advertise only what has been requested */ /* advertise only what has been requested */
adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
if (ecmd->advertising & ADVERTISED_10baseT_Half) if (ecmd->advertising & ADVERTISED_10baseT_Half)
adv |= ADVERTISE_10HALF; adv |= ADVERTISE_10HALF;
if (ecmd->advertising & ADVERTISED_10baseT_Full) if (ecmd->advertising & ADVERTISED_10baseT_Full)
adv |= ADVERTISE_10FULL; adv |= ADVERTISE_10FULL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
if (ecmd->advertising & ADVERTISED_100baseT_Half) if (ecmd->advertising & ADVERTISED_100baseT_Half)
adv |= ADVERTISE_100HALF; adv |= ADVERTISE_100HALF;
if (ecmd->advertising & ADVERTISED_100baseT_Full) if (ecmd->advertising & ADVERTISED_100baseT_Full)
adv |= ADVERTISE_100FULL; adv |= ADVERTISE_100FULL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv); mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv);
if (np->gigabit == PHY_GIGABIT) { if (np->gigabit == PHY_GIGABIT) {
adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ); adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
adv &= ~ADVERTISE_1000FULL; adv &= ~ADVERTISE_1000FULL;
if (ecmd->advertising & ADVERTISED_1000baseT_Full) if (ecmd->advertising & ADVERTISED_1000baseT_Full)
adv |= ADVERTISE_1000FULL; adv |= ADVERTISE_1000FULL;
mii_rw(dev, np->phyaddr, MII_1000BT_CR, adv); mii_rw(dev, np->phyaddr, MII_CTRL1000, adv);
} }
bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
...@@ -2534,22 +2594,22 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ...@@ -2534,22 +2594,22 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
np->autoneg = 0; np->autoneg = 0;
adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ); adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF) if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF)
adv |= ADVERTISE_10HALF; adv |= ADVERTISE_10HALF;
if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL) if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL)
adv |= ADVERTISE_10FULL; adv |= ADVERTISE_10FULL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_HALF) if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_HALF)
adv |= ADVERTISE_100HALF; adv |= ADVERTISE_100HALF;
if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL) if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL)
adv |= ADVERTISE_100FULL; adv |= ADVERTISE_100FULL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv); mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv);
np->fixed_mode = adv; np->fixed_mode = adv;
if (np->gigabit == PHY_GIGABIT) { if (np->gigabit == PHY_GIGABIT) {
adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ); adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
adv &= ~ADVERTISE_1000FULL; adv &= ~ADVERTISE_1000FULL;
mii_rw(dev, np->phyaddr, MII_1000BT_CR, adv); mii_rw(dev, np->phyaddr, MII_CTRL1000, adv);
} }
bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
...@@ -2813,6 +2873,9 @@ static int nv_open(struct net_device *dev) ...@@ -2813,6 +2873,9 @@ static int nv_open(struct net_device *dev)
writel(0, base + NvRegAdapterControl); writel(0, base + NvRegAdapterControl);
if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE)
writel(NVREG_TX_PAUSEFRAME_DISABLE, base + NvRegTxPauseFrame);
/* 2) initialize descriptor rings */ /* 2) initialize descriptor rings */
set_bufsize(dev); set_bufsize(dev);
oom = nv_init_ring(dev); oom = nv_init_ring(dev);
...@@ -3098,6 +3161,12 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i ...@@ -3098,6 +3161,12 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
np->msi_flags |= NV_MSI_X_CAPABLE; np->msi_flags |= NV_MSI_X_CAPABLE;
} }
np->pause_flags = NV_PAUSEFRAME_RX_CAPABLE;
if (id->driver_data & DEV_HAS_PAUSEFRAME_TX) {
np->pause_flags |= NV_PAUSEFRAME_TX_CAPABLE;
}
err = -ENOMEM; err = -ENOMEM;
np->base = ioremap(addr, np->register_size); np->base = ioremap(addr, np->register_size);
if (!np->base) if (!np->base)
...@@ -3358,11 +3427,11 @@ static struct pci_device_id pci_tbl[] = { ...@@ -3358,11 +3427,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_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL, .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX,
}, },
{ /* 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_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL, .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX,
}, },
{0,}, {0,},
}; };
......
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