mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-04-01 22:18:04 +07:00
8139too: RTNL and flush_scheduled_work deadlock
Your usual dont-flush_scheduled_work-with-RTNL-held stuff. It is a bit different here since the thread runs permanently or is only occasionally kicked for recovery depending on the hardware revision. Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
c014f6c8f8
commit
83cbb4d257
@ -1109,6 +1109,8 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
|
|||||||
|
|
||||||
assert (dev != NULL);
|
assert (dev != NULL);
|
||||||
|
|
||||||
|
flush_scheduled_work();
|
||||||
|
|
||||||
unregister_netdev (dev);
|
unregister_netdev (dev);
|
||||||
|
|
||||||
__rtl8139_cleanup_dev (dev);
|
__rtl8139_cleanup_dev (dev);
|
||||||
@ -1603,18 +1605,21 @@ static void rtl8139_thread (struct work_struct *work)
|
|||||||
struct net_device *dev = tp->mii.dev;
|
struct net_device *dev = tp->mii.dev;
|
||||||
unsigned long thr_delay = next_tick;
|
unsigned long thr_delay = next_tick;
|
||||||
|
|
||||||
|
rtnl_lock();
|
||||||
|
|
||||||
|
if (!netif_running(dev))
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
if (tp->watchdog_fired) {
|
if (tp->watchdog_fired) {
|
||||||
tp->watchdog_fired = 0;
|
tp->watchdog_fired = 0;
|
||||||
rtl8139_tx_timeout_task(work);
|
rtl8139_tx_timeout_task(work);
|
||||||
} else if (rtnl_trylock()) {
|
} else
|
||||||
rtl8139_thread_iter (dev, tp, tp->mmio_addr);
|
rtl8139_thread_iter(dev, tp, tp->mmio_addr);
|
||||||
rtnl_unlock ();
|
|
||||||
} else {
|
|
||||||
/* unlikely race. mitigate with fast poll. */
|
|
||||||
thr_delay = HZ / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
schedule_delayed_work(&tp->thread, thr_delay);
|
if (tp->have_thread)
|
||||||
|
schedule_delayed_work(&tp->thread, thr_delay);
|
||||||
|
out_unlock:
|
||||||
|
rtnl_unlock ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rtl8139_start_thread(struct rtl8139_private *tp)
|
static void rtl8139_start_thread(struct rtl8139_private *tp)
|
||||||
@ -1626,19 +1631,11 @@ static void rtl8139_start_thread(struct rtl8139_private *tp)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
tp->have_thread = 1;
|
tp->have_thread = 1;
|
||||||
|
tp->watchdog_fired = 0;
|
||||||
|
|
||||||
schedule_delayed_work(&tp->thread, next_tick);
|
schedule_delayed_work(&tp->thread, next_tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rtl8139_stop_thread(struct rtl8139_private *tp)
|
|
||||||
{
|
|
||||||
if (tp->have_thread) {
|
|
||||||
cancel_rearming_delayed_work(&tp->thread);
|
|
||||||
tp->have_thread = 0;
|
|
||||||
} else
|
|
||||||
flush_scheduled_work();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
|
static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
|
||||||
{
|
{
|
||||||
tp->cur_tx = 0;
|
tp->cur_tx = 0;
|
||||||
@ -1696,12 +1693,11 @@ static void rtl8139_tx_timeout (struct net_device *dev)
|
|||||||
{
|
{
|
||||||
struct rtl8139_private *tp = netdev_priv(dev);
|
struct rtl8139_private *tp = netdev_priv(dev);
|
||||||
|
|
||||||
|
tp->watchdog_fired = 1;
|
||||||
if (!tp->have_thread) {
|
if (!tp->have_thread) {
|
||||||
INIT_DELAYED_WORK(&tp->thread, rtl8139_tx_timeout_task);
|
INIT_DELAYED_WORK(&tp->thread, rtl8139_thread);
|
||||||
schedule_delayed_work(&tp->thread, next_tick);
|
schedule_delayed_work(&tp->thread, next_tick);
|
||||||
} else
|
}
|
||||||
tp->watchdog_fired = 1;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
|
static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
|
||||||
@ -2233,8 +2229,6 @@ static int rtl8139_close (struct net_device *dev)
|
|||||||
|
|
||||||
netif_stop_queue (dev);
|
netif_stop_queue (dev);
|
||||||
|
|
||||||
rtl8139_stop_thread(tp);
|
|
||||||
|
|
||||||
if (netif_msg_ifdown(tp))
|
if (netif_msg_ifdown(tp))
|
||||||
printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n",
|
printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n",
|
||||||
dev->name, RTL_R16 (IntrStatus));
|
dev->name, RTL_R16 (IntrStatus));
|
||||||
|
Loading…
Reference in New Issue
Block a user