* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).