2002-08-05 19:11:53

by Patrick Mochel

[permalink] [raw]
Subject: driverfs API Updates


A series of driverfs changes went into Linus' tree last Friday. This is a
short summary of those changes, and some notes on how to use them.

Firstly, I changed the name of the structure that must be declared
from struct driver_file_entry to struct device_attribute. This more
accurately represents what is going on.


I've also created a macro[1] for defining device attributes, that goes
like this:

DEVICE_ATTR(name,"strname",mode,show,store);

This will create a structure by the name of 'dev_attr_##name', where
##name is the first parameter, which can then be passed to
device_create_file(). [2]


The definition of device_remove_file has changed to:

void device_remove_file(struct device * dev, struct device_attribute *
attr);

(The second parameter is now the same type as what is passed to
device_create_file, for consistency's sake (instead of a char *)).


I've added support for bus and device driver attributes. The mechanism
for manipulating them is analogous to that of device attributes. To
declare them, you do:

BUS_ATTR(name,"strname",mode,show,store);
DRIVER_ATTR(name,"strname",mode,show,store);

which create the objects

struct bus_attribute bus_attr_##name;

and

struct driver_attribute driver_attr_##name;

respectively.

You can then use

int bus_create_file(struct bus_type *, struct bus_attribute *);
void bus_remove_file(struct bus_type *, struct bus_attribute *);

int driver_create_file(struct device_driver *, struct driver_attribute *);
void driver_remove_file(struct device_driver *, struct driver_attribute
*);

To add and remove them.

Bus attribute files appear in the bus's directory (bus/<bus>/ under
the driverfs mountpoint).

Driver attributes appear in the driver's directory
(bus/<bus>/<driver>/ under the driverfs mountpoint).


The bus show and store routines are identical to the device show and
store routines, though they take a pointer of type struct bus_type as
the first parameter.

Similarly for drivers; they take a struct device_driver * as the first
parameter.

