USB Enumeration

The process of identifying the device and setting a unique address is referred as bus enumeration. The enumeration process is handled by the system software on the host and the USB logical layer on the device side. The enumeration process starts when a device is attached to the host and the device gets the power. The USB specification includes simple steps for enumeration.

  1. The USB device is attached to the host, which receives an event indicating a change in the pipe’s status. The USB device is in the powered state, and the port it is attached to is disabled.
  2. The host queries about the change in the bus.
  3. Once the host determines that a new device is attached, it waits for at least 100ms for the device to become stable after power, after which it enables and resets the port.
  4. After a successful reset, the USB device is in a default state and can draw power to a range of 100 mA from VBUS pin.
  5. Once the device is in a default state, the host assigns a unique address to the USB device, which moves the device to an address state.
  6. The host starts communicating with the USB device in the default control pipe and reads the device descriptor.
  7. Subsequently, the host reads the device configuration information
  8. The host selects the configuration, which moves the device to a configured state and makes it ready for use.

Tasklet v/s Bottom Halves v/s Softirq

I spent good time reading the Linux Kernel things this morning. Here is what I found which explains the difference between bottom halves, tasklets and softirqs.

Softirqs and tasklets replaced bottom halves, because bottom halves were a large bottle neck on SMP systems. If a bottom half was running on one CPU no other bottom halves could run on any other CPU. It’s obvious how these would not scale. So here what I understand.
Softirqs and tasklets replaced bottom halves. The difference between softirqs and tasklets, is that a softirq is guaranteed to run on the CPU it was scheduled on, where as tasklets don’t have that guarantee. Also the same tasklet can not run on two separate CPUS at the same time, where as a softirq can. Don’t confuse the tasklet restriction with that of the bottom halves. Two different tasklets can run on two different CPUs, just not the same one.
 I can't argue why we have tasklets (I’m trying to get rid of them ( if you have idea please share with me ) but I'll give the best example of why we have softirqs. That’s the networking code. Say you get a network packet. But to process that packet, it takes a lot of work. If you do that in the interrupt handler, no other interrupts can happen on that IRQ line. That would cause a large latency to incoming interrupts and perhaps you'll overflow the buffers and drop packets. So the interrupt handler only moves the data off to a network receive queue, and returns. But this packet still needs to be processed right away. Before anything else. So it goes off to a softirq for processing. Now you still allow for interrupts to come in. Perhaps the network interrupt comes in again on another CPU. The other CPU can start processing that packet with a softirq on that CPU, even before the first packet was done processing.
See how this can scale well? But the same tasklet can't run on two different CPUs, so it doesn't have this advantage. In fact if a tasklet is scheduled to run on another CPU but is waiting for other tasklets to finish, and you try to schedule the tasklet on a CPU that’s not currently processing tasklets, it will notice that the tasklet is already scheduled to run and not do anything. So tasklets are not so reliable when it comes to latencies. Hence, why I’m working on getting rid of them, since I don't believe they accomplish what people think they do.
 I will discuss more about Bottom halves some other time, then I will discuss about workqueue too. Till then you can explore things from Linux Kernel Development.