firmware: add new extensible firmware API - driver_data
The firmware API has evolved over the years slowly, as it
grows we extend it by adding new routines or at times we extend
existing routines with more or less arguments. This doesn't scale
well, when new arguments are added to existing routines it means
we need to traverse the kernel with a slew of collateral
evolutions to adjust old driver users. The firmware API is also
now being used for things outside of the scope of what typically
would be considered "firmware", an example here is the p54 driver
enables users to provide a custom EEPROM through this interface.
Another example is optional CPU microcode updates. This list is
actually quite endless...
There are other subsystems which would like to make use of the
APIs for similar things and its clearly not firmware, but have different
requirements and criteria which they'd like to be met for the
requested file. If different requirements are needed it would
again mean adding more arguments and making a slew of collateral
evolutions, or adding yet-another-new-API-call (TM).
Another sticking point over the current firmware API is that
some callers may need the firmware fallback mechanism when its
enabled. There are two types of fallback mechanisms and both have
shortcomings. This new API accepts the current status quo and
ignore the fallback mechanism all together. When and if we add
support for it, it will be well though out.
This new extensible firmware API enables new extensions to be added by
avoiding future unnecessary collateral evolutions as this code /
features get added. This new set of APIs leaves the old firmware API
as-is, ignores all firmware fallback mechanism, labels the new
API to reflect its broad use outside of the scope of firmware: driver
data helpers, and builds on top of the original firmware core code.
We purposely try to limit the scope of changes in this new API to
simply enable a flexible API to start off with.
The new extensible "driver data" set of helpers accepts that there
really are only two types of requests for accessing driver data:
a) synchronous requests
b) asynchronous requests
Both of these requests may have a different set of requirements which
must be met. These requirements can simply be passed as a struct
drvdata_req_params to each type of request. This struct can be extended
over time to support different requirements as the kernel evolves.
Using the new driver data helpers is only necessary if you have
requirements outside of what the existing old firmware API accepts
or alternatively if you want to ensure to avoid the old firmware
fallback mechanism at all times, regardless of what kernel your driver
might run in.
Developers with new uses should extend the new new struct drvdata_req_params
and driver data code to provide support for new features.
A *few* simple features added as part of the new set of driver data
request APIs, other than making the new API easily extensible for
the future:
- The firmware fallback mechanism is currenlty always ignored
- By default the kernel will free the driver data file for you after
your callbacks are called, you however are allowed to request that
you wish to keep the driver data file on the descriptor. The new
drvdata API is able to free the drvdata file for you by requiring a
consumer callback for the driver data file.
- You no longer need to declare and use your own completions, you
can replace your completions with drvdata_synchronize_request() using
the async_cookie set for you by drvdata_file_request_async(). When
drvdata_file_request_async() completes you can rest assured all the
work for both triggering, and processing the drvdata using any of
your callbacks has completed.
- Allow both asynchronous and synchronous request to specify that driver data
files are optional. With the old APIs we had added one full API call,
request_firmware_direct() just for this purpose -- although it should be
noted another one of its goal was to also skip the fallback mechanisms.
The driver data request APIs allow for you to annotate that a driver
data file is optional for both synchronous or asynchronous requests
through the same two basic set of APIs.
- The driver data request APIs currently match the old synchronous firmware
API calls to refcounted firmware_class module, but it should be easy
to add support now to enable also refcounting the caller's module
should it be be needed. Likewise the driver data request APIs match the
old asynchronous firmware API call and refcounts the caller's module.
v6 changes:
o Bike shedding:
o drvdata/driver_data
v5 changes:
o Bike shedding:
o sysdata/drvdata
o sysdata_req_desc/drvdata_req_params
o Documentation conversion to Sphinx
v4 changes:
o Add SYSDATA_KEEP_SYNC() and SYSDATA_KEEP_ASYNC() macro helpers,
drivers that want to keep the firmware are pretty common, however
note that if we can figure out a way to avoid having drivers
deal with releasing the firmware we're better off, that however
can be an additional change to look forward to.
o 0-day-bot make htmldocs warning fixes
o When developing and testing the sysdata test driver I ended up
running into tons of hairball code just to be able to come up
with enough code to be able to tweak all possible knobs using
a userspace test interface. This begged for a cleaner API and
in testing found that async_schedule_domain() made life so much
easier. This also added the sysdata_synchronize_request() helper
which user can use to see if their async request completed. This
should help users considerably as well. Updated code, commit log
and documentation to reflect these changes.
o In testing found that to make semantics stronger we should
require @optional to true on the descriptor if an optional
callback is to be provided (with SYSDATA_SYNC_OPT_CB() or
SYSDATA_ASYNC_OPT_CB()). Made notes to ensure to users
that set @optional to true but are not providing a opt_fail_cb()
should at the very least seriously consider using the returned
using async_cookie to sysdata_synchronize_request() to ensure
no lingering requests are kept out of bounds.
o Updated commit log to reflect how we can compartamentalize
usermode helper code
o Adds SYSDATA_ASYNC_OPT_CB()
o Forces @optional on SYSDATA_SYNC_OPT_CB() to true
o Ensures sysdata_file_request() and sysdata_file_request_async()
check for emptry string (name[0] == '\0') as follow up to
Kees's check for empty string name 471b095dfe0d6 ("firmware_class:
make sure fw requests contain a name") and later a fix by
Brian through 715780ae4bb76d ("firmware: actually return NULL on
failed request_firmware_nowait()).
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
6 files changed