Please see include/linux/device.h for the structure definitions, and
drivers/base/fs/*.c for implementation details.


driverfs now has the ability to support attributes for any object
type. I've updated the documentation
(Documentation/filesystems/driverfs.txt) to hopefully include enough
information to hack on it. I'm also open to all questions and
suggestions, so please feel free to ask.



Thanks,

-pat




[1]: The reason for the macro is because the driverfs internals
have changed enough to be able to support attributes of any type. In
order to do this in a type-safe manner, we have a generic object type
(struct attribute) that we use. We pass this to an intermediate layer
that does a container_of() on that object to obtain the specific
attribute type.

This means the specific attribute types have an embedded struct
attribute in them, making the initializers kinda ugly. I played with
anonymous structs and unions to have something that could
theoretically work, but they apparently don't like named
initializers.


[2]: I wanted to consolidate the first two parameters, but I couldn't
find a way to stringify ##name (or un-stringify "strname"). Is that
even possible?


2002-08-05 19:43:28

by Kai Germaschewski

[permalink] [raw]
Subject: Re: driverfs API Updates

On Mon, 5 Aug 2002, Patrick Mochel wrote:

> [1]: The reason for the macro is because the driverfs internals
> have changed enough to be able to support attributes of any type. In
> order to do this in a type-safe manner, we have a generic object type
> (struct attribute) that we use. We pass this to an intermediate layer
> that does a container_of() on that object to obtain the specific
> attribute type.

Of course that means that it's not really type-safe, since it has no way
to check whether the object is embedded in the right type of struct, right
;) (But I think that's okay, C doesn't have provisions for real
inheritance)

> This means the specific attribute types have an embedded struct
> attribute in them, making the initializers kinda ugly. I played with
> anonymous structs and unions to have something that could
> theoretically work, but they apparently don't like named
> initializers.

Have you considered just putting in the embedded part via some macro -
I think that's what NTFS does for compilers which don't support unnamed
structs.

Basically

#define EMB_ATTRIBUTE \
int emb1;
int emb2

struct my_attribute {
EMB_ATTRIBUTE
int my1;
int my2;
};

That'll work with named initializers just fine, so the users don't have to
deal with ugly DEVICE_ATTR macros, where one forgets if parameter #3 was
show or store ;) - It follows the common way of hiding away unavoidable
ugliness in some header.

> [2]: I wanted to consolidate the first two parameters, but I couldn't
> find a way to stringify ##name (or un-stringify "strname"). Is that
> even possible?

Why would stringify (include/linux/stringify.h) not work? However, Al Viro
may get mad at you for generating ungreppable symbols either way ;-)

--Kai



2002-08-05 20:12:09

by Patrick Mochel

[permalink] [raw]
Subject: Re: driverfs API Updates


On Mon, 5 Aug 2002, Kai Germaschewski wrote:

> On Mon, 5 Aug 2002, Patrick Mochel wrote:
>
> > [1]: The reason for the macro is because the driverfs internals
> > have changed enough to be able to support attributes of any type. In
> > order to do this in a type-safe manner, we have a generic object type
> > (struct attribute) that we use. We pass this to an intermediate layer
> > that does a container_of() on that object to obtain the specific
> > attribute type.
>
> Of course that means that it's not really type-safe, since it has no way
> to check whether the object is embedded in the right type of struct, right
> ;) (But I think that's okay, C doesn't have provisions for real
> inheritance)

Well sure, if you want to get technical. ;) I almost said 'mostly'
type-safe, but I decided I would fib a little to make myself sound
stronger. Basically, I think it's as safe as we can get, and it was
type-safe enough for Linus..

> > This means the specific attribute types have an embedded struct
> > attribute in them, making the initializers kinda ugly. I played with
> > anonymous structs and unions to have something that could
> > theoretically work, but they apparently don't like named
> > initializers.
>
> Have you considered just putting in the embedded part via some macro -
> I think that's what NTFS does for compilers which don't support unnamed
> structs.
>
> Basically
>
> #define EMB_ATTRIBUTE \
> int emb1;
> int emb2
>
> struct my_attribute {
> EMB_ATTRIBUTE
> int my1;
> int my2;
> };

It's not that it's unnamed, it's that we want both object types to exist,
and have something to do container_of() on. Yet, have something easy to
declare.

I wanted something like:

struct attribute {
char * name;
mode_t mode;
};

struct device_attribute {
union {
struct attribute attr;
struct {
char * name;
mode_t mode;
};
device_show show;
device_store store;
};

You can access struct device_attribute::name fine, except when using named
initializers. At least with gcc 2.96.

> That'll work with named initializers just fine, so the users don't have to
> deal with ugly DEVICE_ATTR macros, where one forgets if parameter #3 was
> show or store ;) - It follows the common way of hiding away unavoidable
> ugliness in some header.

Bah, tradeoffs. It's not that hard to get the parameters right; and it
won't take long for them to notice ;)

> > [2]: I wanted to consolidate the first two parameters, but I couldn't
> > find a way to stringify ##name (or un-stringify "strname"). Is that
> > even possible?
>
> Why would stringify (include/linux/stringify.h) not work? However, Al Viro
> may get mad at you for generating ungreppable symbols either way ;-)

Uhm, because I'm retarded, and I didn't actually try.


-pat

2002-08-05 23:35:17

by Patrick Mansfield

[permalink] [raw]
Subject: Re: driverfs API Updates

Pat -

On Mon, Aug 05, 2002 at 12:17:13PM -0700, Patrick Mochel wrote:

> I've also created a macro[1] for defining device attributes, that goes
> like this:
>
> DEVICE_ATTR(name,"strname",mode,show,store);

Do you any plans to simplify the show or store interfaces?

We have the same interface and problem with /proc read and write.

Right now, to do it correctly (for short read buffers, seeks, or long strings
being output) using sprintf() is very painful, see sg.c for example, and its
proc read interfaces. It took me forever to realize that the code is
re-writing the same data into a buffer.

Passing a single page or two (4k to 8k buffer), with no offset, and letting
the driverfs_read_file fill buf might be OK, but breaks seeks (and short
buffer usage), but at least the show/restore functions would be less likely
to be broken. Limiting the offset to a fit in a page might help.

If the show and store interfaces could return a pointer, lengths, and
a specifier ("%s", "%d", etc.), that might be pretty simple, and would
allow for correct offset and overflow checks.

Most of the current show interfaces are broken for a short buffer or seek,
and they are being copied to create new interfaces, example usage:

[patman@elm3a50 linux-2.5.29-p1]$ cat /devices/root/pci0/00:0f.2/name
PCI device 1166:0220
[patman@elm3a50 linux-2.5.29-p1]$ dd if=/devices/root/pci0/00:0f.2/name of=/tmp/xx bs=1 count=10 ; cat /tmp/xx ; echo
1+0 records in
1+0 records out
P

I changed the scsi_scan.c scsi_device_type_read(), and got it working
OK, it does not check for overflows (snprintf does not work, since we
do not pass an offset; maybe if a snoffprintf existed it might help),
but this does work for seeks (or short reads):

static ssize_t scsi_device_type_read(struct device *driverfs_dev, char *page,
size_t count, loff_t off)
{
struct scsi_device *sdev = to_scsi_device(driverfs_dev);
ssize_t size;

if ((sdev->type > MAX_SCSI_DEVICE_CODE) ||
(scsi_device_types[(int)sdev->type] == NULL))
size = sprintf(page, "Unknown\n");
else
size = sprintf(page, "%s\n",
scsi_device_types[(int)sdev->type]);
if (off >= size)
/*
* Assumed complete.
*/
return 0;
return size;
}

