0
votes

I have recently been reading about Linux Driver and Device Model. I wanted to understand how the following works in linux in the driver subsystem. So lets say my device tree looks as follows

enter image description here

To be concrete lets assume Bus1 is a PCI bus, Bus2 is ISA and Bus3 is USB. Buses are connected with each other using bridges.

Linux will identify this device tree through the enumeration process and through enumeration and probing mechanism suitable usb driver for terminal device would be identified.

Now lets assume a Tx operation to this terminal device. The terminal device usb driver would end up doing a urb_submit(dev, write_buffer).

My question is in order for the URB to reach the terminal device, theoretically it would have to be enveloped in Bus2 and Bus1 envelopes. So theoretically speaking the outgoing packet has to look something like this

enter image description here

So at some after the urb_submit happens in the driver, does some kernel code walk up the device tree structure and invoke the bus drivers in order (bus 2 driver and then bus 1 driver) to create this envelope structure.

Can anyone point me to the code in the linux kernel where this happens? I tried to follow urb_submit but could not figure this out.

Thanks a bunch!

1
You need to separate hardware layer from software. For example, xHCI driver handles USB bus on x86 thru PCI address space (MMIO and configuration). USB interface driver utilizes APIs from USB core and has no idea what controller is beneath it. USB core provides an API to operate on USB bus layer.0andriy

1 Answers

0
votes

For device drivers that have memory-mapped registers, the device's private data struct contains the addresses assigned by enumeration for each device and they directly write to the registers.

For device drivers that go through layers, as you describe above, the enumeration tells each driver who its parent is, and the driver saves this in its private data when it is instantiated. Then the read or write call of the driver formats the request properly for the device type and invokes the read or write method of the parent driver. For example, a USB disk read might call the read method in the file_operations block of its parent which would be https://elixir.bootlin.com/linux/v4.19.107/source/drivers/usb/core/devio.c#L2614