Re: [PATCH 9/9] thunderbolt: Add support for USB4STREAM

Greg KH
2026-04-28T13:55:35Z

On Tue, Apr 28, 2026 at 02:03:14PM +0200, Mika Westerberg wrote:
> On Tue, Apr 28, 2026 at 05:57:37AM -0600, Greg KH wrote:
> > On Tue, Apr 28, 2026 at 09:22:09AM +0200, Mika Westerberg wrote:
> > > Introduce USB4STREAM protocol and Linux implementation. This allows two
> > > (or more) hosts to transfer data directly over Thunderbolt/USB4 cable
> > > through a character device without need to go through the network stack.
> > >
> > > Any application that supports read(2) and write(2) in some form should
> > > be able to use the device without changes. The data is sent out to the
> > > other side over a tunnel inside Thunderbolt/USB4 fabric. The character
> > > device is called /dev/tbstreamX where X is the minor number starting
> > > from 0.
> > >
> > > All stream devices need to be configured first. This is done through
> > > ConfigFS interface. There can be multiple streams at the same time (this
> > > depends on number of DMA rings and available HopIDs) and a single stream
> > > supports traffic in both directions. For example there could be an
> > > application that uses one stream as control channel and another one as
> > > bi-directional data channel.
> > >
> > > A real use-case for this is to take a backup as a part of recovery
> > > initramfs tooling (no need to setup networking or have ssh or similar
> > > tooling as part of the initramfs). Say we want to backup the disk of
> > > host1 to host2. First Thunderbolt/USB4 cable is connected between the
> > > hosts (there can be devices in the middle too) then the receiving side
> > > configures the stream:
> > >
> > > host2 # mkdir /sys/kernel/config/thunderbolt/stream/0-1.0
> > > host2 # mkdir /sys/kernel/config/thunderbolt/stream/0-1.0/backup
> > > host2 # echo -1 > /sys/kernel/config/thunderbolt/stream/0-1.0/backup/in_hopid
> > > host2 # echo -1 > /sys/kernel/config/thunderbolt/stream/0-1.0/backup/out_hopid
> > >
> > > We use automatic HopID allocation (writing -1 to HopIDs) for simplicity.
> > > >From this point forward the /dev/tbstream0 can be used pretty much as
> > > regular file:
> > >
> > > host2 # dd if=/dev/tbstream0 of=/tmp/host1.nvme0n1.backup-$(date +%F) bs=256k
> > >
> > > The host that is being backed up then configures the stream accordingly:
> > >
> > > host1 # mkdir /sys/kernel/config/thunderbolt/stream/0-503.0
> > > host1 # mkdir /sys/kernel/config/thunderbolt/stream/0-503.0/backup
> > >
> > > Here we take advantage of the fact that host2 also announces the active
> > > streams through XDomain properties so the name "backup" gives us the
> > > HopIDs. It is also possible to configure them manually in the same way
> > > we did for host2.
> > >
> > > Then it is just a matter of copying the data over:
> > >
> > > host1 # dd if=/dev/nvme0n1 of=/dev/tbstream0 bs=256k
> > >
> > > Similarly it is possible to transfer parts of the filesystem. For
> > > example copy contents of mydir over to the host2:
> > >
> > > host2 # gunzip < /dev/tbstream0 | tar xf -
> > > host1 # tar cf - mydir | gzip > /dev/tbstream0
> > >
> > > Other end of the spectrum use-case is "borrowing" laptop (host1) camera
> > > to desktop (host2):
> > >
> > > host2 # gst-launch-1.0 filesrc location=/dev/tbstream0 ! jpegdec ! videoconvert ! \
> > > autovideosink
> > >
> > > host1 # gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw,width=1920,height=1080 ! \
> > > jpegenc quality=90 ! filesink location=/dev/tbstream0
> > >
> > > Once the streams are no longer needed they can be removed:
> > >
> > > host1 # cd /sys/kernel/config/thunderbolt/stream/
> > > host1 # rmdir -p 0-503.0/backup
> > >
> > > host2 # cd /sys/kernel/config/thunderbolt/stream
> > > host2 # rmdir -p 0-1.0/backup
> >
> > Very cool, but shouldn't the above be in some documentation somewhere so
> > that people know how to use it?
>
> Sure, I can add it part of the Documentation/admin-guide/thunderbolt.rs for
> example.
>
> > And why do you need a whole major for this, why not just use a misc
> > device that it dynamically created for every new dev?
>
> We do use this:
>
> ret = alloc_chrdev_region(&tbstream_devt, 0, TBSTREAM_DEV_MINORS,
> "tbstream");
>
> that should be dynamically allocated, no?

Yes, but you are using up a whole major number for this, and in reality
there's only going to be 1-2, maybe 4, different devices needed at once,
right? So just use the miscdev interface instead?

thanks,

greg k-h