For the above to function I also had to change:

===== fs/driverfs/inode.c 1.20 vs edited =====
--- 1.20/fs/driverfs/inode.c Fri Jul 26 12:58:50 2002
+++ edited/fs/driverfs/inode.c Tue Jul 30 14:01:46 2002
@@ -311,7 +311,7 @@
} else if (len > count)
len = count;

- if (copy_to_user(buf,page,len)) {
+ if (copy_to_user(buf,page+*ppos,len)) {
retval = -EFAULT;
break;
}

-- Patrick Mansfield

2002-08-06 16:42:46

by Patrick Mochel

[permalink] [raw]
Subject: Re: driverfs API Updates


> > DEVICE_ATTR(name,"strname",mode,show,store);
>
> Do you any plans to simplify the show or store interfaces?

Yes. But, I'm not sure how I want to do it. A while back, I converted it
to use the seq_file interface, with a (probably broken) implementation of
seq_write(). I'm not sure how well it would fit into what we have now, but
I definitely agree that it should be simpler.

> Passing a single page or two (4k to 8k buffer), with no offset, and letting
> the driverfs_read_file fill buf might be OK, but breaks seeks (and short
> buffer usage), but at least the show/restore functions would be less likely
> to be broken. Limiting the offset to a fit in a page might help.
>
> If the show and store interfaces could return a pointer, lengths, and
> a specifier ("%s", "%d", etc.), that might be pretty simple, and would
> allow for correct offset and overflow checks.

The seq_file interface would allow for that.

One purely evil solution might be to just pass a zero'd page-sized buffer
to be filled one time. We then do strlen() on it for the size, and copy
what the user wants. It would still require some extra state, but it would
force people to stick to ASCII, instead of trying to sneak in some binary
data ;)

> Most of the current show interfaces are broken for a short buffer or seek,
> and they are being copied to create new interfaces, example usage:
>
> [patman@elm3a50 linux-2.5.29-p1]$ cat /devices/root/pci0/00:0f.2/name
> PCI device 1166:0220
> [patman@elm3a50 linux-2.5.29-p1]$ dd if=/devices/root/pci0/00:0f.2/name of=/tmp/xx bs=1 count=10 ; cat /tmp/xx ; echo
> 1+0 records in
> 1+0 records out
> P

Yeah, that's definitely broken.

> For the above to function I also had to change:

Thanks, applied.

-pat

2002-08-06 17:40:59

by Kristian Hogsberg

[permalink] [raw]
Subject: driverfs and ieee1394

Hi Patrick,

I've been reading through your driverfs and device model code, and
trying to change the ieee1394 subsystem over to use it. The ieee1394
subsystem has some bus and device management functionality which works
much like the general device model code, and I think we could replace
much of this in the end. But for now, I was just trying to hook it up
to the driverfs and use this to expose the subsystem status.

An ieee1394 device can have several programming interfaces
(i.e. several supported protocols for the same device), and I'm not
sure how to express this in the device model. Ideally, you would
register a driver and specify which programming interface it supports
and the device model code would call probe for unmanaged devices that
has that interface (among others, possibly) . Conversely, when a new
device is plugged in, the device model code should try to find a
driver that would work with one of the devices programming interfaces.

Likewise, many drivers support several programming interfaces - this
is supported in the PCI driver system, the usb subsystem and also in
the ieee1394 system (this was actually lifted from the PCI code).

I looked briefly at the usb solution, and it seems that they register
programming interfaces as subdevices of the actual device. This has
the advantage of letting the general code do the work of iterating
through the interfaces, but it doesn't seem like the right way to use
the driverfs. Another approach is to not register the actual devices
but only the interfaces like dev0:if0, dev0:if1, dev1:if0, etc. but
this doesn't express the structure of the bus in the directory
structure. Finally, you could choose not to expose the interfaces at
all, and let the bus' match callback iterate through the supported
interfaces for drivers and devices, as is the case with the PCI
subsystem.

I know that the bus matching algorithm necessarily is bus specific,
but I think the concept of interfaces, as exposed by devices and
supported by drivers, is universal, so maybe the device model should
be extended to also incorporate interfaces in some way.

Anyway, for now I'll just implement the interface matching in the
match callback for the bus, and I plan to expose the interfaces of a
device by using the device_attribute mechanism. In the ieee1394
subsystem, a device has a list of structs attached, each representing
an programming interface. To implement a device_attribute entry per
interface in the directory for the device the show callback needs to
know which interface it is supposed to show. As I see it, there are
basically two ways to do this and they both break the current API: 1)
include a void *user_data field in the device_attribute struct and
pass this as an extra argument to the show() and store() callbacks or
2) pass the pointer to the device_attribute struct to the callbacks
and let the callbacks use container_of() to figure out what they're
contained in. I prefer the last solution, since you save the pointer
and I plan to embed the device_attribute structs in the struct
representing the interface anyway. It requires only minimal changes
to the device model code but it breaks the API:

static ssize_t
dev_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
char * buf, size_t count, loff_t off)
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_device(dir);
ssize_t ret = 0;

if (dev_attr->show)
ret = dev_attr->show(dev,dev_attr,buf,count,off);
return ret;
}

Another issue is device naming (bus_id) - what's the convention? I
can see from the PCI names that they use bus position, but this is
probably a bad idea for ieee1394. Devices on the ieee1394 bus are
enumerated by a tree traversal algorithm, and hotplug events change or
even re-root the tree (the linux box isn't necessarily the root), and
thus, the bus addresses change. Instead I was planning to using the
extended unique id (EUI) of the devices as device names. The EUI is a
64 bit globally unique number, much like the MAC address of ethernet
cards. However, there's only allocated 16 chars for the
bus_id... could you make it 20 chars, or do you have another
suggestion for device naming?

Kristian

2002-08-08 03:53:17

by Rusty Russell

[permalink] [raw]
Subject: Re: driverfs API Updates

On Mon, 5 Aug 2002 12:17:13 -0700 (PDT)
Patrick Mochel <[email protected]> wrote:
> I've also created a macro[1] for defining device attributes, that goes
> like this:
>
> DEVICE_ATTR(name,"strname",mode,show,store);
>
> This will create a structure by the name of 'dev_attr_##name', where
> ##name is the first parameter, which can then be passed to
> device_create_file(). [2]

Hi Patrick,
I'll grab 2.5.31 when it comes out and play with it.

Personally, I would get rid of the "strname" (make it implied by the variable
name), and use type instead of show & store, eg:

DEVICE_ATTR(frobbable, O_RDWR, int);

This means you can (1) check that frobbable is actually an int at compile
time (__check_int), (2) you can use __show_int and __store_int as standard
routines, and (3) you can use your own types by:

#define __check_frobbable_t(x) ((void)((&x) == (frobbable_t *)0)
/* Define show_frobbable and store_frobbable here */

DEVICE_ATTR(frobbable, O_RDWR, frobbable_t);

This ties into alot of other projects such as event logging, etc.

Rusty.
PS. yeah yeah, I'll send code RSN.
--
there are those who do and those who hang on and you don't see too
many doers quoting their contemporaries. -- Larry McVoy

2002-08-08 18:15:14

by Patrick Mochel

[permalink] [raw]
Subject: Re: driverfs API Updates


On Thu, 8 Aug 2002, Rusty Russell wrote:

> On Mon, 5 Aug 2002 12:17:13 -0700 (PDT)
> Patrick Mochel <[email protected]> wrote:
> > I've also created a macro[1] for defining device attributes, that goes
> > like this:
> >
> > DEVICE_ATTR(name,"strname",mode,show,store);
> >
> > This will create a structure by the name of 'dev_attr_##name', where
> > ##name is the first parameter, which can then be passed to
> > device_create_file(). [2]
>
> Hi Patrick,
> I'll grab 2.5.31 when it comes out and play with it.
>
> Personally, I would get rid of the "strname" (make it implied by the variable
> name), and use type instead of show & store, eg:

Ok, I updated the macros to drop the "strname" parameter, so they now look
like this:

DEVICE_ATTR(name,mode,show,store)
BUS_ATTR(name,mode,show,store)
DRIVER_ATTR(name,mode,show,store)

> DEVICE_ATTR(frobbable, O_RDWR, int);
>
> This means you can (1) check that frobbable is actually an int at compile
> time (__check_int), (2) you can use __show_int and __store_int as standard
> routines, and (3) you can use your own types by:
>
> #define __check_frobbable_t(x) ((void)((&x) == (frobbable_t *)0)
> /* Define show_frobbable and store_frobbable here */
>
> DEVICE_ATTR(frobbable, O_RDWR, frobbable_t);

We're talking about very similar, though distinctly different attributes.

The attributes that I've addressed so far are those that are per-object
and would typically reside in the object's data structure. You want to
declare one attribute, and expose it for each instance of the object.
The show and store methods have to know which instance you're referring
to.

'frobbable' above would be a single static variable. show and store could
only take a pointer to the variable, and could easily use common, shared
routines.

With common routines though, you don't get the ability to do object-level
locking. By defining your own show and store methods, you can.

That said, this is what I want to do:

Define helpers for parsing and formatting types; e.g. show_int() and
store_int(). Objects' show and store methods can use those for the exposed
attribute.

Support single static attributes by having something like this:

struct int_attribute {
struct attribute attr;
show_int_t show;
store_int_t store;
int * data;
};

INT_ATTR(frobbable,0644);

which would produce something like:

int frobbable;
struct int_attr_frobbable = {
.attr = {
.name = "frobbale",
.mode = 0644,
},
.show = show_int,
.store = store_int,
};

Then, to expose it to userspace, you would do:

int_attr_create(&int_attr_frobbale);

(or equivalent), and it would then show up in the object's driverfs/kfs
directory.

What do you think? It definitely looks a lot like your PARAM stuff, and I
need to look again at what you wrote to see if I can tie in any more of
it.

Of course, they don't have to be exposed to userspace in order to access
them. This is a little further down the road, but by placing them (or
pointers to them) in a special section, we could access attributes at boot
time or module load time, like module parameters.

And, if we do that, we don't have to have explicit create and remove
functions to add them to userspace. We can just iterate over the pointers
at some stage in the boot process or module load time.

I'm thinking that we could macro-ize locking for single static variables
as well. We could have something like:

rwlock_t mylock;

INT_ATTR_LOCKED(frobbable,0644,mylock);

which could then generate

int get_frobbable(void);

void set_frobbable(int val);

as static functions. The show and store methods could either use the lock
directly, or call back the get/set pair as necessary. I dunno; I haven't
actually tried to implement that...

-pat



2002-08-09 01:49:17

by Rusty Russell

[permalink] [raw]
Subject: Re: driverfs API Updates

In message <[email protected]> you w
rite:
> That said, this is what I want to do:
>
> Define helpers for parsing and formatting types; e.g. show_int() and
> store_int(). Objects' show and store methods can use those for the exposed
> attribute.
>
> Support single static attributes by having something like this:
>
> struct int_attribute {
> struct attribute attr;
> show_int_t show;
> store_int_t store;
> int * data;
> };
>
> INT_ATTR(frobbable,0644);

Ok, that makes sense, except I prefer to build the interface in
layers, something like:

ATTRIBUTE(frobbable,int,0644)
=> ATTRIBUTE_CALL(frobbable,0644,show_int,store_int)

This still allows you to define your own types...

> What do you think? It definitely looks a lot like your PARAM stuff, and I
> need to look again at what you wrote to see if I can tie in any more of
> it.

I think you've got all the good bits now 8)

> Of course, they don't have to be exposed to userspace in order to access
> them. This is a little further down the road, but by placing them (or
> pointers to them) in a special section, we could access attributes at boot
> time or module load time, like module parameters.

This was my idea with "000" perm attributes: they are explicitly only
settable at module/kernel init (eg. they and their set/show functions
can be declared __init).

> I'm thinking that we could macro-ize locking for single static variables
> as well. We could have something like:
>
> rwlock_t mylock;
>
> INT_ATTR_LOCKED(frobbable,0644,mylock);
>
> which could then generate
>
> int get_frobbable(void);
>
> void set_frobbable(int val);

Hmmm, how about:

ATTRIBUTE_LOCKED(frobbable,int,0644,mylock)
=> ATTRIBUTE_CALL(frobbable,0644,mylock,show_int_lock,store_int_lock)

With PARAM()/sysfs, I hit the wall when I tried to handle spinlocks,
rwlocks, semaphores, rwsemaphores, and backed off until I knew which
ones were actually useful 8)

