hotplug remove vs. device driver close
linas at austin.ibm.com
linas at austin.ibm.com
Fri Jun 4 08:25:03 EST 2004
Greg,
My apologies, I think I needed to read the source before posting to the
mailing list. (yes, my middle name really is 'Luke', no kidding). I might have
been on a wild goose chase. See below.
On Thu, Jun 03, 2004 at 01:02:27PM -0700, Don Fry wrote:
> > >
> > > The pcnet32 driver tries to do the 'right thing' when it reads 0xffff,
> > > but that does not include doing a 'close' prior to being removed. The
> > > driver could keep some state around so that if its remove routine was
> > > called without close first, it would cleanup, but I don't know of any
> > > network driver that does this.
> >
> > What I get out of this thread is that pcnet32, and in fact, all drivers,
> > should keep sufficient state around so that close() can be called either
> > after or before remove().
>
> Today in 2.6.6 if I try and do a rmmod pcnet32 and something is still using
> the device, the rmmod will wait until the device is closed, and then it
> goes away.
Where? pcnet32_cleanup_module() doesn't seem to wait for anything.
However, I'm reading the source, tracing through a power-off, and I don't
see any device driver memory leaks, at least not in the 'typical' pcnet32
driver. What I do see is that the the device driver close() routine is
called before the device driver memory is released.
Anatomy of a device remove,
---------------------------
starting with an
echo 1 > /sysfs/bus/ .. power file ...
I trace this through the ppc64 rpaphp hotplug code, and the pcnet32 code.
I did this manually, I hope there aren't any mistakes.
power_write_file () // in /drivers/pci/hotplug/pci_hotplug_core.c
{
calls
slot->ops->disable_slot() which is just
struct hotplug_slot_ops ->disable_slot() which is just
disable_slot (struct hotplug_slot *) // in /drivers/pci/hotplug/rpaphp_core.c
{
which calls
rpa_php_unconfig_pci_adapter (struct slot *) // in rpaphp_pci.c
{
calls
pci_remove_bus_device (struct pci_dev *) // in /drivers/pci/remove.c
{
calls
pci_destroy_dev (struct pci_dev *)
{
calls
device_unregister (&dev->dev) // in /drivers/base/core.c
{
calls
device_del (struct device *)
{
calls
bus_remove_device() // in /drivers/base/bus.c
{
calls
device_release_driver()
{
calls
struct device_driver->remove() which is just
pci_device_remove() // in /drivers/pci/pci_driver.c
{
calls
struct pci_driver->remove() which is just
pcnet32_remove_one() // in /drivers/net/pcnet32.c
{
calls
unregister_netdev() // in /net/core/dev.c
{
calls
dev_close() // in /net/core/dev.c
{
calls dev->stop();
which is just pcnet32_close() // in pcnet32.c
{
which does what you wanted
to stop the device
}
}
}
which
frees pcnet32 device driver memory
}
}}}}}}
** Sent via the linuxppc64-dev mail list. See http://lists.linuxppc.org/
More information about the Linuxppc64-dev
mailing list