All right, the next talk is a lot of words about how devices modelled in Linux, but please.
Hi, so I review mostly driver code and I realize that sometimes there seems to be some confusion on what different types of firmware notes are and what they are at all.
So I decided to deliver this talk, I'm going to do a short recap of the driver model, how we discussed how we did things in the past and how we're doing them now.
I work for Qualcomm and I maintain a couple of things in the Linux and my work revolves mostly on my own.
So the driver model, the driver model was created to abstract the code that is common to all device drivers and Linux, and we have three principles or actors.
We have the device, we have the driver and bus.
So devices represented in the kernel by struct, by structure called struct device, and this is the logical representation of a hardware component.
Not necessarily one to one, we can have multiple struct devices representing a single component or the other way around.
We can have logical struct devices for where there are no real actual discrete hardware components.
We have the driver driver is a set of instructions telling Linux how to deal and how to control a device.
And finally we have the bus, and bus is the entity whose task is to manage, matching and attaching devices to drivers.
A driver always has to have a bus type assigned, and a bus can actually be a device driver that exports a bus that manages a different type of device drivers.
How does Qualcomm practice? So we have a bus and it contains two lists and maintains a device list and a driver list.
And when a driver appears, so let's populate the driver list with some drivers, this is equivalent to registering your driver in a kernel module, and then a device appears.
So what the bus will try to do, it will try to match the device, the new device with every driver.
So let's try driver zero, didn't match, let's try the second one, okay, this one match.
So that means that this driver can actually control this device.
So the next step is attaching the device to the driver. So we do something that we refer to as probing.
We try to attach the device to the driver and it works.
So that means that this driver and this device can work together. So we consider now the driver, the device to be bound to the driver.
So let's consider another device that appears on the bus.
We try again, we try to match it. It doesn't match. Try to match it with a second driver. Okay, now it matches.
Let's try to probe it. Oh, no, it doesn't work. Probably for what does mean? This means that this driver, this device and this driver can work together, but there's something missing some resource.
So we put it into a queue and we wait for more devices to appear. Okay, we have another device.
This one matches, this one probes. And now we can try to reprobe the device that was previously different.
Okay, now it works. So something provided by device number two was needed by device number one.
And if we add another driver, what we do will do, we will just go through the list of existing devices and try to match them.
Okay, so how are devices that don't just automatically appear on the bus can be discovered and instantiate in the Linux kernel?
So for that we use something called the platform bus and also some other more exotic buses, but that's for another.
That's that's not really for another talk. So what is the platform bus? The platform devices are the devices that you cannot really discover.
You need to describe them in the firmware. And this will be typically the low level devices on your system.
And why do they need to be described? Because let's imagine that you have the same device used in different on different boards and they are wire differently.
Or even you have the same IT you reused in different SOCs, but they are implemented in a bit different way.
So Linux needs to know what register range to map for a device or which clock to enable or which regulator GPI or what not.
And the platform driver just says not me this or give me this and able this.
And it wouldn't be very portable if that driver tries to actually access the system registers. So we abstract that away.
Because there is no problem in computer science that cannot be fixed with another layer of abstraction.
So how do you reuse the same platform driver, the same device that just wired a bit differently on a different system.
So we do along with the device driver, sorry, along with the device, we also need to pass some information describing it to the driver.
How did we do that historically?
Before we had a thing called device 3 we used to use board files.
Of course there were other ways, but I have an ARM BIAS and X86 faultful probably remember different mechanisms.
So this is your typical ARM board file. And what you do, you have some resources, you have some platform data, you have the definition of the device and then you register it in code.
But this comes with a lot of problems. So when you do that in C code, you have strict ordering, no parallelization.
You mix harder description with functional logic and you have a lot of hand coded dependencies, random callbacks all over the place.
Adding anything new, sometimes requires reordering, debugging and whatnot.
And while some things were done right and an example is the track resource which exists has existed for decades and still exists and is still used.
Some things didn't age very well among them platform data. So how did it work?
Each platform driver would define its own custom structure and board files would fill that structure in and pass it to along on the device to the driver.
And that would be quite repetitive. You would have hundreds of different platform data structures.
But what they store are typically integers and strings and possibly also pointers to callbacks that would be defined in the board files and would be responsible for setting up clock regulators and whatnot.
So the latter, that has mostly been abstracted away into driver substance subsistence nowadays.
And if what you're left with is mostly integers and strings, then it probably can be done better.
And third device three.
So device three is called a device three because the device a cyclic directed graph wasn't a very sexy name.
This is a data structure that has both text and binary format and this platform's hardware.
And we have a compiler dedicated called device to compiler DTC that is used to translate between the two formats.
And notes in device three are ordered in a parent child fashion and also talking from a root.
And we also can reference notes from other notes using what we call p handles.
This is just a bit of a device three in text format.
You have your properties. You have your references to other notes.
You can use the so-called hash properties to define, for instance, number of expected p handle arguments.
You have your child notes. And there are also some more advanced concepts like drafts and whatnot.
But in Linux, in general, all upstream device resources should conform with.
With device three bindings, which are YAML documents that define expected properties, their format meaning and whatnot.
And Linux, at boot, it parses the binary form of device three and creates a tree in memory or a cyclic directed graph in memory of structures called device notes.
And also exposes a set of interfaces for accessing this data from drivers.
So when you have the example that we had before, you can use the functions in the kernel that use the OS prefix for accessing the data strings, integers, lists, p handles.
And you can iterate over child notes.
So now this is not the only data format that uses notes and concepts like children references to other notes and whatnot.
So we have this, but we also have a CPI, which isn't the same, but can we use a certain number of concepts.
And we have software notes about which I'm going to be talking in a minute.
So they're powered by their power combined. We created something that is called the firmer note interface.
So this is just a generalization of this firmer description.
And if you want to generalize your off-centric system to firmer notes, your device note will become an FW note handle.
P handles become references, graphs from graphs and graphs.
And users drivers can freely translate between the two using the provided interfaces.
So if we go back to our example, instead of using the OS interfaces, if we translate our device note to the firmer note, we now can use the FW note properties to, for most parts do all the same operations.
They are not one to one, and there's some functionality in firmer note that is missing from, sorry, in of OS notes that is missing from the firmer notes, but for most part they can be used.
What are software notes? So some devices don't have real firmer notes associated with them or they are incomplete.
So this is where you can fill in those gaps in software.
Software notes are basically C structure that are defined statically and they are registered at runtime, and they also have a parent shot relationship.
You can also reference other notes.
And if you look at that and you tell to yourself, well, this is just platform data with extra steps, then you are right, but also with this, we have the abstraction that allows drivers to use the same code to access data defined in firmer and in software.
And can we have both, can we mix the two OF notes or ACPI notes and software notes? Yes, we have a concept called secondary firmer notes where a firmer note can have an additional reference to, to a software note from which we can complete its information about the device.
So so far, we've been talking about mostly about the parent shot relationship, but we also have to talk more about sibling relationships or other maybe supplier consumer.
So let's imagine that we have a system where we have a Mac and this Mac needs to function and say phi and a clock.
So the Mac and the clock are the children of the SOC and the clock we can consider the supplier to the internet Mac and same phi.
But the thing is that if the phi and the clock is not there, then there is no reason to even try to probe the Mac.
That's why we have a thing where from the firmer information like device 3, we can infer what the relationships between the device are, who is supplier of whom and we can actually make sure that we don't pass that we don't try to probe the Mac before we have successfully probe the phi and the clock.
So if you look at all those interfaces that we have, like to give you an example, there is this thing called recurrent laryngeal nerve in our bodies which is a nerve that controls the larynx, the speech and it goes from your brain all the way under the hour time and then all the way back.
And if you consider an animal like giraffe with a very long neck, it actually does go all the way down and all the way up.
This is the result of evolution which is just good enough and it isn't an intelligent design.
So it's the same with the kernel. The interfaces have evolved, evolved over many, many years and through many iterations and not all of them were done perfectly from the get go.
So this is why we have so many different interfaces. If we did it from the start now, we would probably have ended up with a single firmer note interface, but we have all these other interfaces as well that we mix.
So to explain why the kernel is a bit like a giraffe programming guide. If you're writing a kernel driver, which interfaces do use.
If you have a struck device and you don't need to do anything complex like resolving references to other notes use the interfaces that start with device underscore they go to the firmer note and they are the highest fraction layer for retreating information for devices.
If you take the example from before, this is what interfaces you can use to retrieve the information from that piece of device to use firmer note APIs.
If you need to, if your device note has children that carry important information, you may need to iterate over the child firmer note.
This is where you start using the FW note API. Also you may need to extract information from a note that is not associated with an actual device doesn't exist yet.
When to use the very low level API like the OF functions, you may need to iterate over all the properties of a firmer note that's not possible or not possible yet.
And also you may need, if you may need to set up software notes, for software notes you need to set them up before you register up here register them.
Before you register them, you refer to them as software notes using their low level APIs.
If the register they become full firmer notes and this is where you should switch to the higher level API.
So this is like something like this device underscore, it's better than FW note than FW note or FW note and ACPI so the low level APIs.
Yeah, that's it. Sorry, I have to bring really fast because I wanted to fit into their hands.
All right, questions.
So since there are some drivers that needs to take information from software as a firmer note, is that possible that more drivers have to adopt the firmer note, the conventional instead of
the OF note or the ACPI note, if for example in some devices, can run ACPI have ACPI and the device tree, for example, is it possible to transform the drivers to use either ACPI and what is the situation now in the kernel for those drivers.
So if you are writing a new driver, there's no reason to use OF interfaces. You should use either the device or as a second option, the firmer note interface.
If you're writing a new driver, even if it's OF only for now, there's no reason to not use the firmer note abstraction.
And if you need to enable firmer note abstraction and an OF centric driver, then yeah, that's the way to do it.
Maybe a bit a little out of topic, but is support for MacFise really there?
Because it was a new example, but I thought all week with a FI driver for another FI, not probing before it's consumer, so the Mac.
I saw something on the lore about this leveling, not really working for MacFise.
Oh, I don't have an answer, but I will find out.
Hi, God. So good presentation. I like that you made it eventually.
Not really the equation, but one additional information maybe to audience and to you as well.
There is an activity for this big devices like DSAs and PCAx extension cards with full computer on them.
That week could run on ASAP by the system, so actually we could run device three overways.
And when you say about or have specific APIs, in some cases it's used even in ACP enabled systems.
So it's really interesting case to maybe mention.
I will update the talkifier, we do it.
Possibly a last question, thank you.
Based on what you mentioned, I understand that the FW interface can do anything that the OS is not anything.
I mentioned there are a couple of things that they cannot do.
It can do no.
So does this mean the OS one would eventually be replaced by the other entirely?
So I don't think so, but for most use cases it probably could.
But there's no chance of deprecating the other one.
Well, there are still things that we do like device three overways dynamic or F notes and what not that we'll probably have to keep it around.
I think but I don't think we can entirely get rid of it, but probably we can use FW note interface.
In most use cases, normal use cases not doing anything over the complex.
All right, thank you very much.