I think this proposal is well intentioned, but from my previous
experience in trying to "manage" minor number spaces in portable
frameworks, its hard to get this right.
Device drivers may have multiple "real" minor nodes, which have
different behaviors. You usually have to have at least a decode of the
instance number, and possibly a decode of the "behavior". (E.g. in the
audio framework, I have to know whether the node was opened to use the
OSS API or the Sun API, and is it a "control" node (audioctl) or a
regular /dev/audio data transfer node?)
You can't rely on instance numbering either... some drivers might want
to have a single "dev_info_t" with multiple logical devices. (E.g. a
multi-port ethernet card, or an audio device with multiple independent
output ports but only a single PCI device.. I've seen both instances
occurs, so this is not merely hypothetical. Even the SDcard code has
this -- multiple SDcard slots on a single PCI function is specified in
the SDHCI specification.)
So, the problem is carving up minor name space.
You can offer drivers a convenience function, but you have to give them
a way to constrain the space from which they allocate minor nodes &
minor node state. (And you might need different state structures for
different kinds of clone opens -- e.g. OSS has very different state than
the legacy Sun Audio.)
Your proposal is also lacking in the detail for "parent" state. How is
that parent state (set of minor data) managed? Is the state to track
minor usage tracked per major in a master table somewhere? When is the
initial empty state allocated, and when is it freed? Will this be
automatic as part of modload/unload?
In short, while such utility functions may be useful for some, or even
many drivers, it will be difficult to make them generally useful for all
cloneable device drivers. And more detail is needed. At the end of the
day, I'm not sure it will save all that much code in each driver. Maybe
100 lines, but probably less.....
-- Garrett
Darren Reed wrote:
To follow up on my earlier post...
I've put a bit more thought into it...
The impetus for doing this is BPF. BPF keeps per
open file data for each file descriptor.
Enhanced Minor Device Management
================================
This proposal is focused on one goal: making life
easier for device driver writers that wish to
implement "cloning" for character or block devices.
This proposal is not concerned with why a developer
might choose to do that in favour of other alternatives.
Today
-----
The problem a device driver developer faces today is
that OpenSolaris only provides the bare minimum support
for cloning on character/block devices and even then,
it's not completely obvious. The method through which
this is done is to have the device driver choose which
minor number is to be allocated each time the device is
opened. Thus the driver is responsible for its use of
minor numbers and getting information from an open to a
read, etc. More over, every device that wishes to support
a cloned open for a character/block device needs to
implement its own management of minor number space and
context tracking.
Goals
-----
The goals of this interface change is to free the device
driver developer from worrying about minor number
allocation, how cloning operates and how to get context
from open(9e) to read(9e) and friends. The implementation
of this is intended to be completely backwards compatible.
There are no requirements for old drivers to work with the
new interfaces, if it is merely just binary drivers that
are being copied. Drivers that are being compiled will
need to be modified slightly to compile cleanly with the
new arguments for the changes to the entrypoints.
This proposal assumes that a developer is going to only use
their own method for managing minor numbers or only rely on
the interfaces provided as a part of this project.
Managing Minor Numbers
~~~~~~~~~~~~~~~~~~~~~~
To make it easier for developers to ...
To meet these requirements, this proposal suggests two new
functions: ddi_minor_alloc and ddi_minor_free.
The prototypes for these functions are:
int ddi_minor_alloc(major_t, minor_t *);
void ddi_minor_free(major_t, minor_t);
The use of the above with makedevice would be something
like this:
if (ddi_minor_alloc(getmajor(*devp), &newminor) == 0)
*devp = makedev(getmajor(*devp), newminor);
ddi_minor_alloc will attempt to allocate a new minor number
for a given major number. The first call to ddi_minor_alloc
takes care of any internal initialisation required to support
further calls. Similarly, the call to ddi_minor_free that
cleans up the last used minor device will dismantle respective
internal infrastructure.
ddi_minor_alloc will return DDI_FAILURE if it is unable to
allocate a new, unique minor number and DDI_SUCCESS if it
does succeed. The range of minor device numbers that can be
returned is specific to the platform: 32bit systems are
limited to 0x3ffff devices, whilst a 64bit system can
allocate up to 2^31 minor decices.
If the developer doesn't wish to get involved at all with
managing minor numbers at all, then D_CLONE_OPEN can be set
in cb_flags. This is the equivalent to calling ddi_minor_alloc()
before calling the driver's open(9e) function and calling
ddi_minor_free() after close(9e) has been called.
Minor Device Context
~~~~~~~~~~~~~~~~~~~~
Allocating a new minor device number with each open is just
the first step to providing meaningful support for drivers
that wish to provide a clean slate each time the device is
opened. The next, key, component is to provide support for
being able to access context about the minor device from the
other entry points such as read(9e), write(9e), etc.
To support this, provision for storing a pointer to context
created in the open(9e) entry point is provided. When the
open entry point is called, the context pointer is NULL.
It is the responsibility of the driver to set the context
pointer if so desired.
Each of the following entry points into the driver will be
supplied with a new, extra, paramter: aread, awrite, chpoll,
dump, ioctl, mmap, print, read, segmap, strategy and write.
close is supplied pointer to the context pointer, which the
driver is expected to clear before returning from its
close(9e) function. The difference with close(9e) is to
enforce the idea that the driver is required to clean up
the context data that it allocated/set.
This proposal makes no distinction between block and
character devices and as such entry points to both are
intended to be updated. There's no reason why a block device
can't be written to be a cloning device, only the historical
implementations that subscribed to the notion of each minor
node for a device needing to be present, individually, in
the device filesystem.
The provision of context through the proposed interfaces is
optional and drivers can ignore it and use their own mechanism
if they wish. It is expected that the performance hit of
providing the context pointer to the entry point functions would
be negligable for devices that do not use it and of some benefit,
but perhaps not measurable, for those that are able to use it.
It is the responsibility of the driver to manage simultaneous
access to its own context data structure. No extra locking or
protection is supplied for the driver because it decides to
use the interfaces in this proposal.
As a result of this interface proposal being backward compatible
with existing binary drivers, there is no direct requirement for
any significant change such as increasing CB_REV to indicate that
the structure members of cb_ops have changed. Increasing it would
not stop new drivers being used on old kernels, only the use of
mew symbols can achieve that here.
Comments?
Criticisms?
Darren
_______________________________________________
opensolaris-code mailing list
opensolaris-code@opensolaris.org
http://mail.opensolaris.org/mailman/listinfo/opensolaris-code
_______________________________________________
opensolaris-code mailing list
opensolaris-code@opensolaris.org
http://mail.opensolaris.org/mailman/listinfo/opensolaris-code