Commit 373ed85e authored by Russell King's avatar Russell King Committed by Stephen Hemminger

[netdrvr pcmcia] fix hot unplugging

This patch fixes a deadlock which occurs when a PCMCIA card is
physically removed, and the netdev interface is then downed.

The problem occurs because these drivers delay the call of
unregister_netdev until the netdev is downed.

Since 2.6 now downs the interface on unregister_netdev(), we can
call this function as soon as the card has been removed without
waiting for the netdev to be downed.
parent da11d5bb
...@@ -362,11 +362,8 @@ static void tc574_detach(dev_link_t *link) ...@@ -362,11 +362,8 @@ static void tc574_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
tc574_release(link); tc574_release(link);
if (link->state & DEV_STALE_CONFIG)
return;
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -554,21 +551,11 @@ static void tc574_release(dev_link_t *link) ...@@ -554,21 +551,11 @@ static void tc574_release(dev_link_t *link)
{ {
DEBUG(0, "3c574_release(0x%p)\n", link); DEBUG(0, "3c574_release(0x%p)\n", link);
if (link->open) {
DEBUG(1, "3c574_cs: release postponed, '%s' still open\n",
link->dev->dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq); CardServices(ReleaseIRQ, link->handle, &link->irq);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_CONFIG)
tc574_detach(link);
} }
/* /*
...@@ -1297,8 +1284,7 @@ static int el3_close(struct net_device *dev) ...@@ -1297,8 +1284,7 @@ static int el3_close(struct net_device *dev)
link->open--; link->open--;
netif_stop_queue(dev); netif_stop_queue(dev);
del_timer_sync(&lp->media); del_timer_sync(&lp->media);
if (link->state & DEV_STALE_CONFIG)
tc574_release(link);
return 0; return 0;
} }
......
...@@ -276,11 +276,8 @@ static void tc589_detach(dev_link_t *link) ...@@ -276,11 +276,8 @@ static void tc589_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
tc589_release(link); tc589_release(link);
if (link->state & DEV_STALE_CONFIG)
return;
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -430,21 +427,11 @@ static void tc589_release(dev_link_t *link) ...@@ -430,21 +427,11 @@ static void tc589_release(dev_link_t *link)
{ {
DEBUG(0, "3c589_release(0x%p)\n", link); DEBUG(0, "3c589_release(0x%p)\n", link);
if (link->open) {
DEBUG(1, "3c589_cs: release postponed, '%s' still open\n",
link->dev->dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq); CardServices(ReleaseIRQ, link->handle, &link->irq);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_CONFIG)
tc589_detach(link);
} }
/*====================================================================== /*======================================================================
...@@ -1073,8 +1060,6 @@ static int el3_close(struct net_device *dev) ...@@ -1073,8 +1060,6 @@ static int el3_close(struct net_device *dev)
link->open--; link->open--;
netif_stop_queue(dev); netif_stop_queue(dev);
del_timer_sync(&lp->media); del_timer_sync(&lp->media);
if (link->state & DEV_STALE_CONFIG)
tc589_release(link);
return 0; return 0;
} }
......
...@@ -237,11 +237,8 @@ static void axnet_detach(dev_link_t *link) ...@@ -237,11 +237,8 @@ static void axnet_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
axnet_release(link); axnet_release(link);
if (link->state & DEV_STALE_CONFIG)
return;
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -513,21 +510,11 @@ static void axnet_release(dev_link_t *link) ...@@ -513,21 +510,11 @@ static void axnet_release(dev_link_t *link)
{ {
DEBUG(0, "axnet_release(0x%p)\n", link); DEBUG(0, "axnet_release(0x%p)\n", link);
if (link->open) {
DEBUG(1, "axnet_cs: release postponed, '%s' still open\n",
((axnet_dev_t *)(link->priv))->node.dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq); CardServices(ReleaseIRQ, link->handle, &link->irq);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_CONFIG)
axnet_detach(link);
} }
/*====================================================================== /*======================================================================
...@@ -685,8 +672,6 @@ static int axnet_close(struct net_device *dev) ...@@ -685,8 +672,6 @@ static int axnet_close(struct net_device *dev)
link->open--; link->open--;
netif_stop_queue(dev); netif_stop_queue(dev);
del_timer_sync(&info->watchdog); del_timer_sync(&info->watchdog);
if (link->state & DEV_STALE_CONFIG)
axnet_release(link);
return 0; return 0;
} /* axnet_close */ } /* axnet_close */
......
...@@ -263,11 +263,8 @@ static void com20020_detach(dev_link_t *link) ...@@ -263,11 +263,8 @@ static void com20020_detach(dev_link_t *link)
dev = info->dev; dev = info->dev;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
com20020_release(link); com20020_release(link);
if (link->state & DEV_STALE_CONFIG)
return;
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -439,21 +436,11 @@ static void com20020_release(dev_link_t *link) ...@@ -439,21 +436,11 @@ static void com20020_release(dev_link_t *link)
DEBUG(0, "com20020_release(0x%p)\n", link); DEBUG(0, "com20020_release(0x%p)\n", link);
if (link->open) {
DEBUG(1,"postpone...\n");
DEBUG(1, "com20020_cs: release postponed, device stll open\n");
link->state |= DEV_STALE_CONFIG;
return;
}
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq); CardServices(ReleaseIRQ, link->handle, &link->irq);
link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
if (link->state & DEV_STALE_CONFIG)
com20020_detach(link);
} }
/*====================================================================== /*======================================================================
......
...@@ -332,11 +332,8 @@ static void fmvj18x_detach(dev_link_t *link) ...@@ -332,11 +332,8 @@ static void fmvj18x_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
fmvj18x_release(link); fmvj18x_release(link);
if (link->state & DEV_STALE_CONFIG)
return;
}
/* Break the link with Card Services */ /* Break the link with Card Services */
if (link->handle) if (link->handle)
...@@ -722,17 +719,6 @@ static void fmvj18x_release(dev_link_t *link) ...@@ -722,17 +719,6 @@ static void fmvj18x_release(dev_link_t *link)
DEBUG(0, "fmvj18x_release(0x%p)\n", link); DEBUG(0, "fmvj18x_release(0x%p)\n", link);
/*
If the device is currently in use, we won't release until it
is actually closed.
*/
if (link->open) {
DEBUG(1, "fmvj18x_cs: release postponed, '%s' "
"still open\n", link->dev->dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
/* Don't bother checking to see if these succeed or not */ /* Don't bother checking to see if these succeed or not */
CardServices(ReleaseWindow, link->win); CardServices(ReleaseWindow, link->win);
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
...@@ -740,9 +726,6 @@ static void fmvj18x_release(dev_link_t *link) ...@@ -740,9 +726,6 @@ static void fmvj18x_release(dev_link_t *link)
CardServices(ReleaseIRQ, link->handle, &link->irq); CardServices(ReleaseIRQ, link->handle, &link->irq);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_CONFIG)
fmvj18x_detach(link);
} }
/*====================================================================*/ /*====================================================================*/
...@@ -1250,8 +1233,6 @@ static int fjn_close(struct net_device *dev) ...@@ -1250,8 +1233,6 @@ static int fjn_close(struct net_device *dev)
outb(INTR_OFF, ioaddr + LAN_CTRL); outb(INTR_OFF, ioaddr + LAN_CTRL);
link->open--; link->open--;
if (link->state & DEV_STALE_CONFIG)
fmvj18x_release(link);
return 0; return 0;
} /* fjn_close */ } /* fjn_close */
......
...@@ -257,11 +257,8 @@ static void ibmtr_detach(dev_link_t *link) ...@@ -257,11 +257,8 @@ static void ibmtr_detach(dev_link_t *link)
struct tok_info *ti = (struct tok_info *)dev->priv; struct tok_info *ti = (struct tok_info *)dev->priv;
del_timer_sync(&(ti->tr_timer)); del_timer_sync(&(ti->tr_timer));
} }
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
ibmtr_release(link); ibmtr_release(link);
if (link->state & DEV_STALE_CONFIG)
return;
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -412,13 +409,6 @@ static void ibmtr_release(dev_link_t *link) ...@@ -412,13 +409,6 @@ static void ibmtr_release(dev_link_t *link)
DEBUG(0, "ibmtr_release(0x%p)\n", link); DEBUG(0, "ibmtr_release(0x%p)\n", link);
if (link->open) {
DEBUG(1, "ibmtr_cs: release postponed, '%s' "
"still open\n", info->node.dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq); CardServices(ReleaseIRQ, link->handle, &link->irq);
...@@ -430,9 +420,6 @@ static void ibmtr_release(dev_link_t *link) ...@@ -430,9 +420,6 @@ static void ibmtr_release(dev_link_t *link)
} }
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_CONFIG)
ibmtr_detach(link);
} }
/*====================================================================== /*======================================================================
......
...@@ -551,11 +551,8 @@ static void nmclan_detach(dev_link_t *link) ...@@ -551,11 +551,8 @@ static void nmclan_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
nmclan_release(link); nmclan_release(link);
if (link->state & DEV_STALE_CONFIG)
return;
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -809,21 +806,11 @@ static void nmclan_release(dev_link_t *link) ...@@ -809,21 +806,11 @@ static void nmclan_release(dev_link_t *link)
DEBUG(0, "nmclan_release(0x%p)\n", link); DEBUG(0, "nmclan_release(0x%p)\n", link);
if (link->open) {
DEBUG(1, "nmclan_cs: release postponed, '%s' "
"still open\n", link->dev->dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq); CardServices(ReleaseIRQ, link->handle, &link->irq);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_CONFIG)
nmclan_detach(link);
} }
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
...@@ -990,8 +977,6 @@ static int mace_close(struct net_device *dev) ...@@ -990,8 +977,6 @@ static int mace_close(struct net_device *dev)
link->open--; link->open--;
netif_stop_queue(dev); netif_stop_queue(dev);
if (link->state & DEV_STALE_CONFIG)
nmclan_release(link);
return 0; return 0;
} /* mace_close */ } /* mace_close */
......
...@@ -335,11 +335,8 @@ static void pcnet_detach(dev_link_t *link) ...@@ -335,11 +335,8 @@ static void pcnet_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
pcnet_release(link); pcnet_release(link);
if (link->state & DEV_STALE_CONFIG)
return;
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -790,13 +787,6 @@ static void pcnet_release(dev_link_t *link) ...@@ -790,13 +787,6 @@ static void pcnet_release(dev_link_t *link)
DEBUG(0, "pcnet_release(0x%p)\n", link); DEBUG(0, "pcnet_release(0x%p)\n", link);
if (link->open) {
DEBUG(1, "pcnet_cs: release postponed, '%s' still open\n",
info->node.dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
if (info->flags & USE_SHMEM) { if (info->flags & USE_SHMEM) {
iounmap(info->base); iounmap(info->base);
CardServices(ReleaseWindow, link->win); CardServices(ReleaseWindow, link->win);
...@@ -806,9 +796,6 @@ static void pcnet_release(dev_link_t *link) ...@@ -806,9 +796,6 @@ static void pcnet_release(dev_link_t *link)
CardServices(ReleaseIRQ, link->handle, &link->irq); CardServices(ReleaseIRQ, link->handle, &link->irq);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_CONFIG)
pcnet_detach(link);
} }
/*====================================================================== /*======================================================================
...@@ -1132,8 +1119,6 @@ static int pcnet_close(struct net_device *dev) ...@@ -1132,8 +1119,6 @@ static int pcnet_close(struct net_device *dev)
link->open--; link->open--;
netif_stop_queue(dev); netif_stop_queue(dev);
del_timer_sync(&info->watchdog); del_timer_sync(&info->watchdog);
if (link->state & DEV_STALE_CONFIG)
pcnet_release(link);
return 0; return 0;
} /* pcnet_close */ } /* pcnet_close */
......
...@@ -411,11 +411,8 @@ static void smc91c92_detach(dev_link_t *link) ...@@ -411,11 +411,8 @@ static void smc91c92_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG)
smc91c92_release(link); smc91c92_release(link);
if (link->state & DEV_STALE_CONFIG)
return;
}
if (link->handle) if (link->handle)
CardServices(DeregisterClient, link->handle); CardServices(DeregisterClient, link->handle);
...@@ -1060,13 +1057,6 @@ static void smc91c92_release(dev_link_t *link) ...@@ -1060,13 +1057,6 @@ static void smc91c92_release(dev_link_t *link)
DEBUG(0, "smc91c92_release(0x%p)\n", link); DEBUG(0, "smc91c92_release(0x%p)\n", link);
if (link->open) {
DEBUG(1, "smc91c92_cs: release postponed, '%s' still open\n",
link->dev->dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq); CardServices(ReleaseIRQ, link->handle, &link->irq);
...@@ -1078,9 +1068,6 @@ static void smc91c92_release(dev_link_t *link) ...@@ -1078,9 +1068,6 @@ static void smc91c92_release(dev_link_t *link)
} }
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_CONFIG)
smc91c92_detach(link);
} }
/*====================================================================== /*======================================================================
...@@ -1306,8 +1293,6 @@ static int smc_close(struct net_device *dev) ...@@ -1306,8 +1293,6 @@ static int smc_close(struct net_device *dev)
link->open--; link->open--;
del_timer_sync(&smc->media); del_timer_sync(&smc->media);
if (link->state & DEV_STALE_CONFIG)
smc91c92_release(link);
return 0; return 0;
} /* smc_close */ } /* smc_close */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment