* [PATCH 3/6] b44: add parameter
From: Gary Zambrano @ 2006-06-16 19:19 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
This patch adds a parameter to init_hw() to not completely initialize
the nic for wol.
Signed-off-by: Gary Zambrano <zambrano@broadcom.com>
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 73ca729..12fc67a 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -101,7 +101,7 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl);
static void b44_halt(struct b44 *);
static void b44_init_rings(struct b44 *);
-static void b44_init_hw(struct b44 *);
+static void b44_init_hw(struct b44 *, int);
static int dma_desc_align_mask;
static int dma_desc_sync_size;
@@ -873,7 +873,7 @@ static int b44_poll(struct net_device *n
spin_lock_irq(&bp->lock);
b44_halt(bp);
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
netif_wake_queue(bp->dev);
spin_unlock_irq(&bp->lock);
done = 1;
@@ -942,7 +942,7 @@ static void b44_tx_timeout(struct net_de
b44_halt(bp);
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
spin_unlock_irq(&bp->lock);
@@ -1059,7 +1059,7 @@ static int b44_change_mtu(struct net_dev
b44_halt(bp);
dev->mtu = new_mtu;
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
spin_unlock_irq(&bp->lock);
b44_enable_ints(bp);
@@ -1356,13 +1356,15 @@ static int b44_set_mac_addr(struct net_d
* packet processing. Invoked with bp->lock held.
*/
static void __b44_set_rx_mode(struct net_device *);
-static void b44_init_hw(struct b44 *bp)
+static void b44_init_hw(struct b44 *bp, int full_reset)
{
u32 val;
b44_chip_reset(bp);
- b44_phy_reset(bp);
- b44_setup_phy(bp);
+ if (full_reset) {
+ b44_phy_reset(bp);
+ b44_setup_phy(bp);
+ }
/* Enable CRC32, set proper LED modes and power on PHY */
bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
@@ -1376,16 +1378,21 @@ static void b44_init_hw(struct b44 *bp)
bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
- bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
- bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
- bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
- (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
- bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
+ if (full_reset) {
+ bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
+ bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
+ bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
+ (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+ bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
- bw32(bp, B44_DMARX_PTR, bp->rx_pending);
- bp->rx_prod = bp->rx_pending;
+ bw32(bp, B44_DMARX_PTR, bp->rx_pending);
+ bp->rx_prod = bp->rx_pending;
- bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
+ bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
+ } else {
+ bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
+ (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+ }
val = br32(bp, B44_ENET_CTRL);
bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
@@ -1401,7 +1408,7 @@ static int b44_open(struct net_device *d
goto out;
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
b44_check_phy(bp);
@@ -1511,7 +1518,7 @@ static int b44_close(struct net_device *
netif_poll_enable(dev);
if (bp->flags & B44_FLAG_WOL_ENABLE) {
- b44_init_hw(bp);
+ b44_init_hw(bp, 0);
b44_setup_wol(bp);
}
@@ -1786,7 +1793,7 @@ static int b44_set_ringparam(struct net_
b44_halt(bp);
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
netif_wake_queue(bp->dev);
spin_unlock_irq(&bp->lock);
@@ -1829,7 +1836,7 @@ static int b44_set_pauseparam(struct net
if (bp->flags & B44_FLAG_PAUSE_AUTO) {
b44_halt(bp);
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
} else {
__b44_set_flow_ctrl(bp, bp->flags);
}
@@ -2188,7 +2195,7 @@ static int b44_suspend(struct pci_dev *p
free_irq(dev->irq, dev);
if (bp->flags & B44_FLAG_WOL_ENABLE) {
- b44_init_hw(bp);
+ b44_init_hw(bp, 0);
b44_setup_wol(bp);
}
pci_disable_device(pdev);
@@ -2213,7 +2220,7 @@ static int b44_resume(struct pci_dev *pd
spin_lock_irq(&bp->lock);
b44_init_rings(bp);
- b44_init_hw(bp);
+ b44_init_hw(bp, 1);
netif_device_attach(bp->dev);
spin_unlock_irq(&bp->lock);
^ permalink raw reply related
* [PATCH 2/6] b44: add wol
From: Gary Zambrano @ 2006-06-16 19:19 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
Adds wol to the driver.
This is a redo of a previous patch thanks to feedback from Francois Romieu.
Signed-off-by Gary Zambrano <zambrano@broadcom.com>
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 41b1618..81f434e 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -1450,6 +1450,41 @@ static void b44_poll_controller(struct n
}
#endif
+
+static void b44_setup_wol(struct b44 *bp)
+{
+ u32 val;
+ u16 pmval;
+
+ bw32(bp, B44_RXCONFIG, RXCONFIG_ALLMULTI);
+
+ if (bp->flags & B44_FLAG_B0_ANDLATER) {
+
+ bw32(bp, B44_WKUP_LEN, WKUP_LEN_DISABLE);
+
+ val = bp->dev->dev_addr[2] << 24 |
+ bp->dev->dev_addr[3] << 16 |
+ bp->dev->dev_addr[4] << 8 |
+ bp->dev->dev_addr[5];
+ bw32(bp, B44_ADDR_LO, val);
+
+ val = bp->dev->dev_addr[0] << 8 |
+ bp->dev->dev_addr[1];
+ bw32(bp, B44_ADDR_HI, val);
+
+ val = br32(bp, B44_DEVCTRL);
+ bw32(bp, B44_DEVCTRL, val | DEVCTRL_MPM | DEVCTRL_PFE);
+
+ }
+
+ val = br32(bp, B44_SBTMSLOW);
+ bw32(bp, B44_SBTMSLOW, val | SBTMSLOW_PE);
+
+ pci_read_config_word(bp->pdev, SSB_PMCSR, &pmval);
+ pci_write_config_word(bp->pdev, SSB_PMCSR, pmval | SSB_PE);
+
+}
+
static int b44_close(struct net_device *dev)
{
struct b44 *bp = netdev_priv(dev);
@@ -1475,6 +1510,11 @@ static int b44_close(struct net_device *
netif_poll_enable(dev);
+ if (bp->flags & B44_FLAG_WOL_ENABLE) {
+ b44_init_hw(bp);
+ b44_setup_wol(bp);
+ }
+
b44_free_consistent(bp);
return 0;
@@ -1831,12 +1871,40 @@ static void b44_get_ethtool_stats(struct
spin_unlock_irq(&bp->lock);
}
+static void b44_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct b44 *bp = netdev_priv(dev);
+
+ wol->supported = WAKE_MAGIC;
+ if (bp->flags & B44_FLAG_WOL_ENABLE)
+ wol->wolopts = WAKE_MAGIC;
+ else
+ wol->wolopts = 0;
+ memset(&wol->sopass, 0, sizeof(wol->sopass));
+}
+
+static int b44_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct b44 *bp = netdev_priv(dev);
+
+ spin_lock_irq(&bp->lock);
+ if (wol->wolopts & WAKE_MAGIC)
+ bp->flags |= B44_FLAG_WOL_ENABLE;
+ else
+ bp->flags &= ~B44_FLAG_WOL_ENABLE;
+ spin_unlock_irq(&bp->lock);
+
+ return 0;
+}
+
static struct ethtool_ops b44_ethtool_ops = {
.get_drvinfo = b44_get_drvinfo,
.get_settings = b44_get_settings,
.set_settings = b44_set_settings,
.nway_reset = b44_nway_reset,
.get_link = ethtool_op_get_link,
+ .get_wol = b44_get_wol,
+ .set_wol = b44_set_wol,
.get_ringparam = b44_get_ringparam,
.set_ringparam = b44_set_ringparam,
.get_pauseparam = b44_get_pauseparam,
@@ -1915,6 +1983,10 @@ static int __devinit b44_get_invariants(
/* XXX - really required?
bp->flags |= B44_FLAG_BUGGY_TXPTR;
*/
+
+ if (ssb_get_core_rev(bp) >= 7)
+ bp->flags |= B44_FLAG_B0_ANDLATER;
+
out:
return err;
}
@@ -2115,6 +2187,10 @@ static int b44_suspend(struct pci_dev *p
spin_unlock_irq(&bp->lock);
free_irq(dev->irq, dev);
+ if (bp->flags & B44_FLAG_WOL_ENABLE) {
+ b44_init_hw(bp);
+ b44_setup_wol(bp);
+ }
pci_disable_device(pdev);
return 0;
}
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index b178662..1f47777 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -264,6 +264,8 @@
#define SBIDHIGH_VC_SHIFT 16
/* SSB PCI config space registers. */
+#define SSB_PMCSR 0x44
+#define SSB_PE 0x100
#define SSB_BAR0_WIN 0x80
#define SSB_BAR1_WIN 0x84
#define SSB_SPROM_CONTROL 0x88
@@ -420,6 +422,7 @@ struct b44 {
u32 dma_offset;
u32 flags;
+#define B44_FLAG_B0_ANDLATER 0x00000001
#define B44_FLAG_BUGGY_TXPTR 0x00000002
#define B44_FLAG_REORDER_BUG 0x00000004
#define B44_FLAG_PAUSE_AUTO 0x00008000
@@ -435,6 +438,7 @@ struct b44 {
#define B44_FLAG_INTERNAL_PHY 0x10000000
#define B44_FLAG_RX_RING_HACK 0x20000000
#define B44_FLAG_TX_RING_HACK 0x40000000
+#define B44_FLAG_WOL_ENABLE 0x80000000
u32 rx_offset;
^ permalink raw reply related
* [PATCH 1/6] b44: fix manual speed/duplex/autoneg settings
From: Gary Zambrano @ 2006-06-16 19:19 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
Fixes for speed/duplex/autoneg settings and driver settings info.
This is a redo of a previous patch thanks to feedback from Jeff Garzik.
Signed-off-by: Gary Zambrano <zambrano@broadcom.com>
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index d8233e0..41b1618 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -1620,8 +1620,6 @@ static int b44_get_settings(struct net_d
{
struct b44 *bp = netdev_priv(dev);
- if (!netif_running(dev))
- return -EAGAIN;
cmd->supported = (SUPPORTED_Autoneg);
cmd->supported |= (SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
@@ -1649,6 +1647,12 @@ static int b44_get_settings(struct net_d
XCVR_INTERNAL : XCVR_EXTERNAL;
cmd->autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ?
AUTONEG_DISABLE : AUTONEG_ENABLE;
+ if (cmd->autoneg == AUTONEG_ENABLE)
+ cmd->advertising |= ADVERTISED_Autoneg;
+ if (!netif_running(dev)){
+ cmd->speed = 0;
+ cmd->duplex = 0xff;
+ }
cmd->maxtxpkt = 0;
cmd->maxrxpkt = 0;
return 0;
@@ -1658,9 +1662,6 @@ static int b44_set_settings(struct net_d
{
struct b44 *bp = netdev_priv(dev);
- if (!netif_running(dev))
- return -EAGAIN;
-
/* We do not support gigabit. */
if (cmd->autoneg == AUTONEG_ENABLE) {
if (cmd->advertising &
@@ -1677,28 +1678,39 @@ static int b44_set_settings(struct net_d
spin_lock_irq(&bp->lock);
if (cmd->autoneg == AUTONEG_ENABLE) {
- bp->flags &= ~B44_FLAG_FORCE_LINK;
- bp->flags &= ~(B44_FLAG_ADV_10HALF |
+ bp->flags &= ~(B44_FLAG_FORCE_LINK |
+ B44_FLAG_100_BASE_T |
+ B44_FLAG_FULL_DUPLEX |
+ B44_FLAG_ADV_10HALF |
B44_FLAG_ADV_10FULL |
B44_FLAG_ADV_100HALF |
B44_FLAG_ADV_100FULL);
- if (cmd->advertising & ADVERTISE_10HALF)
- bp->flags |= B44_FLAG_ADV_10HALF;
- if (cmd->advertising & ADVERTISE_10FULL)
- bp->flags |= B44_FLAG_ADV_10FULL;
- if (cmd->advertising & ADVERTISE_100HALF)
- bp->flags |= B44_FLAG_ADV_100HALF;
- if (cmd->advertising & ADVERTISE_100FULL)
- bp->flags |= B44_FLAG_ADV_100FULL;
+ if (cmd->advertising == 0) {
+ bp->flags |= (B44_FLAG_ADV_10HALF |
+ B44_FLAG_ADV_10FULL |
+ B44_FLAG_ADV_100HALF |
+ B44_FLAG_ADV_100FULL);
+ } else {
+ if (cmd->advertising & ADVERTISED_10baseT_Half)
+ bp->flags |= B44_FLAG_ADV_10HALF;
+ if (cmd->advertising & ADVERTISED_10baseT_Full)
+ bp->flags |= B44_FLAG_ADV_10FULL;
+ if (cmd->advertising & ADVERTISED_100baseT_Half)
+ bp->flags |= B44_FLAG_ADV_100HALF;
+ if (cmd->advertising & ADVERTISED_100baseT_Full)
+ bp->flags |= B44_FLAG_ADV_100FULL;
+ }
} else {
bp->flags |= B44_FLAG_FORCE_LINK;
+ bp->flags &= ~(B44_FLAG_100_BASE_T | B44_FLAG_FULL_DUPLEX);
if (cmd->speed == SPEED_100)
bp->flags |= B44_FLAG_100_BASE_T;
if (cmd->duplex == DUPLEX_FULL)
bp->flags |= B44_FLAG_FULL_DUPLEX;
}
- b44_setup_phy(bp);
+ if (netif_running(dev))
+ b44_setup_phy(bp);
spin_unlock_irq(&bp->lock);
^ permalink raw reply related
* [PATCH 0/6] b44: fixes for speed settings, addition of wol.
From: Gary Zambrano @ 2006-06-16 19:18 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
This series of patches is to update the b44 driver with the following changes:
1-fix the manual speed settings
2-add wol functionality
3-add a parameter to init_hw function to support wol
4-add wol for older nic
5-bump driver version to 1.01
6-modify the Kconfig b44 entry
^ permalink raw reply
* [PATCH] sky2: netconsole suspend/resume interaction
From: Stephen Hemminger @ 2006-06-16 19:12 UTC (permalink / raw)
To: netdev
A couple of fixes that should prevent crashes when using netconsole and
suspend/resume. First, netconsole poll routine shouldn't run unless the
device is up; second, the NAPI poll should be disabled during suspend.
This is only an issue on sky2, because it has to have one NAPI poll
routine for both ports on dual port boards. Normal drivers use
netif_rx_schedule_prep and that checks for netif_running.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
--- sky2.orig/drivers/net/sky2.c 2006-06-15 14:36:05.000000000 -0700
+++ sky2/drivers/net/sky2.c 2006-06-15 15:04:55.000000000 -0700
@@ -2255,8 +2255,10 @@
static void sky2_netpoll(struct net_device *dev)
{
struct sky2_port *sky2 = netdev_priv(dev);
+ struct net_device *dev0 = sky2->hw->dev[0];
- sky2_intr(sky2->hw->pdev->irq, sky2->hw, NULL);
+ if (netif_running(dev) && __netif_rx_schedule_prep(dev0))
+ __netif_rx_schedule(dev0);
}
#endif
@@ -3446,6 +3448,7 @@
sky2_down(dev);
netif_device_detach(dev);
+ netif_poll_disable(dev);
}
}
@@ -3474,6 +3477,8 @@
struct net_device *dev = hw->dev[i];
if (dev && netif_running(dev)) {
netif_device_attach(dev);
+ netif_poll_enable(dev);
+
err = sky2_up(dev);
if (err) {
printk(KERN_ERR PFX "%s: could not up: %d\n",
^ permalink raw reply
* [RFT] pcnet32 NAPI changes
From: Don Fry @ 2006-06-16 19:11 UTC (permalink / raw)
To: lsorense, netdev
This patch is a collection of changes to pcnet32 which does the
following:
- Fix section mismatch warning.
- fix set_ringparam to correctly handle memory allocation failures
- fix off-by-one in get_ringparam.
- cleanup at end of loopback_test when not up.
- Add NAPI to driver, fixing set_ringparam and loopback_test to work
correctly with poll.
- for multicast, do not reset the chip unless cannot enter suspend mode
to avoid race with poll.
The set_ringparam code is larger than I would prefer, but it will not
leave null pointers around for the code to stumble over when memory
allocation fails. If anyone has a better idea, please let me know.
Some complexity could be avoided by allocating memory for the maximum
number of tx and rx buffers at probe time. Requiring 14k for the tx
ring and arrays, and another 14k for rx; instead of about 10k total for
the default sizes.
It is NAPI only, unlike Len Sorensen's version which allows for compile
time selection. Some drivers are NAPI only, others have compile
options. Which is preferred?
I have tested these changes with a 79C971, 973, 976, and 978 on a ppc64
machine, and 970A, 972, 973, 975, and 976 on an x86 machine.
I have not tested these changes with VMware or Xen.
--- linux-2.6.17-rc6/drivers/net/orig.pcnet32.c 2006-06-15 11:49:39.000000000 -0700
+++ linux-2.6.17-rc6/drivers/net/pcnet32.c 2006-06-16 11:30:45.000000000 -0700
@@ -22,8 +22,8 @@
*************************************************************************/
#define DRV_NAME "pcnet32"
-#define DRV_VERSION "1.32"
-#define DRV_RELDATE "18.Mar.2006"
+#define DRV_VERSION "1.33-NAPI"
+#define DRV_RELDATE "16.Jun.2006"
#define PFX DRV_NAME ": "
static const char *const version =
@@ -277,13 +277,12 @@ struct pcnet32_private {
u32 phymask;
};
-static void pcnet32_probe_vlbus(void);
static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *);
static int pcnet32_probe1(unsigned long, int, struct pci_dev *);
static int pcnet32_open(struct net_device *);
static int pcnet32_init_ring(struct net_device *);
static int pcnet32_start_xmit(struct sk_buff *, struct net_device *);
-static int pcnet32_rx(struct net_device *);
+static int pcnet32_poll(struct net_device *dev, int *budget);
static void pcnet32_tx_timeout(struct net_device *dev);
static irqreturn_t pcnet32_interrupt(int, void *, struct pt_regs *);
static int pcnet32_close(struct net_device *);
@@ -425,6 +424,215 @@ static struct pcnet32_access pcnet32_dwi
.reset = pcnet32_dwio_reset
};
+static void pcnet32_netif_stop(struct net_device *dev)
+{
+ dev->trans_start = jiffies;
+ netif_poll_disable(dev);
+ netif_tx_disable(dev);
+}
+
+static void pcnet32_netif_start(struct net_device *dev)
+{
+ netif_wake_queue(dev);
+ netif_poll_enable(dev);
+}
+
+/*
+ * Allocate space for the new sized tx ring.
+ * Free old resources
+ * Save new resources.
+ * Any failure keeps old resources.
+ * Must be called with lp->lock held.
+ */
+static void pcnet32_realloc_tx_ring(struct net_device *dev,
+ struct pcnet32_private *lp,
+ unsigned int size)
+{
+ dma_addr_t new_ring_dma_addr;
+ dma_addr_t *new_dma_addr_list;
+ struct pcnet32_tx_head *new_tx_ring;
+ struct sk_buff **new_skb_list;
+
+ pcnet32_purge_tx_ring(dev);
+
+ new_tx_ring = pci_alloc_consistent(lp->pci_dev,
+ sizeof(struct pcnet32_tx_head) *
+ (1 << size),
+ &new_ring_dma_addr);
+ if (new_tx_ring == NULL) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk("\n" KERN_ERR PFX
+ "%s: Consistent memory allocation failed.\n",
+ dev->name);
+ return;
+ }
+ memset(new_tx_ring, 0, sizeof(struct pcnet32_tx_head) * (1 << size));
+
+ new_dma_addr_list = kcalloc(sizeof(dma_addr_t), (1 << size), GFP_ATOMIC);
+ if (!new_dma_addr_list) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk("\n" KERN_ERR PFX
+ "%s: Memory allocation failed.\n", dev->name);
+ goto free_new_tx_ring;
+ }
+
+ new_skb_list = kcalloc(sizeof(struct sk_buff *), (1 << size), GFP_ATOMIC);
+ if (!new_skb_list) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk("\n" KERN_ERR PFX
+ "%s: Memory allocation failed.\n", dev->name);
+ goto free_new_lists;
+ }
+
+ kfree(lp->tx_skbuff);
+ kfree(lp->tx_dma_addr);
+ pci_free_consistent(lp->pci_dev,
+ sizeof(struct pcnet32_tx_head) *
+ lp->tx_ring_size, lp->tx_ring,
+ lp->tx_ring_dma_addr);
+
+ lp->tx_ring_size = (1 << size);
+ lp->tx_mod_mask = lp->tx_ring_size - 1;
+ lp->tx_len_bits = (size << 12);
+ lp->tx_ring = new_tx_ring;
+ lp->tx_ring_dma_addr = new_ring_dma_addr;
+ lp->tx_dma_addr = new_dma_addr_list;
+ lp->tx_skbuff = new_skb_list;
+ return;
+
+ free_new_lists:
+ kfree(new_dma_addr_list);
+ free_new_tx_ring:
+ pci_free_consistent(lp->pci_dev,
+ sizeof(struct pcnet32_tx_head) *
+ (1 << size),
+ new_tx_ring,
+ new_ring_dma_addr);
+ return;
+}
+
+/*
+ * Allocate space for the new sized rx ring.
+ * Re-use old receive buffers.
+ * alloc extra buffers
+ * free unneeded buffers
+ * free unneeded buffers
+ * Save new resources.
+ * Any failure keeps old resources.
+ * Must be called with lp->lock held.
+ */
+static void pcnet32_realloc_rx_ring(struct net_device *dev,
+ struct pcnet32_private *lp,
+ unsigned int size)
+{
+ dma_addr_t new_ring_dma_addr;
+ dma_addr_t *new_dma_addr_list;
+ struct pcnet32_rx_head *new_rx_ring;
+ struct sk_buff **new_skb_list;
+ int new, overlap;
+
+ new_rx_ring = pci_alloc_consistent(lp->pci_dev,
+ sizeof(struct pcnet32_rx_head) *
+ (1 << size),
+ &new_ring_dma_addr);
+ if (new_rx_ring == NULL) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk("\n" KERN_ERR PFX
+ "%s: Consistent memory allocation failed.\n",
+ dev->name);
+ return;
+ }
+ memset(new_rx_ring, 0, sizeof(struct pcnet32_rx_head) * (1 << size));
+
+ new_dma_addr_list = kcalloc(sizeof(dma_addr_t), (1 << size), GFP_ATOMIC);
+ if (!new_dma_addr_list) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk("\n" KERN_ERR PFX
+ "%s: Memory allocation failed.\n", dev->name);
+ goto free_new_rx_ring;
+ }
+
+ new_skb_list = kcalloc(sizeof(struct sk_buff *), (1 << size), GFP_ATOMIC);
+ if (!new_skb_list) {
+ if (pcnet32_debug & NETIF_MSG_DRV)
+ printk("\n" KERN_ERR PFX
+ "%s: Memory allocation failed.\n", dev->name);
+ goto free_new_lists;
+ }
+
+ /* first copy the current receive buffers */
+ overlap = min(size, lp->rx_ring_size);
+ for (new=0; new<overlap; new++) {
+ new_rx_ring[new] = lp->rx_ring[new];
+ new_dma_addr_list[new] = lp->rx_dma_addr[new];
+ new_skb_list[new] = lp->rx_skbuff[new];
+ }
+ /* now allocate any new buffers needed */
+ for (; new < size; new++ ) {
+ struct sk_buff *rx_skbuff;
+ new_skb_list[new] = dev_alloc_skb(PKT_BUF_SZ);
+ if (!(rx_skbuff = new_skb_list[new])) {
+ /* keep the original lists and buffers */
+ if (netif_msg_drv(lp))
+ printk(KERN_ERR
+ "%s: pcnet32_realloc_rx_ring dev_alloc_skb failed.\n",
+ dev->name);
+ goto free_all_new;
+ }
+ skb_reserve(rx_skbuff, 2);
+
+ new_dma_addr_list[new] =
+ pci_map_single(lp->pci_dev, rx_skbuff->data,
+ PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
+ new_rx_ring[new].base = (u32) le32_to_cpu(new_dma_addr_list[new]);
+ new_rx_ring[new].buf_length = le16_to_cpu(2 - PKT_BUF_SZ);
+ new_rx_ring[new].status = le16_to_cpu(0x8000);
+ }
+ /* and free any unneeded buffers */
+ for (; new < lp->rx_ring_size; new++) {
+ if (lp->rx_skbuff[new]) {
+ pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[new],
+ PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(lp->rx_skbuff[new]);
+ }
+ }
+
+ kfree(lp->rx_skbuff);
+ kfree(lp->rx_dma_addr);
+ pci_free_consistent(lp->pci_dev,
+ sizeof(struct pcnet32_rx_head) *
+ lp->rx_ring_size, lp->rx_ring,
+ lp->rx_ring_dma_addr);
+
+ lp->rx_ring_size = (1 << size);
+ lp->rx_mod_mask = lp->rx_ring_size - 1;
+ lp->rx_len_bits = (size << 4);
+ lp->rx_ring = new_rx_ring;
+ lp->rx_ring_dma_addr = new_ring_dma_addr;
+ lp->rx_dma_addr = new_dma_addr_list;
+ lp->rx_skbuff = new_skb_list;
+ return;
+
+ free_all_new:
+ for (; --new >= lp->rx_ring_size; ) {
+ if (new_skb_list[new]) {
+ pci_unmap_single(lp->pci_dev, new_dma_addr_list[new],
+ PKT_BUF_SZ - 2, PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(new_skb_list[new]);
+ }
+ }
+ kfree(new_skb_list);
+ free_new_lists:
+ kfree(new_dma_addr_list);
+ free_new_rx_ring:
+ pci_free_consistent(lp->pci_dev,
+ sizeof(struct pcnet32_rx_head) *
+ (1 << size),
+ new_rx_ring,
+ new_ring_dma_addr);
+ return;
+}
+
#ifdef CONFIG_NET_POLL_CONTROLLER
static void pcnet32_poll_controller(struct net_device *dev)
{
@@ -525,10 +733,10 @@ static void pcnet32_get_ringparam(struct
{
struct pcnet32_private *lp = dev->priv;
- ering->tx_max_pending = TX_MAX_RING_SIZE - 1;
- ering->tx_pending = lp->tx_ring_size - 1;
- ering->rx_max_pending = RX_MAX_RING_SIZE - 1;
- ering->rx_pending = lp->rx_ring_size - 1;
+ ering->tx_max_pending = TX_MAX_RING_SIZE;
+ ering->tx_pending = lp->tx_ring_size;
+ ering->rx_max_pending = RX_MAX_RING_SIZE;
+ ering->rx_pending = lp->rx_ring_size;
}
static int pcnet32_set_ringparam(struct net_device *dev,
@@ -536,44 +744,44 @@ static int pcnet32_set_ringparam(struct
{
struct pcnet32_private *lp = dev->priv;
unsigned long flags;
+ unsigned int size;
+ ulong ioaddr = dev->base_addr;
int i;
if (ering->rx_mini_pending || ering->rx_jumbo_pending)
return -EINVAL;
if (netif_running(dev))
- pcnet32_close(dev);
+ pcnet32_netif_stop(dev);
spin_lock_irqsave(&lp->lock, flags);
- pcnet32_free_ring(dev);
- lp->tx_ring_size =
- min(ering->tx_pending, (unsigned int)TX_MAX_RING_SIZE);
- lp->rx_ring_size =
- min(ering->rx_pending, (unsigned int)RX_MAX_RING_SIZE);
+ lp->a.write_csr(ioaddr, 0, 0x0004); /* stop the chip */
+
+ size = min(ering->tx_pending, (unsigned int)TX_MAX_RING_SIZE);
/* set the minimum ring size to 4, to allow the loopback test to work
* unchanged.
*/
for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) {
- if (lp->tx_ring_size <= (1 << i))
+ if (size <= (1 << i))
break;
}
- lp->tx_ring_size = (1 << i);
- lp->tx_mod_mask = lp->tx_ring_size - 1;
- lp->tx_len_bits = (i << 12);
-
+ if ((1 << i) != lp->tx_ring_size)
+ pcnet32_realloc_tx_ring(dev, lp, i);
+
+ size = min(ering->rx_pending, (unsigned int)RX_MAX_RING_SIZE);
for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) {
- if (lp->rx_ring_size <= (1 << i))
+ if (size <= (1 << i))
break;
}
- lp->rx_ring_size = (1 << i);
- lp->rx_mod_mask = lp->rx_ring_size - 1;
- lp->rx_len_bits = (i << 4);
+ if ((1 << i) != lp->rx_ring_size)
+ pcnet32_realloc_rx_ring(dev, lp, i);
+
+ dev->weight = lp->rx_ring_size / 2;
- if (pcnet32_alloc_ring(dev, dev->name)) {
- pcnet32_free_ring(dev);
- spin_unlock_irqrestore(&lp->lock, flags);
- return -ENOMEM;
+ if (netif_running(dev)) {
+ pcnet32_netif_start(dev);
+ pcnet32_restart(dev, 0x0042);
}
spin_unlock_irqrestore(&lp->lock, flags);
@@ -583,9 +791,6 @@ static int pcnet32_set_ringparam(struct
"%s: Ring Param Settings: RX: %d, TX: %d\n", dev->name,
lp->rx_ring_size, lp->tx_ring_size);
- if (netif_running(dev))
- pcnet32_open(dev);
-
return 0;
}
@@ -643,21 +848,20 @@ static int pcnet32_loopback_test(struct
rc = 1; /* default to fail */
if (netif_running(dev))
- pcnet32_close(dev);
+ pcnet32_netif_stop(dev);
spin_lock_irqsave(&lp->lock, flags);
+ lp->a.write_csr(ioaddr, 0, 0x0004); /* stop the chip */
+
+ numbuffs = min(numbuffs, (int)min(lp->rx_ring_size, lp->tx_ring_size));
/* Reset the PCNET32 */
lp->a.reset(ioaddr);
+ lp->a.write_csr(ioaddr, 4, 0x0915);
/* switch pcnet32 to 32bit mode */
lp->a.write_bcr(ioaddr, 20, 2);
- lp->init_block.mode =
- le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
- lp->init_block.filter[0] = 0;
- lp->init_block.filter[1] = 0;
-
/* purge & init rings but don't actually restart */
pcnet32_restart(dev, 0x0000);
@@ -704,10 +908,10 @@ static int pcnet32_loopback_test(struct
}
x = a->read_bcr(ioaddr, 32); /* set internal loopback in BSR32 */
- x = x | 0x0002;
- a->write_bcr(ioaddr, 32, x);
+ a->write_bcr(ioaddr, 32, x | 0x0002);
- lp->a.write_csr(ioaddr, 15, 0x0044); /* set int loopback in CSR15 */
+ x = a->read_csr(ioaddr, 15); /* set int loopback in CSR15 */
+ lp->a.write_csr(ioaddr, 15, x | 0x0044);
teststatus = le16_to_cpu(0x8000);
lp->a.write_csr(ioaddr, 0, 0x0002); /* Set STRT bit */
@@ -770,21 +974,26 @@ static int pcnet32_loopback_test(struct
clean_up:
pcnet32_purge_tx_ring(dev);
+ for (x = 0; x < numbuffs; x++) {
+ lp->rx_ring[x].buf_length = le16_to_cpu(2 - PKT_BUF_SZ);
+ wmb();
+ lp->rx_ring[x].status = le16_to_cpu(0x8000);
+ }
x = a->read_csr(ioaddr, 15) & 0xFFFF;
a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */
x = a->read_bcr(ioaddr, 32); /* reset internal loopback */
- x = x & ~0x0002;
- a->write_bcr(ioaddr, 32, x);
-
- spin_unlock_irqrestore(&lp->lock, flags);
+ a->write_bcr(ioaddr, 32, (x & ~0x0002));
if (netif_running(dev)) {
- pcnet32_open(dev);
+ pcnet32_netif_start(dev);
+ pcnet32_restart(dev, 0x0042);
} else {
lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */
}
+ spin_unlock_irqrestore(&lp->lock, flags);
+
return (rc);
} /* end pcnet32_loopback_test */
@@ -855,6 +1064,39 @@ static int pcnet32_get_regs_len(struct n
return ((PCNET32_NUM_REGS + j) * sizeof(u16));
}
+/*
+ * lp->lock must be held.
+ */
+static int pcnet32_suspend(struct net_device *dev, unsigned long *flags)
+{
+ int csr5;
+ struct pcnet32_private *lp = dev->priv;
+ struct pcnet32_access *a = &lp->a;
+ ulong ioaddr = dev->base_addr;
+ int ticks;
+
+ /* set SUSPEND (SPND) - CSR5 bit 0 */
+ csr5 = a->read_csr(ioaddr, 5);
+ a->write_csr(ioaddr, 5, csr5 | 0x0001);
+
+ /* poll waiting for bit to be set */
+ ticks = 0;
+ while (!(a->read_csr(ioaddr, 5) & 0x0001)) {
+ spin_unlock_irqrestore(&lp->lock, *flags);
+ mdelay(1);
+ spin_lock_irqsave(&lp->lock, *flags);
+ ticks++;
+ if (ticks > 200) {
+ if (netif_msg_hw(lp))
+ printk(KERN_DEBUG
+ "%s: Error getting into suspend!\n",
+ dev->name);
+ return 0;
+ }
+ }
+ return 1;
+}
+
static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *ptr)
{
@@ -863,31 +1105,17 @@ static void pcnet32_get_regs(struct net_
struct pcnet32_private *lp = dev->priv;
struct pcnet32_access *a = &lp->a;
ulong ioaddr = dev->base_addr;
- int ticks;
unsigned long flags;
spin_lock_irqsave(&lp->lock, flags);
csr0 = a->read_csr(ioaddr, 0);
if (!(csr0 & 0x0004)) { /* If not stopped */
- /* set SUSPEND (SPND) - CSR5 bit 0 */
- a->write_csr(ioaddr, 5, 0x0001);
-
- /* poll waiting for bit to be set */
- ticks = 0;
- while (!(a->read_csr(ioaddr, 5) & 0x0001)) {
- spin_unlock_irqrestore(&lp->lock, flags);
- mdelay(1);
- spin_lock_irqsave(&lp->lock, flags);
- ticks++;
- if (ticks > 200) {
- if (netif_msg_hw(lp))
- printk(KERN_DEBUG
- "%s: Error getting into suspend!\n",
- dev->name);
- break;
- }
- }
+ if (!pcnet32_suspend(dev, &flags))
+ if (netif_msg_hw(lp))
+ printk(KERN_DEBUG
+ "%s: Error getting into suspend!\n",
+ dev->name);
}
/* read address PROM */
@@ -926,8 +1154,11 @@ static void pcnet32_get_regs(struct net_
}
if (!(csr0 & 0x0004)) { /* If not stopped */
+ int csr5;
+
/* clear SUSPEND (SPND) - CSR5 bit 0 */
- a->write_csr(ioaddr, 5, 0x0000);
+ csr5 = a->read_csr(ioaddr, 5);
+ a->write_csr(ioaddr, 5, csr5 & (~0x0001));
}
spin_unlock_irqrestore(&lp->lock, flags);
@@ -958,7 +1189,7 @@ static struct ethtool_ops pcnet32_ethtoo
/* only probes for non-PCI devices, the rest are handled by
* pci_register_driver via pcnet32_probe_pci */
-static void __devinit pcnet32_probe_vlbus(void)
+static void __devinit pcnet32_probe_vlbus(unsigned int *pcnet32_portlist)
{
unsigned int *port, ioaddr;
@@ -1396,6 +1627,8 @@ pcnet32_probe1(unsigned long ioaddr, int
dev->ethtool_ops = &pcnet32_ethtool_ops;
dev->tx_timeout = pcnet32_tx_timeout;
dev->watchdog_timeo = (5 * HZ);
+ dev->poll = pcnet32_poll;
+ dev->weight = lp->rx_ring_size / 2;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = pcnet32_poll_controller;
@@ -2004,6 +2237,279 @@ static int pcnet32_start_xmit(struct sk_
return 0;
}
+static int pcnet32_rx_entry(struct net_device *dev,
+ struct pcnet32_private *lp,
+ struct pcnet32_rx_head *rxp,
+ int entry)
+{
+ int status = (short)le16_to_cpu(rxp->status) >> 8;
+ int rx_in_place = 0;
+ struct sk_buff *skb;
+ short pkt_len;
+
+ if (status != 0x03) { /* There was an error. */
+ /*
+ * There is a tricky error noted by John Murphy,
+ * <murf@perftech.com> to Russ Nelson: Even with full-sized
+ * buffers it's possible for a jabber packet to use two
+ * buffers, with only the last correctly noting the error.
+ */
+ if (status & 0x01) /* Only count a general error at the */
+ lp->stats.rx_errors++; /* end of a packet. */
+ if (status & 0x20)
+ lp->stats.rx_frame_errors++;
+ if (status & 0x10)
+ lp->stats.rx_over_errors++;
+ if (status & 0x08)
+ lp->stats.rx_crc_errors++;
+ if (status & 0x04)
+ lp->stats.rx_fifo_errors++;
+ return 1;
+ }
+
+ pkt_len = (le32_to_cpu(rxp->msg_length) & 0xfff) - 4;
+
+ /* Discard oversize frames. */
+ if (unlikely(pkt_len > PKT_BUF_SZ - 2)) {
+ if (netif_msg_drv(lp))
+ printk(KERN_ERR "%s: Impossible packet size %d!\n",
+ dev->name, pkt_len);
+ lp->stats.rx_errors++;
+ return 1;
+ }
+ if (pkt_len < 60) {
+ if (netif_msg_rx_err(lp))
+ printk(KERN_ERR "%s: Runt packet!\n", dev->name);
+ lp->stats.rx_errors++;
+ return 1;
+ }
+
+ if (pkt_len > rx_copybreak) {
+ struct sk_buff *newskb;
+
+ if ((newskb = dev_alloc_skb(PKT_BUF_SZ))) {
+ skb_reserve(newskb, 2);
+ skb = lp->rx_skbuff[entry];
+ pci_unmap_single(lp->pci_dev,
+ lp->rx_dma_addr[entry],
+ PKT_BUF_SZ - 2,
+ PCI_DMA_FROMDEVICE);
+ skb_put(skb, pkt_len);
+ lp->rx_skbuff[entry] = newskb;
+ newskb->dev = dev;
+ lp->rx_dma_addr[entry] =
+ pci_map_single(lp->pci_dev,
+ newskb->data,
+ PKT_BUF_SZ - 2,
+ PCI_DMA_FROMDEVICE);
+ rxp->base = le32_to_cpu(lp->rx_dma_addr[entry]);
+ rx_in_place = 1;
+ } else
+ skb = NULL;
+ } else {
+ skb = dev_alloc_skb(pkt_len + 2);
+ }
+
+ if (skb == NULL) {
+ if (netif_msg_drv(lp))
+ printk(KERN_ERR
+ "%s: Memory squeeze, dropping packet.\n",
+ dev->name);
+ lp->stats.rx_dropped++;
+ return 1;
+ }
+ skb->dev = dev;
+ if (!rx_in_place) {
+ skb_reserve(skb, 2); /* 16 byte align */
+ skb_put(skb, pkt_len); /* Make room */
+ pci_dma_sync_single_for_cpu(lp->pci_dev,
+ lp->rx_dma_addr[entry],
+ PKT_BUF_SZ - 2,
+ PCI_DMA_FROMDEVICE);
+ eth_copy_and_sum(skb,
+ (unsigned char *)(lp->rx_skbuff[entry]->data),
+ pkt_len, 0);
+ pci_dma_sync_single_for_device(lp->pci_dev,
+ lp->rx_dma_addr[entry],
+ PKT_BUF_SZ - 2,
+ PCI_DMA_FROMDEVICE);
+ }
+ lp->stats.rx_bytes += skb->len;
+ lp->stats.rx_packets++;
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_receive_skb(skb);
+ dev->last_rx = jiffies;
+ return 1;
+}
+
+static int pcnet32_rx(struct net_device *dev, int quota)
+{
+ struct pcnet32_private *lp = dev->priv;
+ int entry = lp->cur_rx & lp->rx_mod_mask;
+ struct pcnet32_rx_head *rxp = &lp->rx_ring[entry];
+ int npackets = 0;
+
+ /* If we own the next entry, it's a new packet. Send it up. */
+ while (quota > npackets && (short)le16_to_cpu(rxp->status) >= 0) {
+ npackets += pcnet32_rx_entry(dev, lp, rxp, entry);
+ /*
+ * The docs say that the buffer length isn't touched, but Andrew
+ * Boyd of QNX reports that some revs of the 79C965 clear it.
+ */
+ rxp->buf_length = le16_to_cpu(2 - PKT_BUF_SZ);
+ wmb(); /* Make sure owner changes after others are visible */
+ rxp->status = le16_to_cpu(0x8000);
+ entry = (++lp->cur_rx) & lp->rx_mod_mask;
+ rxp = &lp->rx_ring[entry];
+ }
+
+ return npackets;
+}
+
+static int pcnet32_tx(struct net_device *dev)
+{
+ struct pcnet32_private *lp = dev->priv;
+ unsigned int dirty_tx = lp->dirty_tx;
+ int delta;
+ int must_restart = 0;
+
+ while (dirty_tx != lp->cur_tx) {
+ int entry = dirty_tx & lp->tx_mod_mask;
+ int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
+
+ if (status < 0)
+ break; /* It still hasn't been Txed */
+
+ lp->tx_ring[entry].base = 0;
+
+ if (status & 0x4000) {
+ /* There was an major error, log it. */
+ int err_status =
+ le32_to_cpu(lp->tx_ring[entry].
+ misc);
+ lp->stats.tx_errors++;
+ if (netif_msg_tx_err(lp))
+ printk(KERN_ERR
+ "%s: Tx error status=%04x err_status=%08x\n",
+ dev->name, status,
+ err_status);
+ if (err_status & 0x04000000)
+ lp->stats.tx_aborted_errors++;
+ if (err_status & 0x08000000)
+ lp->stats.tx_carrier_errors++;
+ if (err_status & 0x10000000)
+ lp->stats.tx_window_errors++;
+#ifndef DO_DXSUFLO
+ if (err_status & 0x40000000) {
+ lp->stats.tx_fifo_errors++;
+ /* Ackk! On FIFO errors the Tx unit is turned off! */
+ /* Remove this verbosity later! */
+ if (netif_msg_tx_err(lp))
+ printk(KERN_ERR
+ "%s: Tx FIFO error!\n",
+ dev->name);
+ must_restart = 1;
+ }
+#else
+ if (err_status & 0x40000000) {
+ lp->stats.tx_fifo_errors++;
+ if (!lp->dxsuflo) { /* If controller doesn't recover ... */
+ /* Ackk! On FIFO errors the Tx unit is turned off! */
+ /* Remove this verbosity later! */
+ if (netif_msg_tx_err(lp))
+ printk(KERN_ERR
+ "%s: Tx FIFO error!\n",
+ dev->name);
+ must_restart = 1;
+ }
+ }
+#endif
+ } else {
+ if (status & 0x1800)
+ lp->stats.collisions++;
+ lp->stats.tx_packets++;
+ }
+
+ /* We must free the original skb */
+ if (lp->tx_skbuff[entry]) {
+ pci_unmap_single(lp->pci_dev,
+ lp->tx_dma_addr[entry],
+ lp->tx_skbuff[entry]->
+ len, PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(lp->tx_skbuff[entry]);
+ lp->tx_skbuff[entry] = NULL;
+ lp->tx_dma_addr[entry] = 0;
+ }
+ dirty_tx++;
+ }
+
+ delta = (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + lp->tx_ring_size);
+ if (delta > lp->tx_ring_size) {
+ if (netif_msg_drv(lp))
+ printk(KERN_ERR
+ "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+ dev->name, dirty_tx, lp->cur_tx,
+ lp->tx_full);
+ dirty_tx += lp->tx_ring_size;
+ delta -= lp->tx_ring_size;
+ }
+
+ if (lp->tx_full &&
+ netif_queue_stopped(dev) &&
+ delta < lp->tx_ring_size - 2) {
+ /* The ring is no longer full, clear tbusy. */
+ lp->tx_full = 0;
+ netif_wake_queue(dev);
+ }
+ lp->dirty_tx = dirty_tx;
+
+ return must_restart;
+}
+
+static int pcnet32_poll(struct net_device *dev, int *budget)
+{
+ struct pcnet32_private *lp = dev->priv;
+ int quota = min(dev->quota, *budget);
+ unsigned long ioaddr = dev->base_addr;
+ u16 val;
+ unsigned long flags;
+
+ quota = pcnet32_rx(dev, quota);
+
+ spin_lock_irqsave(&lp->lock, flags);
+ if (pcnet32_tx(dev)) {
+ /* reset the chip to clear the error condition, then restart */
+ lp->a.reset(ioaddr);
+ lp->a.write_csr(ioaddr, 4, 0x0915);
+ pcnet32_restart(dev, 0x0002);
+ netif_wake_queue(dev);
+ }
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ *budget -= quota;
+ dev->quota -= quota;
+
+ if (dev->quota == 0) {
+ return 1;
+ }
+
+ netif_rx_complete(dev);
+
+ spin_lock_irqsave(&lp->lock, flags);
+
+ /* clear interrupt masks */
+ val = lp->a.read_csr(ioaddr, 3);
+ val &= 0x00ff;
+ lp->a.write_csr(ioaddr, 3, val);
+
+ /* Set interrupt enable. */
+ lp->a.write_csr(ioaddr, 0, 0x0040);
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ return 0;
+}
+
/* The PCNET32 interrupt handler. */
static irqreturn_t
pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -2011,9 +2517,8 @@ pcnet32_interrupt(int irq, void *dev_id,
struct net_device *dev = dev_id;
struct pcnet32_private *lp;
unsigned long ioaddr;
- u16 csr0, rap;
- int boguscnt = max_interrupt_work;
- int must_restart;
+ u16 csr0;
+ irqreturn_t rc = IRQ_HANDLED;
if (!dev) {
if (pcnet32_debug & NETIF_MSG_INTR)
@@ -2027,124 +2532,27 @@ pcnet32_interrupt(int irq, void *dev_id,
spin_lock(&lp->lock);
- rap = lp->a.read_rap(ioaddr);
- while ((csr0 = lp->a.read_csr(ioaddr, 0)) & 0x8f00 && --boguscnt >= 0) {
- if (csr0 == 0xffff) {
- break; /* PCMCIA remove happened */
- }
+ csr0 = lp->a.read_csr(ioaddr, 0);
+ if (csr0 == 0xffff) {
+ rc = IRQ_NONE;
+ } else if (csr0 & 0x8f00) {
/* Acknowledge all of the current interrupt sources ASAP. */
lp->a.write_csr(ioaddr, 0, csr0 & ~0x004f);
- must_restart = 0;
-
if (netif_msg_intr(lp))
printk(KERN_DEBUG
"%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n",
dev->name, csr0, lp->a.read_csr(ioaddr, 0));
- if (csr0 & 0x0400) /* Rx interrupt */
- pcnet32_rx(dev);
-
- if (csr0 & 0x0200) { /* Tx-done interrupt */
- unsigned int dirty_tx = lp->dirty_tx;
- int delta;
-
- while (dirty_tx != lp->cur_tx) {
- int entry = dirty_tx & lp->tx_mod_mask;
- int status =
- (short)le16_to_cpu(lp->tx_ring[entry].
- status);
-
- if (status < 0)
- break; /* It still hasn't been Txed */
-
- lp->tx_ring[entry].base = 0;
-
- if (status & 0x4000) {
- /* There was an major error, log it. */
- int err_status =
- le32_to_cpu(lp->tx_ring[entry].
- misc);
- lp->stats.tx_errors++;
- if (netif_msg_tx_err(lp))
- printk(KERN_ERR
- "%s: Tx error status=%04x err_status=%08x\n",
- dev->name, status,
- err_status);
- if (err_status & 0x04000000)
- lp->stats.tx_aborted_errors++;
- if (err_status & 0x08000000)
- lp->stats.tx_carrier_errors++;
- if (err_status & 0x10000000)
- lp->stats.tx_window_errors++;
-#ifndef DO_DXSUFLO
- if (err_status & 0x40000000) {
- lp->stats.tx_fifo_errors++;
- /* Ackk! On FIFO errors the Tx unit is turned off! */
- /* Remove this verbosity later! */
- if (netif_msg_tx_err(lp))
- printk(KERN_ERR
- "%s: Tx FIFO error! CSR0=%4.4x\n",
- dev->name, csr0);
- must_restart = 1;
- }
-#else
- if (err_status & 0x40000000) {
- lp->stats.tx_fifo_errors++;
- if (!lp->dxsuflo) { /* If controller doesn't recover ... */
- /* Ackk! On FIFO errors the Tx unit is turned off! */
- /* Remove this verbosity later! */
- if (netif_msg_tx_err
- (lp))
- printk(KERN_ERR
- "%s: Tx FIFO error! CSR0=%4.4x\n",
- dev->
- name,
- csr0);
- must_restart = 1;
- }
- }
-#endif
- } else {
- if (status & 0x1800)
- lp->stats.collisions++;
- lp->stats.tx_packets++;
- }
-
- /* We must free the original skb */
- if (lp->tx_skbuff[entry]) {
- pci_unmap_single(lp->pci_dev,
- lp->tx_dma_addr[entry],
- lp->tx_skbuff[entry]->
- len, PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(lp->tx_skbuff[entry]);
- lp->tx_skbuff[entry] = NULL;
- lp->tx_dma_addr[entry] = 0;
- }
- dirty_tx++;
- }
-
- delta =
- (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask +
- lp->tx_ring_size);
- if (delta > lp->tx_ring_size) {
- if (netif_msg_drv(lp))
- printk(KERN_ERR
- "%s: out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
- dev->name, dirty_tx, lp->cur_tx,
- lp->tx_full);
- dirty_tx += lp->tx_ring_size;
- delta -= lp->tx_ring_size;
- }
-
- if (lp->tx_full &&
- netif_queue_stopped(dev) &&
- delta < lp->tx_ring_size - 2) {
- /* The ring is no longer full, clear tbusy. */
- lp->tx_full = 0;
- netif_wake_queue(dev);
- }
- lp->dirty_tx = dirty_tx;
+ if (netif_rx_schedule_prep(dev)) {
+ u16 val;
+ /* set interrupt masks */
+ val = lp->a.read_csr(ioaddr, 3);
+ val |= 0x5f00;
+ lp->a.write_csr(ioaddr, 3, val);
+ __netif_rx_schedule(dev);
+ } else {
+ printk(KERN_DEBUG "%s: interrupt while in polling mode.\n", dev->name);
}
/* Log misc errors. */
@@ -2152,16 +2560,16 @@ pcnet32_interrupt(int irq, void *dev_id,
lp->stats.tx_errors++; /* Tx babble. */
if (csr0 & 0x1000) {
/*
- * this happens when our receive ring is full. This shouldn't
- * be a problem as we will see normal rx interrupts for the frames
- * in the receive ring. But there are some PCI chipsets (I can
- * reproduce this on SP3G with Intel saturn chipset) which have
- * sometimes problems and will fill up the receive ring with
- * error descriptors. In this situation we don't get a rx
- * interrupt, but a missed frame interrupt sooner or later.
- * So we try to clean up our receive ring here.
+ * This happens when our receive ring is full. This
+ * shouldn't be a problem as we will see normal rx
+ * interrupts for the frames in the receive ring. But
+ * there are some PCI chipsets (I can reproduce this
+ * on SP3G with Intel saturn chipset) which have
+ * sometimes problems and will fill up the receive
+ * ring with error descriptors. In this situation we
+ * don't get a rx interrupt, but a missed frame
+ * interrupt sooner or later.
*/
- pcnet32_rx(dev);
lp->stats.rx_errors++; /* Missed a Rx frame. */
}
if (csr0 & 0x0800) {
@@ -2171,183 +2579,15 @@ pcnet32_interrupt(int irq, void *dev_id,
dev->name, csr0);
/* unlike for the lance, there is no restart needed */
}
-
- if (must_restart) {
- /* reset the chip to clear the error condition, then restart */
- lp->a.reset(ioaddr);
- lp->a.write_csr(ioaddr, 4, 0x0915);
- pcnet32_restart(dev, 0x0002);
- netif_wake_queue(dev);
- }
}
- /* Set interrupt enable. */
- lp->a.write_csr(ioaddr, 0, 0x0040);
- lp->a.write_rap(ioaddr, rap);
-
if (netif_msg_intr(lp))
printk(KERN_DEBUG "%s: exiting interrupt, csr0=%#4.4x.\n",
dev->name, lp->a.read_csr(ioaddr, 0));
spin_unlock(&lp->lock);
- return IRQ_HANDLED;
-}
-
-static int pcnet32_rx(struct net_device *dev)
-{
- struct pcnet32_private *lp = dev->priv;
- int entry = lp->cur_rx & lp->rx_mod_mask;
- int boguscnt = lp->rx_ring_size / 2;
-
- /* If we own the next entry, it's a new packet. Send it up. */
- while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) {
- int status = (short)le16_to_cpu(lp->rx_ring[entry].status) >> 8;
-
- if (status != 0x03) { /* There was an error. */
- /*
- * There is a tricky error noted by John Murphy,
- * <murf@perftech.com> to Russ Nelson: Even with full-sized
- * buffers it's possible for a jabber packet to use two
- * buffers, with only the last correctly noting the error.
- */
- if (status & 0x01) /* Only count a general error at the */
- lp->stats.rx_errors++; /* end of a packet. */
- if (status & 0x20)
- lp->stats.rx_frame_errors++;
- if (status & 0x10)
- lp->stats.rx_over_errors++;
- if (status & 0x08)
- lp->stats.rx_crc_errors++;
- if (status & 0x04)
- lp->stats.rx_fifo_errors++;
- lp->rx_ring[entry].status &= le16_to_cpu(0x03ff);
- } else {
- /* Malloc up new buffer, compatible with net-2e. */
- short pkt_len =
- (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff)
- - 4;
- struct sk_buff *skb;
-
- /* Discard oversize frames. */
- if (unlikely(pkt_len > PKT_BUF_SZ - 2)) {
- if (netif_msg_drv(lp))
- printk(KERN_ERR
- "%s: Impossible packet size %d!\n",
- dev->name, pkt_len);
- lp->stats.rx_errors++;
- } else if (pkt_len < 60) {
- if (netif_msg_rx_err(lp))
- printk(KERN_ERR "%s: Runt packet!\n",
- dev->name);
- lp->stats.rx_errors++;
- } else {
- int rx_in_place = 0;
-
- if (pkt_len > rx_copybreak) {
- struct sk_buff *newskb;
-
- if ((newskb =
- dev_alloc_skb(PKT_BUF_SZ))) {
- skb_reserve(newskb, 2);
- skb = lp->rx_skbuff[entry];
- pci_unmap_single(lp->pci_dev,
- lp->
- rx_dma_addr
- [entry],
- PKT_BUF_SZ - 2,
- PCI_DMA_FROMDEVICE);
- skb_put(skb, pkt_len);
- lp->rx_skbuff[entry] = newskb;
- newskb->dev = dev;
- lp->rx_dma_addr[entry] =
- pci_map_single(lp->pci_dev,
- newskb->data,
- PKT_BUF_SZ -
- 2,
- PCI_DMA_FROMDEVICE);
- lp->rx_ring[entry].base =
- le32_to_cpu(lp->
- rx_dma_addr
- [entry]);
- rx_in_place = 1;
- } else
- skb = NULL;
- } else {
- skb = dev_alloc_skb(pkt_len + 2);
- }
-
- if (skb == NULL) {
- int i;
- if (netif_msg_drv(lp))
- printk(KERN_ERR
- "%s: Memory squeeze, deferring packet.\n",
- dev->name);
- for (i = 0; i < lp->rx_ring_size; i++)
- if ((short)
- le16_to_cpu(lp->
- rx_ring[(entry +
- i)
- & lp->
- rx_mod_mask].
- status) < 0)
- break;
-
- if (i > lp->rx_ring_size - 2) {
- lp->stats.rx_dropped++;
- lp->rx_ring[entry].status |=
- le16_to_cpu(0x8000);
- wmb(); /* Make sure adapter sees owner change */
- lp->cur_rx++;
- }
- break;
- }
- skb->dev = dev;
- if (!rx_in_place) {
- skb_reserve(skb, 2); /* 16 byte align */
- skb_put(skb, pkt_len); /* Make room */
- pci_dma_sync_single_for_cpu(lp->pci_dev,
- lp->
- rx_dma_addr
- [entry],
- PKT_BUF_SZ -
- 2,
- PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb,
- (unsigned char *)(lp->
- rx_skbuff
- [entry]->
- data),
- pkt_len, 0);
- pci_dma_sync_single_for_device(lp->
- pci_dev,
- lp->
- rx_dma_addr
- [entry],
- PKT_BUF_SZ
- - 2,
- PCI_DMA_FROMDEVICE);
- }
- lp->stats.rx_bytes += skb->len;
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
- dev->last_rx = jiffies;
- lp->stats.rx_packets++;
- }
- }
- /*
- * The docs say that the buffer length isn't touched, but Andrew Boyd
- * of QNX reports that some revs of the 79C965 clear it.
- */
- lp->rx_ring[entry].buf_length = le16_to_cpu(2 - PKT_BUF_SZ);
- wmb(); /* Make sure owner changes after all others are visible */
- lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
- entry = (++lp->cur_rx) & lp->rx_mod_mask;
- if (--boguscnt <= 0)
- break; /* don't stay in loop forever */
- }
-
- return 0;
+ return rc;
}
static int pcnet32_close(struct net_device *dev)
@@ -2420,13 +2660,10 @@ static struct net_device_stats *pcnet32_
{
struct pcnet32_private *lp = dev->priv;
unsigned long ioaddr = dev->base_addr;
- u16 saved_addr;
unsigned long flags;
spin_lock_irqsave(&lp->lock, flags);
- saved_addr = lp->a.read_rap(ioaddr);
lp->stats.rx_missed_errors = lp->a.read_csr(ioaddr, 112);
- lp->a.write_rap(ioaddr, saved_addr);
spin_unlock_irqrestore(&lp->lock, flags);
return &lp->stats;
@@ -2439,6 +2676,7 @@ static void pcnet32_load_multicast(struc
volatile struct pcnet32_init_block *ib = &lp->init_block;
volatile u16 *mcast_table = (u16 *) & ib->filter;
struct dev_mc_list *dmi = dev->mc_list;
+ unsigned long ioaddr = dev->base_addr;
char *addrs;
int i;
u32 crc;
@@ -2447,6 +2685,10 @@ static void pcnet32_load_multicast(struc
if (dev->flags & IFF_ALLMULTI) {
ib->filter[0] = 0xffffffff;
ib->filter[1] = 0xffffffff;
+ lp->a.write_csr(ioaddr, 8, 0xffff);
+ lp->a.write_csr(ioaddr, 9, 0xffff);
+ lp->a.write_csr(ioaddr, 10, 0xffff);
+ lp->a.write_csr(ioaddr, 11, 0xffff);
return;
}
/* clear the multicast filter */
@@ -2468,6 +2710,8 @@ static void pcnet32_load_multicast(struc
le16_to_cpu(le16_to_cpu(mcast_table[crc >> 4]) |
(1 << (crc & 0xf)));
}
+ for (i=0; i<4; i++)
+ lp->a.write_csr(ioaddr, 8+i, le16_to_cpu(mcast_table[i]));
return;
}
@@ -2478,8 +2722,11 @@ static void pcnet32_set_multicast_list(s
{
unsigned long ioaddr = dev->base_addr, flags;
struct pcnet32_private *lp = dev->priv;
+ int csr15, suspended;
spin_lock_irqsave(&lp->lock, flags);
+ suspended = pcnet32_suspend(dev, &flags);
+ csr15 = lp->a.read_csr(ioaddr, 15);
if (dev->flags & IFF_PROMISC) {
/* Log any net taps. */
if (netif_msg_hw(lp))
@@ -2488,15 +2735,24 @@ static void pcnet32_set_multicast_list(s
lp->init_block.mode =
le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) <<
7);
+ lp->a.write_csr(ioaddr, 15, csr15 | 0x8000);
} else {
lp->init_block.mode =
le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
+ lp->a.write_csr(ioaddr, 15, csr15 & 0x7fff);
pcnet32_load_multicast(dev);
}
- lp->a.write_csr(ioaddr, 0, 0x0004); /* Temporarily stop the lance. */
- pcnet32_restart(dev, 0x0042); /* Resume normal operation */
- netif_wake_queue(dev);
+ if (suspended) {
+ int csr5;
+ /* clear SUSPEND (SPND) - CSR5 bit 0 */
+ csr5 = lp->a.read_csr(ioaddr, 5);
+ lp->a.write_csr(ioaddr, 5, csr5 & (~0x0001));
+ } else {
+ lp->a.write_csr(ioaddr, 0, 0x0004); /* stop the lance. */
+ pcnet32_restart(dev, 0x0042); /* Resume normal operation */
+ netif_wake_queue(dev);
+ }
spin_unlock_irqrestore(&lp->lock, flags);
}
@@ -2736,7 +2992,7 @@ static int __init pcnet32_init_module(vo
/* should we find any remaining VLbus devices ? */
if (pcnet32vlb)
- pcnet32_probe_vlbus();
+ pcnet32_probe_vlbus(pcnet32_portlist);
if (cards_found && (pcnet32_debug & NETIF_MSG_PROBE))
printk(KERN_INFO PFX "%d cards_found.\n", cards_found);
--
Don Fry
brazilnut@us.ibm.com
^ permalink raw reply
* Linux 2.6 Vs linux 2.4 routing
From: Mayuresh Chitale @ 2006-06-16 18:41 UTC (permalink / raw)
To: netdev, linux-net
Hi All,
I am doing a routing test using linux 2.4 and linux 2.6 kernel on our
board. I am using 2.4.31 and 2.6.16.17 for comparison.
I have ported the bsp and drivers from 2.4 to 2.6 and am using a
smartbits tester which pumps traffic at high rates and at varying
packet sizes.
On 2.4, the test goes fine ie I get meaningful values. But on 2.6
kernel, routing begins and continues for sometime before it completely
stops. The smartbits configuration is identical in both the cases.
I have noticed same problem with dlink and 3com cards which is causing
me to suspect that there is some probem with 2.6 routing.
Has anyone seen a similar problem ?
Any inputs on this would be appreciated.
Thanks,
Mayuresh.
^ permalink raw reply
* Re: Suspending 802.11 drivers
From: Stefan Rompf @ 2006-06-16 18:36 UTC (permalink / raw)
To: Michael Buesch; +Cc: Jiri Benc, John W. Linville, netdev, bcm43xx-dev
In-Reply-To: <200606152158.10079.mb@bu3sch.de>
Am Donnerstag 15 Juni 2006 21:58 schrieb Michael Buesch:
> I am currently thinking about the best way to correctly
> implement PM suspending for wireless drivers.
> Currently, the 802.11 stack is not suspend aware (if I talk
> about "stack" here, I mostly mean devicescape).
> For example, if we suspend the bcm43xx driver, we don't
> notify the stack before doing so. That's a bug.
I think the most important question is how a suspend/resume action should be
translated. For the managed case, it is clearly an association loss, normally
signalled by netif_carrier_on/off() and a corresponding SIOCGIWAP event.
Supplicants can act on this. In AP mode, suspend is equal to disassociating
all stations. Ad-hoc... dunno.
For a softmac stack like devicescape, it makes sense to have a function that
abstracts these scenarios as it is the stack anyway that handles association
stuff. However, I'd rather extend the existing function
ieee80211_netif_oper().
> The suspend would save all status information, for example
> to which AP we are associated and so on. After that it would
> cleanly disassociate from the AP and do other cleanups which
> are needed.
It would *try* to cleanly disassociate. No way waiting for the management
packet to reach the air or even for the AP's acknowledgement while half of
userspace is already frozen and the user wants the machine to go down ASAP.
(But that's an interesting point. Will sniff whether ipw2200 hardware sends a
final packet on suspend.)
> The resume function would try to re-esablish the connection.
Don't keep too much state - just notify userspace of the disassociation, then
scan and reassociate using the given iwconfig parameters or the running
supplicant as it would happen on a normal association loss. ipw2200 acts like
this, and it is definitely fast enough.
Stefan
^ permalink raw reply
* Re: tg3 timeouts with 2.6.17-rc6
From: Michael Chan @ 2006-06-16 17:02 UTC (permalink / raw)
To: Juergen Kreileder, linux-kernel; +Cc: netdev
Juergen Kreileder
> I'm seeing frequent network timeouts on my PowerMac G5 Quad with
> 2.6.17-rc6. The timeouts are easily reproducible with moderate
> network traffic, e.g. by using bittorrent.
>
Did this use to work with an older kernel or older tg3 driver? If
yes, what version?
Please also provide the full tg3 probing output during modprobe and
ifconfig up. Thanks.
^ permalink raw reply
* tg3 timeouts with 2.6.17-rc6
From: Juergen Kreileder @ 2006-06-16 16:50 UTC (permalink / raw)
To: linux-kernel; +Cc: mchan, netdev
Hi,
I'm seeing frequent network timeouts on my PowerMac G5 Quad with
2.6.17-rc6. The timeouts are easily reproducible with moderate
network traffic, e.g. by using bittorrent.
,----
| NETDEV WATCHDOG: lan0: transmit timed out
| tg3: lan0: transmit timed out, resetting
| tg3: tg3_stop_block timed out, ofs=2c00 enable_bit=2
| tg3: tg3_stop_block timed out, ofs=1400 enable_bit=2
| tg3: lan0: Link is down.
| [...]
| tg3: lan0: Link is up at 1000 Mbps, full duplex.
| tg3: lan0: Flow control is on for TX and on for RX.
`----
Juergen
--
Juergen Kreileder, Blackdown Java-Linux Team
http://blog.blackdown.de/
^ permalink raw reply
* Re: PATCHv3 2.6.17-rc5 tulip free_irq() called too late
From: Jeff Garzik @ 2006-06-16 16:16 UTC (permalink / raw)
To: Grant Grundler; +Cc: Francois Romieu, Valerie Henson, Andrew Morton, netdev
In-Reply-To: <20060616160623.GF7868@colo.lackof.org>
Grant Grundler wrote:
> [ Jeff, apologies. I hit "reply" instead of "group reply" on previous email.
> I've added everyone back on the cc list.]
>
> On Fri, Jun 16, 2006 at 11:30:32AM -0400, Jeff Garzik wrote:
> ...
>>> Are you saying this sequence won't mask interrupts on tulip?
>>>
>>> /* Disable interrupts by clearing the interrupt mask. */
>>> iowrite32 (0x00000000, ioaddr + CSR7);
>>> ioread32 (ioaddr + CSR7); /* flush posted write */
>> It does not stop the generation of interrupt events.
>
> This use of "interrupt events" is misleading.
> The CPU does not sees these "interrupt events" once we mask interrupts.
>
>> The DMA engine is still running, packets are still being received.
>> The above code sequence does not change that.
>
> I agree. And I'm asking why does anyone care?
> We clean that up after IRQs are stopped from being delivered to the CPU.
>
> ...
>>> Secondly, since you have ignored the two previous times I've asked,
>>> I'll presume you agree that if firmware leaves it in this state
>>> (pending, masked interrupts), that the driver has to (and does)
>>> handle it.
>> There is no firmware involved here, at any level, after boot.
>
> I agree. What about at boot time?
We reset the chip each time we do an interface-up.
>> The needed task in the driver has been the same since this thread
>> started: (1) stop generating new work [stop DMA engine], and (2)
>> quiesce the hardware. And it must happen in that order.
>
> No it doesn't. I've proven it works in the order I've proposed
> on pretty damn anal HW.
>
>> Setting the interrupt mask register to zero doesn't stop new work from
>> appearing.
>
> I agree. It stops the "screaming interrupt" problem. The fact that we
> are in "close" or "down" routine means the user already decided
> they don't care if new packets do or do not arrive.
>
> Unless you can point to a real user who is affected by
> my proposed patch, I ask again patch v3 be accepted.
All users are affected. There is still a race window due to calling
free_irq() before stopping the DMA engine, you've simply minimized it.
I don't see why it's so difficult to see
(a) you are introducing a non-standard ordering, different from other
net drivers
(b) you are introducing an ordering that is counter to how the hardware
is designed
(c) if you follow the natural ordering, you are GUARANTEED not to have
screaming interrupts, DMA still going across the PCI bus, and dozens of
other details.
Rather than running through all of these details, and tweaking your
patch for each of them (as you have done with V1->V2 and V2->V3), simply
_guarantee_ that you will not have problems.
Jeff
^ permalink raw reply
* Re: PATCHv3 2.6.17-rc5 tulip free_irq() called too late
From: Grant Grundler @ 2006-06-16 16:06 UTC (permalink / raw)
To: Jeff Garzik; +Cc: Francois Romieu, Valerie Henson, Andrew Morton, netdev
In-Reply-To: <4492CE98.50900@pobox.com>
[ Jeff, apologies. I hit "reply" instead of "group reply" on previous email.
I've added everyone back on the cc list.]
On Fri, Jun 16, 2006 at 11:30:32AM -0400, Jeff Garzik wrote:
...
> >Are you saying this sequence won't mask interrupts on tulip?
> >
> > /* Disable interrupts by clearing the interrupt mask. */
> > iowrite32 (0x00000000, ioaddr + CSR7);
> > ioread32 (ioaddr + CSR7); /* flush posted write */
>
> It does not stop the generation of interrupt events.
This use of "interrupt events" is misleading.
The CPU does not sees these "interrupt events" once we mask interrupts.
> The DMA engine is still running, packets are still being received.
> The above code sequence does not change that.
I agree. And I'm asking why does anyone care?
We clean that up after IRQs are stopped from being delivered to the CPU.
...
> >Secondly, since you have ignored the two previous times I've asked,
> >I'll presume you agree that if firmware leaves it in this state
> >(pending, masked interrupts), that the driver has to (and does)
> >handle it.
>
> There is no firmware involved here, at any level, after boot.
I agree. What about at boot time?
> The needed task in the driver has been the same since this thread
> started: (1) stop generating new work [stop DMA engine], and (2)
> quiesce the hardware. And it must happen in that order.
No it doesn't. I've proven it works in the order I've proposed
on pretty damn anal HW.
> Setting the interrupt mask register to zero doesn't stop new work from
> appearing.
I agree. It stops the "screaming interrupt" problem. The fact that we
are in "close" or "down" routine means the user already decided
they don't care if new packets do or do not arrive.
Unless you can point to a real user who is affected by
my proposed patch, I ask again patch v3 be accepted.
thanks,
grant
^ permalink raw reply
* Re: PATCHv3 2.6.17-rc5 tulip free_irq() called too late
From: Grant Grundler @ 2006-06-16 15:25 UTC (permalink / raw)
To: Jeff Garzik
Cc: Grant Grundler, Francois Romieu, Valerie Henson, Andrew Morton,
netdev
In-Reply-To: <44925EA8.5070906@pobox.com>
On Fri, Jun 16, 2006 at 03:32:56AM -0400, Jeff Garzik wrote:
> >Correct. Before calling free_irq(), patch V3 masks interrupts on tulip
> >and guarantees the tulip will not generate new interrupts before that call.
>
> Incorrect -- it does not guarantee that tulip will not generate new
> interrupt events.
Are you saying the following sequence doesn't mask tulip interrupts?
/* Disable interrupts by clearing the interrupt mask. */
iowrite32 (0x00000000, ioaddr + CSR7);
ioread32 (ioaddr + CSR7); /* flush posted write */
Secondly, since you've ignored the two previous times I've asked,
I'll assume you agree tulip driver has to (and does) handle
the case of pending, masked interrupts at initialization because
firmware might leave it in that state.
thanks,
grant
^ permalink raw reply
* Re: [PATCH v2 4/7] AMSO1100 Memory Management.
From: Steve Wise @ 2006-06-16 14:20 UTC (permalink / raw)
To: Tom Tucker
Cc: Andrew Morton, rdreier, mshefty, linux-kernel, netdev,
openib-general
In-Reply-To: <1150128349.22704.20.camel@trinity.ogc.int>
On Mon, 2006-06-12 at 11:05 -0500, Tom Tucker wrote:
> On Thu, 2006-06-08 at 01:17 -0700, Andrew Morton wrote:
> > On Wed, 07 Jun 2006 15:06:55 -0500
> > Steve Wise <swise@opengridcomputing.com> wrote:
> >
> > >
> > > +void c2_free(struct c2_alloc *alloc, u32 obj)
> > > +{
> > > + spin_lock(&alloc->lock);
> > > + clear_bit(obj, alloc->table);
> > > + spin_unlock(&alloc->lock);
> > > +}
> >
> > The spinlock is unneeded here.
>
> Good point.
>
> >
> >
> > What does all the code in this file do, anyway? It looks totally generic
> > (and hence inappropriate for drivers/infiniband/hw/amso1100/) and somewhat
> > similar to idr trees, perhaps.
> >
>
> We mimicked the mthca driver. It may be code that should be replaced
> with Linux core services for new drivers. We'll investigate.
>
The code in this file implements 2 sets of services:
1) allocating unique qp identifiers (type integer). This is the
c2_alloc struct and functions.
2) maintaining a sparsely allocated array of ptrs indexed by the qp
identifier. This allows for quick mapping to the qp structure ptr given
the qp identifier. This is the c2_array struct and functions.
I believe I can use an IDR tree to provide both of these services.
Steve.
^ permalink raw reply
* Re: NETDEV WATCHDOG: eth2: transmit timed out with 3c905C-TX
From: Marco Berizzi @ 2006-06-16 12:44 UTC (permalink / raw)
To: klassert; +Cc: netdev
In-Reply-To: <20060606191326.GE14011@bayes.mathematik.tu-chemnitz.de>
Steffen Klassert wrote:
>On Tue, Jun 06, 2006 at 11:12:45AM +0200, Marco Berizzi wrote:
> >
> > I have moved this damn pc from the remote to my site and I have
> > placed it in production environment with 2.6.17-rc5
> > No problem after 24 hours (on the remote side the problem was
> > arising after a couple of hours). I have modprobed 3c59x with
> > debug=4. I see only these kind of messages (are they fine?):
> >
> > Jun 5 14:31:25 Pleiadi kernel: eth2: vortex_error(), status=0x8081
> > Jun 5 14:31:40 Pleiadi last message repeated 3 times
> > Jun 5 14:31:47 Pleiadi kernel: eth2: vortex_error(), status=0x8281
> > Jun 5 14:31:47 Pleiadi kernel: eth2: Media selection timer tick
>happened,
> > Autonegotiate.
> > Jun 5 14:31:47 Pleiadi kernel: dev->watchdog_timeo=1250
> > Jun 5 14:31:47 Pleiadi kernel: eth2: MII transceiver has status 782d.
> > Jun 5 14:31:47 Pleiadi kernel: eth2: Media selection timer finished,
> > Autonegotiate.
> > Jun 5 14:31:51 Pleiadi kernel: eth2: vortex_error(), status=0x8081
> > Jun 5 14:32:03 Pleiadi last message repeated 2 times
> > Jun 5 14:32:10 Pleiadi kernel: eth2: vortex_error(), status=0x8481
> > Jun 5 14:32:15 Pleiadi kernel: eth2: vortex_error(), status=0x8081
> > Jun 5 14:32:46 Pleiadi last message repeated 7 times
>
>This is ok, just normal operation of the NIC.
>
> >
> > The only relevant change, between the remote and my site, is a
> > different ethernet switch where the 3c905C is connected to.
> > Could it be an issue?
>
>Well, I think it can. Problems with a switch are mostly related
>to the autonegotiation of the media type and full/half-duplex.
>But in your case the autonegotiation seems to be ok
>(mii-tool/ethtool output). More specific information you can
>get with the mii-diag and vortex-diag tools. You can find
>these tools at http://www.scyld.com/ethercard_diag.html
>
>There are problems with a cisco switch documented in
>Documentation/networking/vortex.txt for example.
[moved again this pc to the original site]
I have modprobed 3c59x with debug=6 and after
a while (about 100 minutes) this error has been
arised. Here is the log. Doy you see anything
relevant? I don't understand why running an
ifconfig eth2 down/up 'resolves' the issue for
another 100 minutes.
Jun 16 14:01:34 Teti kernel: eth2: interrupt, status 8401, latency 2 ticks.
Jun 16 14:01:34 Teti kernel: eth2: In interrupt loop, status 8401.
Jun 16 14:01:34 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:34 Teti kernel: boomerang_rx(): status 8001
Jun 16 14:01:34 Teti kernel: Receiving packet size 60 status a000803c.
Jun 16 14:01:34 Teti kernel: eth2: exiting interrupt, status 8000.
Jun 16 14:01:34 Teti kernel: eth2: interrupt, status 8401, latency 1 ticks.
Jun 16 14:01:34 Teti kernel: eth2: In interrupt loop, status 8401.
Jun 16 14:01:34 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:34 Teti kernel: boomerang_rx(): status 8001
Jun 16 14:01:34 Teti kernel: Receiving packet size 60 status 803c.
Jun 16 14:01:34 Teti kernel: eth2: exiting interrupt, status 8000.
Jun 16 14:01:36 Teti kernel: eth2: interrupt, status 8401, latency 2 ticks.
Jun 16 14:01:36 Teti kernel: eth2: In interrupt loop, status 8401.
Jun 16 14:01:36 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:36 Teti kernel: boomerang_rx(): status 8001
Jun 16 14:01:36 Teti kernel: Receiving packet size 82 status 60008052.
Jun 16 14:01:36 Teti kernel: eth2: exiting interrupt, status 8000.
Jun 16 14:01:36 Teti kernel: eth2: interrupt, status 8401, latency 2 ticks.
Jun 16 14:01:36 Teti kernel: eth2: In interrupt loop, status 8401.
Jun 16 14:01:36 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:36 Teti kernel: boomerang_rx(): status 8001
Jun 16 14:01:36 Teti kernel: Receiving packet size 60 status 803c.
Jun 16 14:01:36 Teti kernel: eth2: exiting interrupt, status 8000.
Jun 16 14:01:38 Teti kernel: eth2: interrupt, status 8401, latency 2 ticks.
Jun 16 14:01:38 Teti kernel: eth2: In interrupt loop, status 8401.
Jun 16 14:01:38 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:38 Teti kernel: boomerang_rx(): status 8001
Jun 16 14:01:38 Teti kernel: Receiving packet size 60 status 6000803c.
Jun 16 14:01:38 Teti kernel: eth2: exiting interrupt, status 8000.
Jun 16 14:01:39 Teti kernel: NETDEV WATCHDOG: eth2: transmit timed out
Jun 16 14:01:39 Teti kernel: eth2: transmit timed out, tx_status 00 status
8000.
Jun 16 14:01:39 Teti kernel: diagnostics: net 0ccc media 8880 dma 000000a0
fifo 0000
Jun 16 14:01:39 Teti kernel: Flags; bus-master 1, dirty 10411(11) current
10427(11)
Jun 16 14:01:39 Teti kernel: Transmit list 159258e0 vs. d59258e0.
Jun 16 14:01:39 Teti kernel: 0: @d5925200 length 80000086 status 00000086
Jun 16 14:01:39 Teti kernel: 1: @d59252a0 length 800000ec status 000000ec
Jun 16 14:01:39 Teti kernel: 2: @d5925340 length 8000003f status 0000003f
Jun 16 14:01:39 Teti kernel: 3: @d59253e0 length 800000ec status 000000ec
Jun 16 14:01:39 Teti kernel: 4: @d5925480 length 8000003f status 0000003f
Jun 16 14:01:39 Teti kernel: 5: @d5925520 length 800000ec status 000000ec
Jun 16 14:01:39 Teti kernel: 6: @d59255c0 length 8000002a status 0000002a
Jun 16 14:01:39 Teti kernel: 7: @d5925660 length 8000003f status 0000003f
Jun 16 14:01:39 Teti kernel: 8: @d5925700 length 800000ec status 000000ec
Jun 16 14:01:39 Teti kernel: 9: @d59257a0 length 800000ec status 800000ec
Jun 16 14:01:39 Teti kernel: 10: @d5925840 length 800000ec status
800000ec
Jun 16 14:01:39 Teti kernel: 11: @d59258e0 length 8000082a status
0000082a
Jun 16 14:01:39 Teti kernel: 12: @d5925980 length 80000086 status
00000086
Jun 16 14:01:39 Teti kernel: 13: @d5925a20 length 80000037 status
00000037
Jun 16 14:01:39 Teti kernel: 14: @d5925ac0 length 80000036 status
00000036
Jun 16 14:01:39 Teti kernel: 15: @d5925b60 length 8000003f status
0000003f
Jun 16 14:01:39 Teti kernel: eth2: Resetting the Tx ring pointer.
Jun 16 14:01:39 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:01:39 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:39 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:39 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:39 Teti kernel: Receiving packet size 82 status 60008052.
Jun 16 14:01:39 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:41 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:01:41 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:41 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:41 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:41 Teti kernel: Receiving packet size 82 status a0008052.
Jun 16 14:01:41 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:42 Teti kernel: eth2: interrupt, status e401, latency 1 ticks.
Jun 16 14:01:42 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:42 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:42 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:42 Teti kernel: Receiving packet size 82 status a0008052.
Jun 16 14:01:42 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:43 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:01:43 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:43 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:43 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:43 Teti kernel: Receiving packet size 82 status a0008052.
Jun 16 14:01:43 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:44 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:01:44 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:44 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:44 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:44 Teti kernel: Receiving packet size 92 status a000805c.
Jun 16 14:01:44 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:44 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:01:44 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:44 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:44 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:44 Teti kernel: Receiving packet size 243 status a00080f3.
Jun 16 14:01:44 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:45 Teti kernel: eth2: interrupt, status e401, latency 1 ticks.
Jun 16 14:01:45 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:45 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:45 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:45 Teti kernel: Receiving packet size 92 status a000805c.
Jun 16 14:01:45 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:45 Teti kernel: eth2: interrupt, status e401, latency 5 ticks.
Jun 16 14:01:45 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:45 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:45 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:45 Teti kernel: Receiving packet size 60 status 6000803c.
Jun 16 14:01:45 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:45 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:01:45 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:45 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:45 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:45 Teti kernel: Receiving packet size 76 status a000804c.
Jun 16 14:01:45 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:46 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:01:46 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:46 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:46 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:46 Teti kernel: Receiving packet size 92 status a000805c.
Jun 16 14:01:46 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:46 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:01:46 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:46 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:46 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:46 Teti kernel: Receiving packet size 247 status a00080f7.
Jun 16 14:01:46 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:46 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:01:46 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:46 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:46 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:46 Teti kernel: Receiving packet size 247 status a00080f7.
Jun 16 14:01:46 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:46 Teti kernel: eth2: interrupt, status e401, latency 1 ticks.
Jun 16 14:01:46 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:46 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:46 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:46 Teti kernel: Receiving packet size 76 status a000804c.
Jun 16 14:01:46 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:47 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:01:47 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:47 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:47 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:47 Teti kernel: Receiving packet size 82 status 60008052.
Jun 16 14:01:47 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:47 Teti kernel: eth2: interrupt, status e401, latency 1 ticks.
Jun 16 14:01:47 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:47 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:47 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:47 Teti kernel: Receiving packet size 76 status a000804c.
Jun 16 14:01:47 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:48 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:01:48 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:01:48 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:01:48 Teti kernel: boomerang_rx(): status e001
Jun 16 14:01:48 Teti kernel: Receiving packet size 60 status 6000803c.
Jun 16 14:01:48 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:01:49 Teti kernel: NETDEV WATCHDOG: eth2: transmit timed out
Jun 16 14:01:49 Teti kernel: eth2: transmit timed out, tx_status 00 status
e000.
Jun 16 14:01:49 Teti kernel: diagnostics: net 0ccc media 8880 dma 000000a0
fifo 0000
Jun 16 14:01:49 Teti kernel: Flags; bus-master 1, dirty 10411(11) current
10427(11)
Jun 16 14:01:49 Teti kernel: Transmit list 159258e0 vs. d59258e0.
Here is the log when I run ifconfig eth2 down
and ifconfig eth2 up:
Jun 16 14:19:49 Teti kernel: NETDEV WATCHDOG: eth2: transmit timed out
Jun 16 14:19:49 Teti kernel: eth2: transmit timed out, tx_status 00 status
e000.
Jun 16 14:19:49 Teti kernel: diagnostics: net 0ccc media 8880 dma 000000a0
fifo 0000
Jun 16 14:19:49 Teti kernel: Flags; bus-master 1, dirty 10411(11) current
10427(11)
Jun 16 14:19:49 Teti kernel: Transmit list 159258e0 vs. d59258e0.
Jun 16 14:19:49 Teti kernel: 0: @d5925200 length 80000086 status 00000086
Jun 16 14:19:49 Teti kernel: 1: @d59252a0 length 800000ec status 000000ec
Jun 16 14:19:49 Teti kernel: 2: @d5925340 length 8000003f status 0000003f
Jun 16 14:19:49 Teti kernel: 3: @d59253e0 length 800000ec status 000000ec
Jun 16 14:19:49 Teti kernel: 4: @d5925480 length 8000003f status 0000003f
Jun 16 14:19:49 Teti kernel: 5: @d5925520 length 800000ec status 000000ec
Jun 16 14:19:49 Teti kernel: 6: @d59255c0 length 8000002a status 0000002a
Jun 16 14:19:49 Teti kernel: 7: @d5925660 length 8000003f status 0000003f
Jun 16 14:19:49 Teti kernel: 8: @d5925700 length 800000ec status 000000ec
Jun 16 14:19:49 Teti kernel: 9: @d59257a0 length 800000ec status 800000ec
Jun 16 14:19:49 Teti kernel: 10: @d5925840 length 800000ec status
800000ec
Jun 16 14:19:49 Teti kernel: 11: @d59258e0 length 8000082a status
0000082a
Jun 16 14:19:49 Teti kernel: 12: @d5925980 length 80000086 status
00000086
Jun 16 14:19:49 Teti kernel: 13: @d5925a20 length 80000037 status
00000037
Jun 16 14:19:49 Teti kernel: 14: @d5925ac0 length 80000036 status
00000036
Jun 16 14:19:49 Teti kernel: 15: @d5925b60 length 8000003f status
0000003f
Jun 16 14:19:49 Teti kernel: eth2: Resetting the Tx ring pointer.
Jun 16 14:19:49 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:19:49 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:49 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:49 Teti kernel: boomerang_rx(): status e001
Jun 16 14:19:49 Teti kernel: Receiving packet size 60 status 803c.
Jun 16 14:19:49 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:19:49 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:19:49 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:49 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:49 Teti kernel: boomerang_rx(): status e001
Jun 16 14:19:49 Teti kernel: Receiving packet size 60 status 803c.
Jun 16 14:19:49 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:19:50 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:19:50 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:50 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:50 Teti kernel: boomerang_rx(): status e001
Jun 16 14:19:50 Teti kernel: Receiving packet size 60 status 803c.
Jun 16 14:19:50 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:19:51 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:19:51 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:51 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:51 Teti kernel: boomerang_rx(): status e001
Jun 16 14:19:51 Teti kernel: Receiving packet size 71 status a0008047.
Jun 16 14:19:51 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:19:51 Teti kernel: eth2: interrupt, status e401, latency 1 ticks.
Jun 16 14:19:51 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:51 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:51 Teti kernel: boomerang_rx(): status e001
Jun 16 14:19:51 Teti kernel: Receiving packet size 60 status 803c.
Jun 16 14:19:51 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:19:51 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:19:51 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:51 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:51 Teti kernel: boomerang_rx(): status e001
Jun 16 14:19:51 Teti kernel: Receiving packet size 60 status 803c.
Jun 16 14:19:51 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:19:52 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:19:52 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:52 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:52 Teti kernel: boomerang_rx(): status e001
Jun 16 14:19:52 Teti kernel: Receiving packet size 71 status a0008047.
Jun 16 14:19:52 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:19:52 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:19:52 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:52 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:52 Teti kernel: boomerang_rx(): status e001
Jun 16 14:19:52 Teti kernel: Receiving packet size 60 status 803c.
Jun 16 14:19:52 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:19:53 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:19:53 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:53 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:53 Teti kernel: boomerang_rx(): status e001
Jun 16 14:19:53 Teti kernel: Receiving packet size 71 status a0008047.
Jun 16 14:19:53 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:19:53 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:19:53 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:53 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:53 Teti kernel: boomerang_rx(): status e001
Jun 16 14:19:53 Teti kernel: Receiving packet size 60 status 803c.
Jun 16 14:19:53 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:19:54 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:19:54 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:54 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:54 Teti kernel: boomerang_rx(): status e001
Jun 16 14:19:54 Teti kernel: Receiving packet size 92 status a000805c.
Jun 16 14:19:54 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:19:54 Teti kernel: eth2: interrupt, status e401, latency 2 ticks.
Jun 16 14:19:54 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:54 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:54 Teti kernel: boomerang_rx(): status e001
Jun 16 14:19:54 Teti kernel: Receiving packet size 60 status 803c.
Jun 16 14:19:54 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:19:54 Teti kernel: eth2: interrupt, status e401, latency 1 ticks.
Jun 16 14:19:54 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:54 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:54 Teti kernel: boomerang_rx(): status e001
Jun 16 14:19:54 Teti kernel: Receiving packet size 60 status 803c.
Jun 16 14:19:54 Teti kernel: eth2: exiting interrupt, status e000.
Jun 16 14:19:55 Teti kernel: eth2: vortex_close() status e000, Tx status 00.
Jun 16 14:19:55 Teti kernel: eth2: vortex close stats: rx_nocopy 10191
rx_copy 46830 tx_queued 51612 Rx pre-checksummed 52779.
Jun 16 14:19:57 Teti kernel: eth2: Filling in the Rx ring.
Jun 16 14:19:57 Teti kernel: PCI: Found IRQ 7 for device 0000:01:09.0
Jun 16 14:19:57 Teti kernel: eth2: using NWAY device table, not 8
Jun 16 14:19:57 Teti kernel: eth2: Initial media type Autonegotiate.
Jun 16 14:19:57 Teti kernel: eth2: link up, 100Mbps, full-duplex, lpa 0x45E1
Jun 16 14:19:57 Teti kernel: eth2: setting full-duplex.
Jun 16 14:19:57 Teti kernel: eth2: vortex_up() irq 7 media status 8880.
Jun 16 14:19:57 Teti kernel: eth2: interrupt, status e401, latency 1 ticks.
Jun 16 14:19:57 Teti kernel: eth2: In interrupt loop, status e401.
Jun 16 14:19:57 Teti kernel: boomerang_interrupt->boomerang_rx
Jun 16 14:19:57 Teti kernel: boomerang_rx(): status e001
PS: linux is vanilla 2.6.17-rc6
^ permalink raw reply
* Hottest new offer I think, yes. Be delighted with
From: Dan @ 2006-06-16 10:24 UTC (permalink / raw)
To: netdev
Hello Sir,
Enhanced male power and unlimited prowess with your girl The best products for the winning guys
Order our magical stuff now for the amazing prices, and we will dispatch it right away
Millions of people enjoy goods from these brands, and they are more than happy
See our shop: http://www.diomedeacb.com
Just check yourself!
^ permalink raw reply
* Re: [RFC] [patch 0/6] [Network namespace] introduction
From: Eric W. Biederman @ 2006-06-16 9:22 UTC (permalink / raw)
To: Daniel Lezcano; +Cc: serue, haveblue, clg, linux-kernel, netdev
In-Reply-To: <449274A3.5050304@fr.ibm.com>
Daniel Lezcano <dlezcano@fr.ibm.com> writes:
> Eric W. Biederman wrote:
>
> > Have you seen my previous work in this direction?
>> I know I had a much much more complete implementation. The only part
>> I had not completed was iptables support and that was about a days
>> more work.
>
> No, I didn't see your work, is it possible to send me a pointer on it or to have
> a patchset of your code ?
It is in my git tree up on kernel.org. I think it is in my proof-of-concept
branch.
The individual commits tell a tangled tale that is definitely unacceptable
for an upstream merge but the actual result is interesting.
If that isn't enough to find it, tell me and I will track down the details.
It has been a couple months since I posted it during the design discussion
and I'm way overdue for being in bed, tonight.
Eric
^ permalink raw reply
* Re: [RFC] [patch 0/6] [Network namespace] introduction
From: Daniel Lezcano @ 2006-06-16 9:06 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: serue, haveblue, clg, linux-kernel, netdev
In-Reply-To: <m1mzcdpw3i.fsf@ebiederm.dsl.xmission.com>
Eric W. Biederman wrote:
> Have you seen my previous work in this direction?
>
> I know I had a much much more complete implementation. The only part
> I had not completed was iptables support and that was about a days
> more work.
No, I didn't see your work, is it possible to send me a pointer on it or
to have a patchset of your code ?
^ permalink raw reply
* Re: PATCHv3 2.6.17-rc5 tulip free_irq() called too late
From: Jeff Garzik @ 2006-06-16 7:32 UTC (permalink / raw)
To: Grant Grundler; +Cc: Francois Romieu, Valerie Henson, Andrew Morton, netdev
In-Reply-To: <20060616054711.GA28524@colo.lackof.org>
Grant Grundler wrote:
> On Thu, Jun 15, 2006 at 10:30:17PM +0200, Francois Romieu wrote:
>> Afaik free_irq() on a shared irq does not touch the hardware and
>> irqs are anything but synchronous. If free_irq() is issued before
>> the device is idle and its irq are not acked, it's wrong.
>
> Correct. Before calling free_irq(), patch V3 masks interrupts on tulip
> and guarantees the tulip will not generate new interrupts before that call.
Incorrect -- it does not guarantee that tulip will not generate new
interrupt events.
Jeff
^ permalink raw reply
* [ETHTOOL]: Fix UFO typo
From: Herbert Xu @ 2006-06-16 6:39 UTC (permalink / raw)
To: David S. Miller, netdev
[-- Attachment #1: Type: text/plain, Size: 395 bytes --]
Hi Dave:
[ETHTOOL]: Fix UFO typo
The function ethtool_get_ufo was referring to ETHTOOL_GTSO instead of
ETHTOOL_GUFO.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
[-- Attachment #2: ufo-typo.patch --]
[-- Type: text/plain, Size: 637 bytes --]
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 3f269e4..151dd98 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -589,7 +589,7 @@ static int ethtool_set_tso(struct net_de
static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr)
{
- struct ethtool_value edata = { ETHTOOL_GTSO };
+ struct ethtool_value edata = { ETHTOOL_GUFO };
if (!dev->ethtool_ops->get_ufo)
return -EOPNOTSUPP;
@@ -598,6 +598,7 @@ static int ethtool_get_ufo(struct net_de
return -EFAULT;
return 0;
}
+
static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
{
struct ethtool_value edata;
^ permalink raw reply related
* Re: PATCHv3 2.6.17-rc5 tulip free_irq() called too late
From: Grant Grundler @ 2006-06-16 5:47 UTC (permalink / raw)
To: Francois Romieu
Cc: Grant Grundler, Jeff Garzik, Valerie Henson, Andrew Morton,
netdev
In-Reply-To: <20060615203017.GA6724@electric-eye.fr.zoreil.com>
On Thu, Jun 15, 2006 at 10:30:17PM +0200, Francois Romieu wrote:
> Afaik free_irq() on a shared irq does not touch the hardware and
> irqs are anything but synchronous. If free_irq() is issued before
> the device is idle and its irq are not acked, it's wrong.
Correct. Before calling free_irq(), patch V3 masks interrupts on tulip
and guarantees the tulip will not generate new interrupts before that call.
grant
^ permalink raw reply
* Re: [Ubuntu PATCH] Broadcom wireless patch, PCIE/Mactel support
From: Randy Dunlap @ 2006-06-16 5:39 UTC (permalink / raw)
To: Arjan van de Ven; +Cc: lkml, netdev, mb, akpm
In-Reply-To: <1150386115.2987.7.camel@laptopd505.fenrus.org>
Arjan van de Ven wrote:
> On Wed, 2006-06-14 at 16:22 -0700, Randy Dunlap wrote:
>> From: Matthew Garrett <mjg59@srcf.ucam.org>
>>
>> Broadcom wireless patch, PCIE/Mactel support
>>
>> http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=1373a8487e911b5ee204f4422ddea00929c8a4cc
>>
>> This patch adds support for PCIE cores to the bcm43xx driver. This is
>> needed for wireless to work on the Intel imacs. I've submitted it to
>> bcm43xx upstream.
>
>
> who's signing off on these patches??
Well, this particular one isn't going anywhere AFAIK, so it doesn't matter here.
For most of them, Ben Collins or someone else at Ubuntu has signed-off on them
(although not so on this one).
Let's continue the general discussion on the "reviewing" thread.
~Randy
^ permalink raw reply
* Re: [RFC] [patch 0/6] [Network namespace] introduction
From: Eric W. Biederman @ 2006-06-16 4:23 UTC (permalink / raw)
To: dlezcano; +Cc: serue, haveblue, clg, dlezcano, linux-kernel, netdev
In-Reply-To: <20060609210202.215291000@localhost.localdomain>
My apologies for not looking at this earlier I had an email
hickup so I'm having to recreate the context from email archives,
and you didn't copy me.
Have you seen my previous work in this direction?
I know I had a much much more complete implementation. The only part
I had not completed was iptables support and that was about a days
more work.
> The following patches create a private "network namespace" for use
> within containers. This is intended for use with system containers
> like vserver, but might also be useful for restricting individual
> applications' access to the network stack.
>
> These patches isolate traffic inside the network namespace. The
> network ressources, the incoming and the outgoing packets are
> identified to be related to a namespace.
>
> It hides network resource not contained in the current namespace, but
> still allows administration of the network with normal commands like
> ifconfig.
>
> It applies to the kernel version 2.6.17-rc6-mm1
A couple of comments.
> ------------
> - do unshare with the CLONE_NEWNET flag as root
> - do echo eth0 > /sys/kernel/debug/net_ns/dev
> - use ifconfig or ip command to set a new ip address
>
> What is missing ?
> -----------------
> The routes are not yet isolated, that implies:
>
> - binding to another container's address is allowed
>
> - an outgoing packet which has an unset source address can
> potentially get another container's address
>
> - an incoming packet can be routed to the wrong container if there
> are several containers listening to the same addr:port
I haven't looked at the patches in enough detail to see how the network
isolation is being done exactly. But some of these comments and some
of the other pieces I have seen don't give me warm fuzzies.
In particular I did not see a provision for multiple instance of
the loopback device.
As a general rule network sockets and network devices should be attached
to the network namespaces, which basically preserves all of the existing
network stack logic.
Basically this means that the only operations that get more expensive
are reads of global variables, which take a necessary extra indirection.
As a general rule I found that it usually makes sense to add an additional
namespace field to hash tables so they can still use the boot time
memory allocator. Although if you already have a network device as
part of your hash table key that isn't necessary for the network
stack.
Eric
^ permalink raw reply
* Question: query for Interface MIB "ifInNUcastPkts "
From: Wei Dong @ 2006-06-16 3:36 UTC (permalink / raw)
To: netdev
Cc: linux.nics, scott.feldman, jesse.brandeburg, john.ronciak,
auke-jan.h.kok, auke
Hi, All
Now I want to test interface MIB(according to RFC1213), and found that
ifInNUcastPkts doesn't exist in Linux kernel. The kernel maintain a
structure "net_device_stats", but it just contain a member named "multicast"
to show how many multicast packets are received, but no member to show how
many broadcast packets are received. Also, I think ifInNUcastPkts should
equal to broadcast + multicast. Or there is some other statistic value to
show "ifInNUcastPkts"?
RFC1213
INTERNET CONTROL MESSAGE PROTOCOL
ifInNUcastPkts OBJECT-TYP
SYNTAX Counter
ACCESS read-only
STATUS mandatory
DESCRIPTION
"The number of non-unicast (i.e., subnetwork-
broadcast or subnetwork-multicast) packets
delivered to a higher-layer protocol."
::= { ifEntry 12 }
Any help is grateful and thanks in advance.
Regards
Wei Dong
^ permalink raw reply
* Re: [Ubuntu PATCH] Broadcom wireless patch, PCIE/Mactel support
From: Arjan van de Ven @ 2006-06-15 15:41 UTC (permalink / raw)
To: Randy Dunlap; +Cc: lkml, netdev, mb, akpm
In-Reply-To: <44909A3F.4090905@oracle.com>
On Wed, 2006-06-14 at 16:22 -0700, Randy Dunlap wrote:
> From: Matthew Garrett <mjg59@srcf.ucam.org>
>
> Broadcom wireless patch, PCIE/Mactel support
>
> http://www.kernel.org/git/?p=linux/kernel/git/bcollins/ubuntu-dapper.git;a=commitdiff;h=1373a8487e911b5ee204f4422ddea00929c8a4cc
>
> This patch adds support for PCIE cores to the bcm43xx driver. This is
> needed for wireless to work on the Intel imacs. I've submitted it to
> bcm43xx upstream.
who's signing off on these patches??
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox