khubd thread and plugging/unplugging a usb device.
Hello,
Usb (4): khubd thread and plugging/unplugging a usb device.
The following text will describe, in short, what happens in the
khubd thread when we plug and unplug a usb device.
Khubd is a daemon thread. After its creation we call daemonize(),
and the daemonize() blocks all signals (see daemonize implementation in /kernel/exit.c) .
We want to be able to send a kill signal (SIGKILL) when cleaning up,
so we enable this by calling allow_signal(SIGKILL) immediately after
it creation.
In fact, the only place where we send this signal is usb_hub_cleanup()
(in hub.c) ; and there are only 2 places where there are calls to this methods in the kernel : one is in usb_init() , which is called when we load usbcore, and when we do not succeed in hub initialization ;
and the second is in usb_exit() , when we unload the usbcore module.
(Both are in core/usb.c). (More on what is usbcore is at the end
of this post).
Usually , when you'll run ps -aux and look at the khubd process,
you will see that it is in a state of sleeping (denoted by the letter 'S').
drivers/usb/core/hub.c is part of usbcore.
Until recently there was a (little) bug (and maybe there still is?)
in
http://www.mail-archive.com/linux-usb-devel@lists.sourceforge.net/msg30070.htmlAndrew Morton says:
"I made the mistake of forgetting to unmount the fat filesystem before
unplugging the USB cable from the digital camera. I then tried to unmount the old mountpoint. khubd is sitting there chewing 100% CPU and I have a reboot in my near future."
And James Bottomley says Mike Christie had fixed it and the fix will soon be integrated.
see:
http://marc.theaimsgroup.com/?l=linux-usb-devel&m=110061842631005&w=2Plugging a USB device:
When we plug in a usb device (like a USB webcam) into the USB port,
the hardware initiates an interrupt; we reach the hub_irq() method.
the hub data (struct usb_hub) is passed to the hub_irq() method as
part of the urb (the context member of struct urb).
There is a global list of hub events(called hub_event_list);
if this list is empty we add event to this list, so that the khubd thread
will handle it.
We also call wake_up(&khubd_wait);
since the khubd is in a waiting status. Waking up causes us to call hub_events().
We also reach the host controller irq (for example, I am working with
ohci and I reach ohci_irq() ) (More on it in the future).
We delete the hub from the event list in hub_events().
(The hub driver writers admit that restarting the list every time to avoid a deadlock with deleting hubs downstream from this current hub is bot the most efficient , but it's safe).
Unplugging a USB device:
When we unplug a USB device (like a webcam) out from it USB port,
the process described earlier is repeated until
we reach hub_events(); there we call hub_port_connect_change() method (implemented in hub.c).
The second parameter of this method is the port number,
So this method disconnect any existing devices under this port,
by calling usb_disconnect(); usb_disconnect(struct usb_device **pdev) is also a usbcore method ,implementation usb.c.
The usb_disconnect() calls usb_disable_device() which disable all the
endpoints for a USB device.
It also removes that USB device endpoints from under /proc/bus/usb/devices by calling usbfs_remove_device(dev);
NOTE: hub_disconnect() is NOT called in this process !!
hub_disconnect() is called when we perform rmmod ohci_hcd , when working with ohci, for example. It is also called in the probing process (in boot); more specifically,hub_probe() calls hub_disconnect() as it's last step,before returning.
And finally,in short, what is usbcore composed of?
The 9 mandatory ingredients of the USBCORE are:
usb.c,hub.c,hcd.c, urb.c, message.c ,config.c, file.c, buffer.c and sysfs.c.
If , when configuring th kernel , you set CONFIG_USB_DEVICEFS to y, add 3 to it:
devio.c inode.c and devices.c.
(the inode.c implements the usbfs ; it has a call
to register_filesystem of the usbfs file system).
Note:
The entries under /sys/usb/usb/drivers/hub
are NOT removed when REMOVED after unplugging a device.
They are removed , for example , after rmmod ohci_hcd. (
assuming that you work with ohci_hcd .)
More on it in the future.
This text is based on 2.67 kernel.
Cheers,
USBLOG