* [PATCH 0/7] Skge driver update
@ 2007-03-16 21:01 Stephen Hemminger
2007-03-16 21:01 ` [PATCH 1/7] skge: deadlock on tx timeout Stephen Hemminger
` (6 more replies)
0 siblings, 7 replies; 11+ messages in thread
From: Stephen Hemminger @ 2007-03-16 21:01 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
Update to skge driver:
1-3 bug fixes for upstream-fixes
4-7 improvements for later releases
--
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/7] skge: deadlock on tx timeout
2007-03-16 21:01 [PATCH 0/7] Skge driver update Stephen Hemminger
@ 2007-03-16 21:01 ` Stephen Hemminger
2007-03-23 5:48 ` Jeff Garzik
2007-03-16 21:01 ` [PATCH 2/7] skge: mask irqs when device down Stephen Hemminger
` (5 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Stephen Hemminger @ 2007-03-16 21:01 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: skge-tx-timeout-deadlock.patch --]
[-- Type: text/plain, Size: 1112 bytes --]
The skge driver will deadlock if gets a transmit timeout
because the netif_tx_lock() is already held.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
---
drivers/net/skge.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- skge-dev.orig/drivers/net/skge.c
+++ skge-dev/drivers/net/skge.c
@@ -2576,7 +2576,11 @@ static int skge_down(struct net_device *
skge_led(skge, LED_MODE_OFF);
netif_poll_disable(dev);
+
+ netif_tx_lock_bh(dev);
skge_tx_clean(dev);
+ netif_tx_unlock_bh(dev);
+
skge_rx_clean(skge);
kfree(skge->rx_ring.start);
@@ -2721,7 +2725,6 @@ static void skge_tx_clean(struct net_dev
struct skge_port *skge = netdev_priv(dev);
struct skge_element *e;
- netif_tx_lock_bh(dev);
for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
struct skge_tx_desc *td = e->desc;
skge_tx_free(skge, e, td->control);
@@ -2730,7 +2733,6 @@ static void skge_tx_clean(struct net_dev
skge->tx_ring.to_clean = e;
netif_wake_queue(dev);
- netif_tx_unlock_bh(dev);
}
static void skge_tx_timeout(struct net_device *dev)
--
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/7] skge: mask irqs when device down
2007-03-16 21:01 [PATCH 0/7] Skge driver update Stephen Hemminger
2007-03-16 21:01 ` [PATCH 1/7] skge: deadlock on tx timeout Stephen Hemminger
@ 2007-03-16 21:01 ` Stephen Hemminger
2007-03-16 21:01 ` [PATCH 3/7] skge: use per-port phy locking Stephen Hemminger
` (4 subsequent siblings)
6 siblings, 0 replies; 11+ messages in thread
From: Stephen Hemminger @ 2007-03-16 21:01 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: skge-noirq-down.patch --]
[-- Type: text/plain, Size: 2585 bytes --]
Wheen a port on the skge driver is not used, it should
mask off interrupts from theat port.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
---
drivers/net/skge.c | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
--- skge-dev.orig/drivers/net/skge.c
+++ skge-dev/drivers/net/skge.c
@@ -105,7 +105,8 @@ static const int txqaddr[] = { Q_XA1, Q_
static const int rxqaddr[] = { Q_R1, Q_R2 };
static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
-static const u32 irqmask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F };
+static const u32 napimask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F };
+static const u32 portmask[] = { IS_PORT_1, IS_PORT_2 };
static int skge_get_regs_len(struct net_device *dev)
{
@@ -2504,6 +2505,11 @@ static int skge_up(struct net_device *de
skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
skge_led(skge, LED_MODE_ON);
+ spin_lock_irq(&hw->hw_lock);
+ hw->intr_mask |= portmask[port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+ spin_unlock_irq(&hw->hw_lock);
+
netif_poll_enable(dev);
return 0;
@@ -2533,6 +2539,13 @@ static int skge_down(struct net_device *
if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
cancel_delayed_work(&skge->link_thread);
+ netif_poll_disable(dev);
+
+ spin_lock_irq(&hw->hw_lock);
+ hw->intr_mask &= ~portmask[port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+ spin_unlock_irq(&hw->hw_lock);
+
skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_stop(skge);
@@ -2575,8 +2588,6 @@ static int skge_down(struct net_device *
skge_led(skge, LED_MODE_OFF);
- netif_poll_disable(dev);
-
netif_tx_lock_bh(dev);
skge_tx_clean(dev);
netif_tx_unlock_bh(dev);
@@ -3051,7 +3062,7 @@ static int skge_poll(struct net_device *
spin_lock_irqsave(&hw->hw_lock, flags);
__netif_rx_complete(dev);
- hw->intr_mask |= irqmask[skge->port];
+ hw->intr_mask |= napimask[skge->port];
skge_write32(hw, B0_IMSK, hw->intr_mask);
skge_read32(hw, B0_IMSK);
spin_unlock_irqrestore(&hw->hw_lock, flags);
@@ -3415,10 +3426,9 @@ static int skge_reset(struct skge_hw *hw
else
hw->ram_size = t8 * 4096;
- hw->intr_mask = IS_HW_ERR | IS_PORT_1;
- if (hw->ports > 1)
- hw->intr_mask |= IS_PORT_2;
+ hw->intr_mask = IS_HW_ERR;
+ /* Use PHY IRQ for all but fiber based Genesis board */
if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC))
hw->intr_mask |= IS_EXT_REG;
--
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/7] skge: use per-port phy locking
2007-03-16 21:01 [PATCH 0/7] Skge driver update Stephen Hemminger
2007-03-16 21:01 ` [PATCH 1/7] skge: deadlock on tx timeout Stephen Hemminger
2007-03-16 21:01 ` [PATCH 2/7] skge: mask irqs when device down Stephen Hemminger
@ 2007-03-16 21:01 ` Stephen Hemminger
2007-03-23 5:49 ` Jeff Garzik
2007-03-16 21:01 ` [PATCH 4/7] skge: ignore unused error interrupts Stephen Hemminger
` (3 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Stephen Hemminger @ 2007-03-16 21:01 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: skge-phy-port.patch --]
[-- Type: text/plain, Size: 9094 bytes --]
Rather than a workqueue and a per-board mutex to control PHY,
use a tasklet and spinlock. Tasklet is lower overhead and works
just as well for this.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
---
drivers/net/skge.c | 82 ++++++++++++++++++++++++++++-------------------------
drivers/net/skge.h | 6 +--
2 files changed, 47 insertions(+), 41 deletions(-)
--- skge-dev.orig/drivers/net/skge.c
+++ skge-dev/drivers/net/skge.c
@@ -672,7 +672,7 @@ static void skge_led(struct skge_port *s
struct skge_hw *hw = skge->hw;
int port = skge->port;
- mutex_lock(&hw->phy_mutex);
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS) {
switch (mode) {
case LED_MODE_OFF:
@@ -743,7 +743,7 @@ static void skge_led(struct skge_port *s
PHY_M_LED_MO_RX(MO_LED_ON));
}
}
- mutex_unlock(&hw->phy_mutex);
+ spin_unlock_bh(&hw->phy_lock);
}
/* blink LED's for finding board */
@@ -1317,7 +1317,7 @@ static void xm_phy_init(struct skge_port
xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl);
/* Poll PHY for status changes */
- schedule_delayed_work(&skge->link_thread, LINK_HZ);
+ mod_timer(&skge->link_timer, jiffies + LINK_HZ);
}
static void xm_check_link(struct net_device *dev)
@@ -1392,10 +1392,9 @@ static void xm_check_link(struct net_dev
* Since internal PHY is wired to a level triggered pin, can't
* get an interrupt when carrier is detected.
*/
-static void xm_link_timer(struct work_struct *work)
+static void xm_link_timer(unsigned long arg)
{
- struct skge_port *skge =
- container_of(work, struct skge_port, link_thread.work);
+ struct skge_port *skge = (struct skge_port *) arg;
struct net_device *dev = skge->netdev;
struct skge_hw *hw = skge->hw;
int port = skge->port;
@@ -1415,13 +1414,13 @@ static void xm_link_timer(struct work_st
goto nochange;
}
- mutex_lock(&hw->phy_mutex);
+ spin_lock(&hw->phy_lock);
xm_check_link(dev);
- mutex_unlock(&hw->phy_mutex);
+ spin_unlock(&hw->phy_lock);
nochange:
if (netif_running(dev))
- schedule_delayed_work(&skge->link_thread, LINK_HZ);
+ mod_timer(&skge->link_timer, jiffies + LINK_HZ);
}
static void genesis_mac_init(struct skge_hw *hw, int port)
@@ -2324,7 +2323,7 @@ static void skge_phy_reset(struct skge_p
netif_stop_queue(skge->netdev);
netif_carrier_off(skge->netdev);
- mutex_lock(&hw->phy_mutex);
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS) {
genesis_reset(hw, port);
genesis_mac_init(hw, port);
@@ -2332,7 +2331,7 @@ static void skge_phy_reset(struct skge_p
yukon_reset(hw, port);
yukon_init(hw, port);
}
- mutex_unlock(&hw->phy_mutex);
+ spin_unlock_bh(&hw->phy_lock);
dev->set_multicast_list(dev);
}
@@ -2355,12 +2354,12 @@ static int skge_ioctl(struct net_device
/* fallthru */
case SIOCGMIIREG: {
u16 val = 0;
- mutex_lock(&hw->phy_mutex);
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS)
err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
else
err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
- mutex_unlock(&hw->phy_mutex);
+ spin_unlock_bh(&hw->phy_lock);
data->val_out = val;
break;
}
@@ -2369,14 +2368,14 @@ static int skge_ioctl(struct net_device
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- mutex_lock(&hw->phy_mutex);
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS)
err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f,
data->val_in);
else
err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f,
data->val_in);
- mutex_unlock(&hw->phy_mutex);
+ spin_unlock_bh(&hw->phy_lock);
break;
}
return err;
@@ -2482,12 +2481,12 @@ static int skge_up(struct net_device *de
goto free_rx_ring;
/* Initialize MAC */
- mutex_lock(&hw->phy_mutex);
+ spin_lock_bh(&hw->phy_lock);
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_mac_init(hw, port);
else
yukon_mac_init(hw, port);
- mutex_unlock(&hw->phy_mutex);
+ spin_unlock_bh(&hw->phy_lock);
/* Configure RAMbuffers */
chunk = hw->ram_size / ((hw->ports + 1)*2);
@@ -2537,7 +2536,7 @@ static int skge_down(struct net_device *
netif_stop_queue(dev);
if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
- cancel_delayed_work(&skge->link_thread);
+ del_timer_sync(&skge->link_timer);
netif_poll_disable(dev);
@@ -3173,28 +3172,29 @@ static void skge_error_irq(struct skge_h
}
/*
- * Interrupt from PHY are handled in work queue
+ * Interrupt from PHY are handled in tasklet (softirq)
* because accessing phy registers requires spin wait which might
* cause excess interrupt latency.
*/
-static void skge_extirq(struct work_struct *work)
+static void skge_extirq(unsigned long arg)
{
- struct skge_hw *hw = container_of(work, struct skge_hw, phy_work);
+ struct skge_hw *hw = (struct skge_hw *) arg;
int port;
- mutex_lock(&hw->phy_mutex);
for (port = 0; port < hw->ports; port++) {
struct net_device *dev = hw->dev[port];
- struct skge_port *skge = netdev_priv(dev);
if (netif_running(dev)) {
+ struct skge_port *skge = netdev_priv(dev);
+
+ spin_lock(&hw->phy_lock);
if (hw->chip_id != CHIP_ID_GENESIS)
yukon_phy_intr(skge);
else if (hw->phy_type == SK_PHY_BCOM)
bcom_phy_intr(skge);
+ spin_unlock(&hw->phy_lock);
}
}
- mutex_unlock(&hw->phy_mutex);
spin_lock_irq(&hw->hw_lock);
hw->intr_mask |= IS_EXT_REG;
@@ -3219,7 +3219,7 @@ static irqreturn_t skge_intr(int irq, vo
status &= hw->intr_mask;
if (status & IS_EXT_REG) {
hw->intr_mask &= ~IS_EXT_REG;
- schedule_work(&hw->phy_work);
+ tasklet_schedule(&hw->phy_task);
}
if (status & (IS_XA1_F|IS_R1_F)) {
@@ -3295,23 +3295,28 @@ static int skge_set_mac_address(struct n
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
- /* disable Rx */
- ctrl = gma_read16(hw, port, GM_GP_CTRL);
- gma_write16(hw, port, GM_GP_CTRL, ctrl & ~GM_GPCR_RX_ENA);
+ if (!netif_running(dev)) {
+ memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN);
+ memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN);
+ } else {
+ /* disable Rx */
+ spin_lock_bh(&hw->phy_lock);
+ ctrl = gma_read16(hw, port, GM_GP_CTRL);
+ gma_write16(hw, port, GM_GP_CTRL, ctrl & ~GM_GPCR_RX_ENA);
- memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN);
- memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN);
+ memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN);
+ memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN);
- if (netif_running(dev)) {
if (hw->chip_id == CHIP_ID_GENESIS)
xm_outaddr(hw, port, XM_SA, dev->dev_addr);
else {
gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
}
- }
- gma_write16(hw, port, GM_GP_CTRL, ctrl);
+ gma_write16(hw, port, GM_GP_CTRL, ctrl);
+ spin_unlock_bh(&hw->phy_lock);
+ }
return 0;
}
@@ -3496,14 +3501,12 @@ static int skge_reset(struct skge_hw *hw
skge_write32(hw, B0_IMSK, hw->intr_mask);
- mutex_lock(&hw->phy_mutex);
for (i = 0; i < hw->ports; i++) {
if (hw->chip_id == CHIP_ID_GENESIS)
genesis_reset(hw, i);
else
yukon_reset(hw, i);
}
- mutex_unlock(&hw->phy_mutex);
return 0;
}
@@ -3551,6 +3554,7 @@ static struct net_device *skge_devinit(s
skge->netdev = dev;
skge->hw = hw;
skge->msg_enable = netif_msg_init(debug, default_msg);
+
skge->tx_ring.count = DEFAULT_TX_RING_SIZE;
skge->rx_ring.count = DEFAULT_RX_RING_SIZE;
@@ -3567,7 +3571,7 @@ static struct net_device *skge_devinit(s
skge->port = port;
/* Only used for Genesis XMAC */
- INIT_DELAYED_WORK(&skge->link_thread, xm_link_timer);
+ setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge);
if (hw->chip_id != CHIP_ID_GENESIS) {
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
@@ -3649,9 +3653,9 @@ static int __devinit skge_probe(struct p
}
hw->pdev = pdev;
- mutex_init(&hw->phy_mutex);
- INIT_WORK(&hw->phy_work, skge_extirq);
spin_lock_init(&hw->hw_lock);
+ spin_lock_init(&hw->phy_lock);
+ tasklet_init(&hw->phy_task, &skge_extirq, (unsigned long) hw);
hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
if (!hw->regs) {
@@ -3737,6 +3741,8 @@ static void __devexit skge_remove(struct
dev0 = hw->dev[0];
unregister_netdev(dev0);
+ tasklet_disable(&hw->phy_task);
+
spin_lock_irq(&hw->hw_lock);
hw->intr_mask = 0;
skge_write32(hw, B0_IMSK, 0);
--- skge-dev.orig/drivers/net/skge.h
+++ skge-dev/drivers/net/skge.h
@@ -2424,8 +2424,8 @@ struct skge_hw {
u32 ram_size;
u32 ram_offset;
u16 phy_addr;
- struct work_struct phy_work;
- struct mutex phy_mutex;
+ spinlock_t phy_lock;
+ struct tasklet_struct phy_task;
};
enum pause_control {
@@ -2457,7 +2457,7 @@ struct skge_port {
struct net_device_stats net_stats;
- struct delayed_work link_thread;
+ struct timer_list link_timer;
enum pause_control flow_control;
enum pause_status flow_status;
u8 rx_csum;
--
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 4/7] skge: ignore unused error interrupts
2007-03-16 21:01 [PATCH 0/7] Skge driver update Stephen Hemminger
` (2 preceding siblings ...)
2007-03-16 21:01 ` [PATCH 3/7] skge: use per-port phy locking Stephen Hemminger
@ 2007-03-16 21:01 ` Stephen Hemminger
2007-03-23 5:58 ` Jeff Garzik
2007-03-16 21:01 ` [PATCH 5/7] skge: transmit locking improvements Stephen Hemminger
` (2 subsequent siblings)
6 siblings, 1 reply; 11+ messages in thread
From: Stephen Hemminger @ 2007-03-16 21:01 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: skge-ignore-unused-errors.patch --]
[-- Type: text/plain, Size: 599 bytes --]
The following hardware error bits only show up on Genesis chipset
and are handled elsewhere, so they can be masked off.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
---
drivers/net/skge.h | 1 -
1 file changed, 1 deletion(-)
--- skge-dev.orig/drivers/net/skge.h
+++ skge-dev/drivers/net/skge.h
@@ -232,7 +232,6 @@ enum {
IS_R2_PAR_ERR = 1<<0, /* Queue R2 Parity Error */
IS_ERR_MSK = IS_IRQ_MST_ERR | IS_IRQ_STAT
- | IS_NO_STAT_M1 | IS_NO_STAT_M2
| IS_RAM_RD_PAR | IS_RAM_WR_PAR
| IS_M1_PAR_ERR | IS_M2_PAR_ERR
| IS_R1_PAR_ERR | IS_R2_PAR_ERR,
--
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 5/7] skge: transmit locking improvements
2007-03-16 21:01 [PATCH 0/7] Skge driver update Stephen Hemminger
` (3 preceding siblings ...)
2007-03-16 21:01 ` [PATCH 4/7] skge: ignore unused error interrupts Stephen Hemminger
@ 2007-03-16 21:01 ` Stephen Hemminger
2007-03-16 21:01 ` [PATCH 6/7] skge: rearrange fields Stephen Hemminger
2007-03-16 21:01 ` [PATCH 7/7] skge: version 1.11 Stephen Hemminger
6 siblings, 0 replies; 11+ messages in thread
From: Stephen Hemminger @ 2007-03-16 21:01 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: skge-prefetch.patch --]
[-- Type: text/plain, Size: 2339 bytes --]
Don't need to lock when processing transmit complete unless queue fills.
Modeled after tg3.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
---
drivers/net/skge.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
--- skge-dev.orig/drivers/net/skge.c
+++ skge-dev/drivers/net/skge.c
@@ -2602,6 +2602,7 @@ static int skge_down(struct net_device *
static inline int skge_avail(const struct skge_ring *ring)
{
+ smp_mb();
return ((ring->to_clean > ring->to_use) ? 0 : ring->count)
+ (ring->to_clean - ring->to_use) - 1;
}
@@ -2690,6 +2691,8 @@ static int skge_xmit_frame(struct sk_buf
dev->name, e - skge->tx_ring.start, skb->len);
skge->tx_ring.to_use = e->next;
+ smp_wmb();
+
if (skge_avail(&skge->tx_ring) <= TX_LOW_WATER) {
pr_debug("%s: transmit queue full\n", dev->name);
netif_stop_queue(dev);
@@ -2707,8 +2710,6 @@ static void skge_tx_free(struct skge_por
{
struct pci_dev *pdev = skge->hw->pdev;
- BUG_ON(!e->skb);
-
/* skb header vs. fragment */
if (control & BMU_STF)
pci_unmap_single(pdev, pci_unmap_addr(e, mapaddr),
@@ -2726,7 +2727,6 @@ static void skge_tx_free(struct skge_por
dev_kfree_skb(e->skb);
}
- e->skb = NULL;
}
/* Free all buffers in transmit ring */
@@ -2998,21 +2998,29 @@ static void skge_tx_done(struct net_devi
skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
- netif_tx_lock(dev);
for (e = ring->to_clean; e != ring->to_use; e = e->next) {
- struct skge_tx_desc *td = e->desc;
+ u32 control = ((const struct skge_tx_desc *) e->desc)->control;
- if (td->control & BMU_OWN)
+ if (control & BMU_OWN)
break;
- skge_tx_free(skge, e, td->control);
+ skge_tx_free(skge, e, control);
}
skge->tx_ring.to_clean = e;
- if (skge_avail(&skge->tx_ring) > TX_LOW_WATER)
- netif_wake_queue(dev);
+ /* Can run lockless until we need to synchronize to restart queue. */
+ smp_mb();
+
+ if (unlikely(netif_queue_stopped(dev) &&
+ skge_avail(&skge->tx_ring) > TX_LOW_WATER)) {
+ netif_tx_lock(dev);
+ if (unlikely(netif_queue_stopped(dev) &&
+ skge_avail(&skge->tx_ring) > TX_LOW_WATER)) {
+ netif_wake_queue(dev);
- netif_tx_unlock(dev);
+ }
+ netif_tx_unlock(dev);
+ }
}
static int skge_poll(struct net_device *dev, int *budget)
--
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 6/7] skge: rearrange fields
2007-03-16 21:01 [PATCH 0/7] Skge driver update Stephen Hemminger
` (4 preceding siblings ...)
2007-03-16 21:01 ` [PATCH 5/7] skge: transmit locking improvements Stephen Hemminger
@ 2007-03-16 21:01 ` Stephen Hemminger
2007-03-16 21:01 ` [PATCH 7/7] skge: version 1.11 Stephen Hemminger
6 siblings, 0 replies; 11+ messages in thread
From: Stephen Hemminger @ 2007-03-16 21:01 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: skge-mem-opt.patch --]
[-- Type: text/plain, Size: 1002 bytes --]
Do some minor rearrangement of data structures to try and optimize
cache usage.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
---
drivers/net/skge.h | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
--- skge-dev.orig/drivers/net/skge.h
+++ skge-dev/drivers/net/skge.h
@@ -2446,15 +2446,15 @@ enum pause_status {
struct skge_port {
- u32 msg_enable;
struct skge_hw *hw;
struct net_device *netdev;
int port;
+ u32 msg_enable;
struct skge_ring tx_ring;
- struct skge_ring rx_ring;
- struct net_device_stats net_stats;
+ struct skge_ring rx_ring ____cacheline_aligned_in_smp;
+ unsigned int rx_buf_size;
struct timer_list link_timer;
enum pause_control flow_control;
@@ -2470,7 +2470,8 @@ struct skge_port {
void *mem; /* PCI memory for rings */
dma_addr_t dma;
unsigned long mem_size;
- unsigned int rx_buf_size;
+
+ struct net_device_stats net_stats;
};
--
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 7/7] skge: version 1.11
2007-03-16 21:01 [PATCH 0/7] Skge driver update Stephen Hemminger
` (5 preceding siblings ...)
2007-03-16 21:01 ` [PATCH 6/7] skge: rearrange fields Stephen Hemminger
@ 2007-03-16 21:01 ` Stephen Hemminger
6 siblings, 0 replies; 11+ messages in thread
From: Stephen Hemminger @ 2007-03-16 21:01 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev
[-- Attachment #1: skge-1.11 --]
[-- Type: text/plain, Size: 443 bytes --]
New version to track changes.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
---
drivers/net/skge.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- skge-dev.orig/drivers/net/skge.c
+++ skge-dev/drivers/net/skge.c
@@ -42,7 +42,7 @@
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "1.10"
+#define DRV_VERSION "1.11"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
--
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/7] skge: deadlock on tx timeout
2007-03-16 21:01 ` [PATCH 1/7] skge: deadlock on tx timeout Stephen Hemminger
@ 2007-03-23 5:48 ` Jeff Garzik
0 siblings, 0 replies; 11+ messages in thread
From: Jeff Garzik @ 2007-03-23 5:48 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
Stephen Hemminger wrote:
> The skge driver will deadlock if gets a transmit timeout
> because the netif_tx_lock() is already held.
>
> Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
applied 1-3 to #upstream-fixes
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 3/7] skge: use per-port phy locking
2007-03-16 21:01 ` [PATCH 3/7] skge: use per-port phy locking Stephen Hemminger
@ 2007-03-23 5:49 ` Jeff Garzik
0 siblings, 0 replies; 11+ messages in thread
From: Jeff Garzik @ 2007-03-23 5:49 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
Stephen Hemminger wrote:
> Rather than a workqueue and a per-board mutex to control PHY,
> use a tasklet and spinlock. Tasklet is lower overhead and works
> just as well for this.
>
> Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Like we give a crap about overhead of PHY code.
This seems like the wrong direction to me, but let's see where this leads.
Jeff
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 4/7] skge: ignore unused error interrupts
2007-03-16 21:01 ` [PATCH 4/7] skge: ignore unused error interrupts Stephen Hemminger
@ 2007-03-23 5:58 ` Jeff Garzik
0 siblings, 0 replies; 11+ messages in thread
From: Jeff Garzik @ 2007-03-23 5:58 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
Stephen Hemminger wrote:
> The following hardware error bits only show up on Genesis chipset
> and are handled elsewhere, so they can be masked off.
>
> Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
>
> ---
> drivers/net/skge.h | 1 -
> 1 file changed, 1 deletion(-)
applied 4-7
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2007-03-23 5:58 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-16 21:01 [PATCH 0/7] Skge driver update Stephen Hemminger
2007-03-16 21:01 ` [PATCH 1/7] skge: deadlock on tx timeout Stephen Hemminger
2007-03-23 5:48 ` Jeff Garzik
2007-03-16 21:01 ` [PATCH 2/7] skge: mask irqs when device down Stephen Hemminger
2007-03-16 21:01 ` [PATCH 3/7] skge: use per-port phy locking Stephen Hemminger
2007-03-23 5:49 ` Jeff Garzik
2007-03-16 21:01 ` [PATCH 4/7] skge: ignore unused error interrupts Stephen Hemminger
2007-03-23 5:58 ` Jeff Garzik
2007-03-16 21:01 ` [PATCH 5/7] skge: transmit locking improvements Stephen Hemminger
2007-03-16 21:01 ` [PATCH 6/7] skge: rearrange fields Stephen Hemminger
2007-03-16 21:01 ` [PATCH 7/7] skge: version 1.11 Stephen Hemminger
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.