[PATCH] forcedeth: rewritten tx irq handling
This is a multi-part message in MIME format. Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
This commit is contained in:
parent
dc8216c192
commit
c2dba06dae
@ -87,6 +87,8 @@
|
||||
* 0.35: 26 Jun 2005: Support for MCP55 added.
|
||||
* 0.36: 28 Jun 2005: Add jumbo frame support.
|
||||
* 0.37: 10 Jul 2005: Additional ethtool support, cleanup of pci id list
|
||||
* 0.38: 16 Jul 2005: tx irq rewrite: Use global flags instead of
|
||||
* per-packet flags.
|
||||
*
|
||||
* Known bugs:
|
||||
* We suspect that on some hardware no TX done interrupts are generated.
|
||||
@ -98,7 +100,7 @@
|
||||
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
|
||||
* superfluous timer interrupts from the nic.
|
||||
*/
|
||||
#define FORCEDETH_VERSION "0.37"
|
||||
#define FORCEDETH_VERSION "0.38"
|
||||
#define DRV_NAME "forcedeth"
|
||||
|
||||
#include <linux/module.h>
|
||||
@ -133,12 +135,9 @@
|
||||
* Hardware access:
|
||||
*/
|
||||
|
||||
#define DEV_NEED_LASTPACKET1 0x0001 /* set LASTPACKET1 in tx flags */
|
||||
#define DEV_IRQMASK_1 0x0002 /* use NVREG_IRQMASK_WANTED_1 for irq mask */
|
||||
#define DEV_IRQMASK_2 0x0004 /* use NVREG_IRQMASK_WANTED_2 for irq mask */
|
||||
#define DEV_NEED_TIMERIRQ 0x0008 /* set the timer irq flag in the irq mask */
|
||||
#define DEV_NEED_LINKTIMER 0x0010 /* poll link settings. Relies on the timer irq */
|
||||
#define DEV_HAS_LARGEDESC 0x0020 /* device supports jumbo frames and needs packet format 2 */
|
||||
#define DEV_NEED_TIMERIRQ 0x0001 /* set the timer irq flag in the irq mask */
|
||||
#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 */
|
||||
|
||||
enum {
|
||||
NvRegIrqStatus = 0x000,
|
||||
@ -149,13 +148,16 @@ enum {
|
||||
#define NVREG_IRQ_RX 0x0002
|
||||
#define NVREG_IRQ_RX_NOBUF 0x0004
|
||||
#define NVREG_IRQ_TX_ERR 0x0008
|
||||
#define NVREG_IRQ_TX2 0x0010
|
||||
#define NVREG_IRQ_TX_OK 0x0010
|
||||
#define NVREG_IRQ_TIMER 0x0020
|
||||
#define NVREG_IRQ_LINK 0x0040
|
||||
#define NVREG_IRQ_TX_ERROR 0x0080
|
||||
#define NVREG_IRQ_TX1 0x0100
|
||||
#define NVREG_IRQMASK_WANTED_1 0x005f
|
||||
#define NVREG_IRQMASK_WANTED_2 0x0147
|
||||
#define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR|NVREG_IRQ_TX2|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX1))
|
||||
#define NVREG_IRQMASK_WANTED 0x00df
|
||||
|
||||
#define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \
|
||||
NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX_ERROR| \
|
||||
NVREG_IRQ_TX1))
|
||||
|
||||
NvRegUnknownSetupReg6 = 0x008,
|
||||
#define NVREG_UNKSETUP6_VAL 3
|
||||
@ -296,7 +298,7 @@ struct ring_desc {
|
||||
|
||||
#define NV_TX_LASTPACKET (1<<16)
|
||||
#define NV_TX_RETRYERROR (1<<19)
|
||||
#define NV_TX_LASTPACKET1 (1<<24)
|
||||
#define NV_TX_FORCED_INTERRUPT (1<<24)
|
||||
#define NV_TX_DEFERRED (1<<26)
|
||||
#define NV_TX_CARRIERLOST (1<<27)
|
||||
#define NV_TX_LATECOLLISION (1<<28)
|
||||
@ -306,7 +308,7 @@ struct ring_desc {
|
||||
|
||||
#define NV_TX2_LASTPACKET (1<<29)
|
||||
#define NV_TX2_RETRYERROR (1<<18)
|
||||
#define NV_TX2_LASTPACKET1 (1<<23)
|
||||
#define NV_TX2_FORCED_INTERRUPT (1<<30)
|
||||
#define NV_TX2_DEFERRED (1<<25)
|
||||
#define NV_TX2_CARRIERLOST (1<<26)
|
||||
#define NV_TX2_LATECOLLISION (1<<27)
|
||||
@ -1013,9 +1015,39 @@ static void nv_tx_timeout(struct net_device *dev)
|
||||
struct fe_priv *np = get_nvpriv(dev);
|
||||
u8 __iomem *base = get_hwbase(dev);
|
||||
|
||||
dprintk(KERN_DEBUG "%s: Got tx_timeout. irq: %08x\n", dev->name,
|
||||
printk(KERN_INFO "%s: Got tx_timeout. irq: %08x\n", dev->name,
|
||||
readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK);
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
printk(KERN_INFO "%s: Ring at %lx: next %d nic %d\n",
|
||||
dev->name, (unsigned long)np->ring_addr,
|
||||
np->next_tx, np->nic_tx);
|
||||
printk(KERN_INFO "%s: Dumping tx registers\n", dev->name);
|
||||
for (i=0;i<0x400;i+= 32) {
|
||||
printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
i,
|
||||
readl(base + i + 0), readl(base + i + 4),
|
||||
readl(base + i + 8), readl(base + i + 12),
|
||||
readl(base + i + 16), readl(base + i + 20),
|
||||
readl(base + i + 24), readl(base + i + 28));
|
||||
}
|
||||
printk(KERN_INFO "%s: Dumping tx ring\n", dev->name);
|
||||
for (i=0;i<TX_RING;i+= 4) {
|
||||
printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
|
||||
i,
|
||||
le32_to_cpu(np->tx_ring[i].PacketBuffer),
|
||||
le32_to_cpu(np->tx_ring[i].FlagLen),
|
||||
le32_to_cpu(np->tx_ring[i+1].PacketBuffer),
|
||||
le32_to_cpu(np->tx_ring[i+1].FlagLen),
|
||||
le32_to_cpu(np->tx_ring[i+2].PacketBuffer),
|
||||
le32_to_cpu(np->tx_ring[i+2].FlagLen),
|
||||
le32_to_cpu(np->tx_ring[i+3].PacketBuffer),
|
||||
le32_to_cpu(np->tx_ring[i+3].FlagLen));
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irq(&np->lock);
|
||||
|
||||
/* 1) stop tx engine */
|
||||
@ -1557,7 +1589,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs)
|
||||
if (!(events & np->irqmask))
|
||||
break;
|
||||
|
||||
if (events & (NVREG_IRQ_TX1|NVREG_IRQ_TX2|NVREG_IRQ_TX_ERR)) {
|
||||
if (events & (NVREG_IRQ_TX1|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_ERROR|NVREG_IRQ_TX_ERR)) {
|
||||
spin_lock(&np->lock);
|
||||
nv_tx_done(dev);
|
||||
spin_unlock(&np->lock);
|
||||
@ -2213,17 +2245,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
|
||||
|
||||
if (np->desc_ver == DESC_VER_1) {
|
||||
np->tx_flags = NV_TX_LASTPACKET|NV_TX_VALID;
|
||||
if (id->driver_data & DEV_NEED_LASTPACKET1)
|
||||
np->tx_flags |= NV_TX_LASTPACKET1;
|
||||
} else {
|
||||
np->tx_flags = NV_TX2_LASTPACKET|NV_TX2_VALID;
|
||||
if (id->driver_data & DEV_NEED_LASTPACKET1)
|
||||
np->tx_flags |= NV_TX2_LASTPACKET1;
|
||||
}
|
||||
if (id->driver_data & DEV_IRQMASK_1)
|
||||
np->irqmask = NVREG_IRQMASK_WANTED_1;
|
||||
if (id->driver_data & DEV_IRQMASK_2)
|
||||
np->irqmask = NVREG_IRQMASK_WANTED_2;
|
||||
np->irqmask = NVREG_IRQMASK_WANTED;
|
||||
if (id->driver_data & DEV_NEED_TIMERIRQ)
|
||||
np->irqmask |= NVREG_IRQ_TIMER;
|
||||
if (id->driver_data & DEV_NEED_LINKTIMER) {
|
||||
@ -2329,73 +2354,63 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
|
||||
static struct pci_device_id pci_tbl[] = {
|
||||
{ /* nForce Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_1),
|
||||
.driver_data = DEV_IRQMASK_1|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
|
||||
},
|
||||
{ /* nForce2 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_2),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
|
||||
},
|
||||
{ /* nForce3 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_3),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
|
||||
},
|
||||
{ /* nForce3 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_4),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|
|
||||
DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
},
|
||||
{ /* nForce3 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_5),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|
|
||||
DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
},
|
||||
{ /* nForce3 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_6),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|
|
||||
DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
},
|
||||
{ /* nForce3 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_7),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|
|
||||
DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
},
|
||||
{ /* CK804 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_8),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|
|
||||
DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
},
|
||||
{ /* CK804 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_9),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|
|
||||
DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
},
|
||||
{ /* MCP04 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_10),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|
|
||||
DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
},
|
||||
{ /* MCP04 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_11),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|
|
||||
DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
},
|
||||
{ /* MCP51 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
|
||||
},
|
||||
{ /* MCP51 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER,
|
||||
},
|
||||
{ /* MCP55 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|
|
||||
DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
},
|
||||
{ /* MCP55 Ethernet Controller */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
|
||||
.driver_data = DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ|
|
||||
DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC,
|
||||
},
|
||||
{0,},
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user