summaryrefslogtreecommitdiffstats
path: root/drivers/net/r8169.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/r8169.c')
-rw-r--r--drivers/net/r8169.c91
1 files changed, 52 insertions, 39 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 5598d86380b..45876a854f0 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -66,6 +66,7 @@ VERSION 2.2LK <2005/01/25>
#include <linux/init.h>
#include <linux/dma-mapping.h>
+#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -486,6 +487,7 @@ static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *,
void __iomem *);
static int rtl8169_change_mtu(struct net_device *dev, int new_mtu);
static void rtl8169_down(struct net_device *dev);
+static void rtl8169_rx_clear(struct rtl8169_private *tp);
#ifdef CONFIG_R8169_NAPI
static int rtl8169_poll(struct net_device *dev, int *budget);
@@ -572,8 +574,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr)
{
unsigned int val;
- mdio_write(ioaddr, MII_BMCR, BMCR_RESET);
- val = mdio_read(ioaddr, MII_BMCR);
+ val = mdio_read(ioaddr, MII_BMCR) | BMCR_RESET;
+ mdio_write(ioaddr, MII_BMCR, val & 0xffff);
}
static void rtl8169_check_link_status(struct net_device *dev,
@@ -890,8 +892,7 @@ static void rtl8169_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
unsigned long flags;
spin_lock_irqsave(&tp->lock, flags);
- if (tp->vlgrp)
- tp->vlgrp->vlan_devices[vid] = NULL;
+ vlan_group_set_device(tp->vlgrp, vid, NULL);
spin_unlock_irqrestore(&tp->lock, flags);
}
@@ -1369,11 +1370,7 @@ static inline void rtl8169_request_timer(struct net_device *dev)
(tp->phy_version >= RTL_GIGA_PHY_VER_H))
return;
- init_timer(timer);
- timer->expires = jiffies + RTL8169_PHY_TIMEOUT;
- timer->data = (unsigned long)(dev);
- timer->function = rtl8169_phy_timer;
- add_timer(timer);
+ mod_timer(timer, jiffies + RTL8169_PHY_TIMEOUT);
}
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1686,6 +1683,10 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->mmio_addr = ioaddr;
tp->align = rtl_cfg_info[ent->driver_data].align;
+ init_timer(&tp->timer);
+ tp->timer.data = (unsigned long) dev;
+ tp->timer.function = rtl8169_phy_timer;
+
spin_lock_init(&tp->lock);
rc = register_netdev(dev);
@@ -1733,6 +1734,8 @@ rtl8169_remove_one(struct pci_dev *pdev)
assert(dev != NULL);
assert(tp != NULL);
+ flush_scheduled_work();
+
unregister_netdev(dev);
rtl8169_release_board(pdev, dev, tp->mmio_addr);
pci_set_drvdata(pdev, NULL);
@@ -1750,16 +1753,10 @@ static int rtl8169_open(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
struct pci_dev *pdev = tp->pci_dev;
- int retval;
+ int retval = -ENOMEM;
- rtl8169_set_rxbufsize(tp, dev);
- retval =
- request_irq(dev->irq, rtl8169_interrupt, IRQF_SHARED, dev->name, dev);
- if (retval < 0)
- goto out;
-
- retval = -ENOMEM;
+ rtl8169_set_rxbufsize(tp, dev);
/*
* Rx and Tx desscriptors needs 256 bytes alignment.
@@ -1768,19 +1765,26 @@ static int rtl8169_open(struct net_device *dev)
tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES,
&tp->TxPhyAddr);
if (!tp->TxDescArray)
- goto err_free_irq;
+ goto out;
tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES,
&tp->RxPhyAddr);
if (!tp->RxDescArray)
- goto err_free_tx;
+ goto err_free_tx_0;
retval = rtl8169_init_ring(dev);
if (retval < 0)
- goto err_free_rx;
+ goto err_free_rx_1;
INIT_DELAYED_WORK(&tp->task, NULL);
+ smp_mb();
+
+ retval = request_irq(dev->irq, rtl8169_interrupt, IRQF_SHARED,
+ dev->name, dev);
+ if (retval < 0)
+ goto err_release_ring_2;
+
rtl8169_hw_start(dev);
rtl8169_request_timer(dev);
@@ -1789,14 +1793,14 @@ static int rtl8169_open(struct net_device *dev)
out:
return retval;
-err_free_rx:
+err_release_ring_2:
+ rtl8169_rx_clear(tp);
+err_free_rx_1:
pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
tp->RxPhyAddr);
-err_free_tx:
+err_free_tx_0:
pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
tp->TxPhyAddr);
-err_free_irq:
- free_irq(dev->irq, dev);
goto out;
}
@@ -2161,10 +2165,13 @@ static void rtl8169_reinit_task(struct work_struct *work)
struct net_device *dev = tp->dev;
int ret;
- if (netif_running(dev)) {
- rtl8169_wait_for_quiescence(dev);
- rtl8169_close(dev);
- }
+ rtnl_lock();
+
+ if (!netif_running(dev))
+ goto out_unlock;
+
+ rtl8169_wait_for_quiescence(dev);
+ rtl8169_close(dev);
ret = rtl8169_open(dev);
if (unlikely(ret < 0)) {
@@ -2179,6 +2186,9 @@ static void rtl8169_reinit_task(struct work_struct *work)
}
rtl8169_schedule_work(dev, rtl8169_reinit_task);
}
+
+out_unlock:
+ rtnl_unlock();
}
static void rtl8169_reset_task(struct work_struct *work)
@@ -2187,8 +2197,10 @@ static void rtl8169_reset_task(struct work_struct *work)
container_of(work, struct rtl8169_private, task.work);
struct net_device *dev = tp->dev;
+ rtnl_lock();
+
if (!netif_running(dev))
- return;
+ goto out_unlock;
rtl8169_wait_for_quiescence(dev);
@@ -2210,6 +2222,9 @@ static void rtl8169_reset_task(struct work_struct *work)
}
rtl8169_schedule_work(dev, rtl8169_reset_task);
}
+
+out_unlock:
+ rtnl_unlock();
}
static void rtl8169_tx_timeout(struct net_device *dev)
@@ -2269,7 +2284,7 @@ static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev)
return LargeSend | ((mss & MSSMask) << MSSShift);
}
if (skb->ip_summed == CHECKSUM_PARTIAL) {
- const struct iphdr *ip = skb->nh.iph;
+ const struct iphdr *ip = ip_hdr(skb);
if (ip->protocol == IPPROTO_TCP)
return IPCS | TCPCS;
@@ -2571,7 +2586,6 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
pci_action(tp->pci_dev, le64_to_cpu(desc->addr),
tp->rx_buf_sz, PCI_DMA_FROMDEVICE);
- skb->dev = dev;
skb_put(skb, pkt_size);
skb->protocol = eth_type_trans(skb, dev);
@@ -2722,8 +2736,6 @@ static void rtl8169_down(struct net_device *dev)
netif_stop_queue(dev);
- flush_scheduled_work();
-
core_down:
spin_lock_irq(&tp->lock);
@@ -2877,7 +2889,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
void __iomem *ioaddr = tp->mmio_addr;
if (!netif_running(dev))
- goto out;
+ goto out_pci_suspend;
netif_device_detach(dev);
netif_stop_queue(dev);
@@ -2891,10 +2903,11 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
spin_unlock_irq(&tp->lock);
+out_pci_suspend:
pci_save_state(pdev);
pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
-out:
+
return 0;
}
@@ -2902,15 +2915,15 @@ static int rtl8169_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ pci_enable_wake(pdev, PCI_D0, 0);
+
if (!netif_running(dev))
goto out;
netif_device_attach(dev);
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
- pci_enable_wake(pdev, PCI_D0, 0);
-
rtl8169_schedule_work(dev, rtl8169_reset_task);
out:
return 0;