This is the nice thing about having people actually using the code is
you can tell when you've hit the 90% mark (the weird cases can always
use their own callbacks). I think trial-and-error is the best way to
introduce these kind of convenience functions.

Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

2002-08-19 19:18:31

by Patrick Mochel

[permalink] [raw]
Subject: Re: driverfs and ieee1394


Hi. Sorry about the long delay in getting back to you.

> I've been reading through your driverfs and device model code, and
> trying to change the ieee1394 subsystem over to use it. The ieee1394
> subsystem has some bus and device management functionality which works
> much like the general device model code, and I think we could replace
> much of this in the end. But for now, I was just trying to hook it up
> to the driverfs and use this to expose the subsystem status.

Excellent. I'll be very interested in seeing what things can do fall out.

> I looked briefly at the usb solution, and it seems that they register
> programming interfaces as subdevices of the actual device. This has
> the advantage of letting the general code do the work of iterating
> through the interfaces, but it doesn't seem like the right way to use
> the driverfs. Another approach is to not register the actual devices
> but only the interfaces like dev0:if0, dev0:if1, dev1:if0, etc. but
> this doesn't express the structure of the bus in the directory
> structure. Finally, you could choose not to expose the interfaces at
> all, and let the bus' match callback iterate through the supported
> interfaces for drivers and devices, as is the case with the PCI
> subsystem.

