request_firmware() hotplug interface.
Hi all,
After the feedback on fwfs, here is my new attempt to move the firmware to userspace.
This time there is working hotplug functionality including preliminary firmware.* hotplug scripts.
Attached goes the README and sample driver code for easy inspection and a full tarball for testing.
Have a nice day
Manuel
Signature · 6 lines
--- Manuel Estrada Sainz <[email protected]> <[email protected]> <[email protected]> ------------------------ <[email protected]> ------------------- Let us have the serenity to accept the things we cannot change, courage to change the things we can, and wisdom to know the difference.
request_firmware() hotplug interface:
------------------------------------
This is not finished code, but most of the functionality is already there.
Why:
---
Today, the most extended way to use firmware in the Linux kernel is linking it statically in a header file. Which has political and technical issues:
1) Some firmware is not legal to redistribute.
2) The firmware occupies memory permanently, even though it often is just used once.
3) Some people, like the Debian crowd, don't consider some firmware free enough and remove entire drivers (e.g.: keyspan).
What:
----
My current plan consists on implementing two pieces:
1) A simple interface for drivers to ask for a named piece of firmware via hotplug.
2) A default way to get the firmware from user space into a [virtually] contiguous memory buffer for drivers to use with ease.
- Currently fwfs
Drivers should be able to use 1) without using 2) as shown in firmware_sample_driver.c. In that case arrangements should be made for hotplug scripts to do the firmware load by themselves either via sysfs or some way else.
As much information as possible should be set on the environment so hotplug scripts can do the job when 1) is used without 2). Currently just an string provided by the driver is set as 'DEVICE'. Once ported to 2.5 'struct device' can be used instead and more information will be available.
Notes:
-----
- Even though the Makefile has 2.5 support the code does not. I'll port it once we agree on how all this should be done.
- Why I don't think any more that sysfs is good as "the default" for userspace to provide the firmware:
- For drivers providing a sysfs entry for firmware:
It will be trivial to use request_firmware() and arrange the hotplug scripts to get it copied to their sysfs firmware entry. They don't need any additional support for copying the firmware from userspace.
- For drivers not providing a sysfs entry for firmware:
They just want the appropriate firmware in a memory buffer. It doesn't make much sense to hack some code to get a sysfs entry for them and then tell hotplug where to copy the firmware. The driver won't know that the entry is there, and it won't make sense to write data to it unless requested via hotplug.
If fwfs is finally not found appropriate, I think that a simpler more specific implementation should be better.
- Why OPTIONALLY caching the firmware in-kernel may be a good idea sometimes:
- If the device that needs the firmware is needed to access the filesystem. When upon some error the device has to be reset and the firmware reloaded, it won't be possible to get it from userspace. e.g.:
- A diskless client with a network card that needs firmware.
- The filesystem is stored in a disk behind an scsi device that needs firmware.
- On embedded systems (like install floppies) where there is no userspace hotplug support, 'cp firmware_file /firmware/' can be handy.
And the same device can be needed to access the filesystem or not depending on the setup, so I think that the choice on what firmware to cache should be left to userspace.
- Why register_firmware()+__init can be useful:
- For boot devices needing firmware.
- To make the transition easier:
The firmware can be declared __init and register_firmware() called on module_init. Then the firmware is warranted to be there even if "firmware hotplug userspace" is not there jet or it doesn't jet provide the needed firmware.
Once the firmware is widely available in userspace, it can be removed from the kernel. Or made optional (CONFIG_.*_FIRMWARE).
In either case, if firmware hotplug support is there, it can move the firmware out of kernel memory into the real filesystem for later usage (like the provided hotplug scripts do).
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include "firmware.h"
#define WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE #ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE char __init inkernel_firmware[] = "let's say that this is firmware\n"; #endif
static void sample_firmware_load(char *firmware, int size)
{
printk("firmware_sample_driver: firmware: %s\n", firmware);
}static void sample_probe_default(void)
{
/* uses the default method to get the firmware */
const struct firmware *fw_entry;
printk("firmware_sample_driver: a ghost device got inserted :)\n");
if(request_firmware(&fw_entry, "sample_driver_fw", "ghost0")!=0)
{
printk(KERN_ERR
"firmware_sample_driver: Firmware not available\n");
return;
}
sample_firmware_load(fw_entry->data, fw_entry->size);
release_firmware(fw_entry);
/* finish setting up the device */
}
static void sample_probe_specific(void)
{
/* Uses some specific hotplug support to get the firmware from
* userspace directly into the hardware, or via some sysfs file */
printk("firmware_sample_driver: a ghost device got inserted :)\n");
if(request_firmware(NULL, "sample_driver_fw", "ghost0")!=0)
{
printk(KERN_ERR
"firmware_sample_driver: Firmware load failed\n");
return;
}
/* request_firmware blocks until userspace finished, so at
* this point the firmware should be already in the device */
/* finish setting up the device */
}static int __init sample_init(void)
{
#ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE
register_firmware("sample_driver_fw", inkernel_firmware,
sizeof(inkernel_firmware));
#endif
/* since there is no real hardware insertion I just call the
* sample probe functions here */
sample_probe_specific();
sample_probe_default();
return 0;
}static void __exit sample_exit(void)
{
}
module_init (sample_init);module_exit (sample_exit);
MODULE_LICENSE("GPL");
Quoted 8 lines · Manuel Estrada Sainz
- Why I don't think any more that sysfs is good as "the default" for userspace to provide the firmware:
- For drivers providing a sysfs entry for firmware:
It will be trivial to userequest_firmware()and arrange the hotplug scripts to get it copied to their sysfs firmware entry. They don't need any additional support for copying the firmware from userspace.
With the code in the latest -bk tree, if you simply create a struct class and name it "firmware", and then just create a struct class_device for any struct device that wants firmware to be loaded, you will get a hotplug event generated for you (with the name "firmware") automatically. That is a lot simpler than the firmware.c code you posted.
Quoted 6 lines
- For drivers not providing a sysfs entry for firmware:
They just want the appropriate firmware in a memory buffer. It doesn't make much sense to hack some code to get a sysfs entry for them and then tell hotplug where to copy the firmware. The driver won't know that the entry is there, and it won't make sense to write data to it unless requested via hotplug.
As all devices in the kernel should now be in sysfs (if not, please let me know what busses haven't been converted yet), I think the firmware class is a much simpler way to go. You get the hotplug call for free, and a sysfs entry where the firmware can be dumped to, if you want to do it that way.
thanks,
greg k-h
Quoted 3 lines · Greg KH
As all devices in the kernel should now be in sysfs (if not, please let me know what busses haven't been converted yet),
How about plain old isa?
-Jeff
Quoted 6 lines · Jeff Muizelaar
Quoted 3 lines · Greg KH
As all devices in the kernel should now be in sysfs (if not, please let me know what busses haven't been converted yet),
How about plain old isa?
ISA PnP is converted, I don't think plain isa is. I think a lack of hardware and usage is probably keeping this one from being converted.
thanks,
greg k-h
Hi Greg,
Sorry, for the delay, I wanted to answer already with some code, but I am too outdated on 2.5 development :(, so it will take a while.
Quoted 10 lines · Greg KH
Quoted 8 lines · Manuel Estrada Sainz
- Why I don't think any more that sysfs is good as "the default" for userspace to provide the firmware:
- For drivers providing a sysfs entry for firmware:
It will be trivial to userequest_firmware()and arrange the hotplug scripts to get it copied to their sysfs firmware entry. They don't need any additional support for copying the firmware from userspace.
Quoted 6 lines
With the code in the latest -bk tree, if you simply create a struct class and name it "firmware", and then just create a struct
class_devicefor any struct device that wants firmware to be loaded, you will get a hotplug event generated for you (with the name "firmware") automatically. That is a lot simpler than thefirmware.ccode you posted.
Sounds promising, I'll try to code something on top of that.
Quoted 9 lines
Quoted 6 lines
- For drivers not providing a sysfs entry for firmware:
They just want the appropriate firmware in a memory buffer. It doesn't make much sense to hack some code to get a sysfs entry for them and then tell hotplug where to copy the firmware. The driver won't know that the entry is there, and it won't make sense to write data to it unless requested via hotplug.As all devices in the kernel should now be in sysfs (if not, please let me know what busses haven't been converted yet),
As said, I am outdated on 2.5 development, if I find any while I look at it, I promise to complain.
Quoted 3 lines
I think the firmware class is a much simpler way to go. You get the hotplug call for free, and a sysfs entry where the firmware can be dumped to, if you want to do it that way.
Sounds good.
Thanks
Manuel
PS: Not much new, mainly proving that I'm not ignoring you :), I'm working on it.
Signature · 6 lines
--- Manuel Estrada Sainz <[email protected]> <[email protected]> <[email protected]> ------------------------ <[email protected]> ------------------- Let us have the serenity to accept the things we cannot change, courage to change the things we can, and wisdom to know the difference.