The core mainly cares about device interfaces right now, for the purpose
of binding drivers to them. Though, there may be attributes about the
device themselves that you want to express.

If there is, I would recommend doing what the USB subsystem does. If not,
go the PCI route, with a flat namespace for all devices and functions on a
particular bus.

If you choose the former, look how the USB code handles devices. They set
the driver to a default, benign one, so the core doesn't call the bus's
match function to bind a driver to it. You probably want to do something
like that.

> Anyway, for now I'll just implement the interface matching in the
> match callback for the bus, and I plan to expose the interfaces of a
> device by using the device_attribute mechanism. In the ieee1394
> subsystem, a device has a list of structs attached, each representing
> an programming interface. To implement a device_attribute entry per
> interface in the directory for the device the show callback needs to
> know which interface it is supposed to show. As I see it, there are
> basically two ways to do this and they both break the current API: 1)
> include a void *user_data field in the device_attribute struct and
> pass this as an extra argument to the show() and store() callbacks or
> 2) pass the pointer to the device_attribute struct to the callbacks
> and let the callbacks use container_of() to figure out what they're
> contained in. I prefer the last solution, since you save the pointer
> and I plan to embed the device_attribute structs in the struct
> representing the interface anyway. It requires only minimal changes
> to the device model code but it breaks the API:

Again, I would say expose the device interfaces by wrapping them around a
struct device and registering them in the device tree. Internally, it
makes sense, since that is the object with the most meaning to us.
Externally, there are most likely many attributes of the interfaces that
you want to expose. Having a directory for each gives you this ability
easily.

> Another issue is device naming (bus_id) - what's the convention? I
> can see from the PCI names that they use bus position, but this is
> probably a bad idea for ieee1394. Devices on the ieee1394 bus are
> enumerated by a tree traversal algorithm, and hotplug events change or
> even re-root the tree (the linux box isn't necessarily the root), and
> thus, the bus addresses change. Instead I was planning to using the
> extended unique id (EUI) of the devices as device names. The EUI is a
> 64 bit globally unique number, much like the MAC address of ethernet
> cards. However, there's only allocated 16 chars for the
> bus_id... could you make it 20 chars, or do you have another
> suggestion for device naming?

The bus_id is simply the position on the bus of the device. It's relative
to the local bus only, and does not have global significance. [1]. It's
equivalent to struct pci_dev::slot_name. [2]

Unique identifiers are a different entity, and will eventually make their
way into the driver model core. But, you don't necessarily need the unique
IDs to ascertain the topology of the system, which was the first goal of
the bus_id.

-pat

[1] Ok, I'm lying. We have a flat namespace of all devices on all
instances of a particular bus type. This makes iterating over the devices
when attaching drivers much easier. This namespace is exposed in
bus/$bus_type/devices/ in driverfs via symlinks to the devices directory
in the physical hierarchy. The name of the symlink is the bus_id field.

In order to avoid conflicts, you want a bus_id that is something like <bus
number><device number><interface number>. They don't have to be UUIDs, and
it's ok for them to change via hotplug events.

[2] Yes, I've considered changing the names of bus_id and name to
something like 'slot' and 'description'. Dave Brownell, I hear you
calling....