2002-09-25 19:23:54

by Matt Domsch

[permalink] [raw]
Subject: devicefs requests

Pat,

1) As new drivers pick up the model, check that all xxx_bus_type objects
get EXPORT_SYMBOLd and included in a include/xxxx header somewhere - My BIOS
EDD code walks the list of bus types looking for attached devices to compare
against (pci, ide, scsi, usb, ...).
ide_bus_type is in include/linux/ide.h but isn't EXPORT_SYMBOL;
usb_bus_type is in include/linux/usb.h but isn't EXPORT_SYMBOL;

Alternately, keep the list of registered bus types accessible via a
list_for_each type macro. I like the exported symbols myself, it lets me
do:

struct edd_known_bus_types_s {
struct bus_type *bus;
const char *edd_type;
int (*match)(struct device *edd_dev, struct device *dev);
};

static const struct edd_known_bus_types_s edd_known_bus_types[] = {
{bus:&scsi_driverfs_bus_type, edd_type: "SCSI", match:
edd_match_scsidev},
// {bus:&ide_bus_type, edd_type: "ATA", match: NULL},
// {bus:&usb_bus_type, edd_type: "USB", match: NULL},
{bus:NULL, edd_type: NULL, match: NULL},
};

so I can supply my own match functions which match one type of device (e.g.
EDD's idea of a SCSI device) to that of the standard device. I could
accomplish the same using well-known names for bus_type I suppose, and doing
a list_for_each until I find it. Just a different thing getting exported, a
well-known name and a lookup method rather than the symbol itself.


2) bus_for_each_dev() is really restrictive right now due to all the locking
mechanisms in place. In my code I'd like to, given a struct device *, walk
a list of devices on a given bus and compare each device with the given
device, returning a match, or not. As it stands, bus_for_each_dev returns
either success (the callback worked for each device on the list), or failure
(the callback failed for some device on the list), but I don't see a
mechanism to return which device failed without excessive abuse of the
void*. For now I've made a private copy of bus_for_each_dev which I've
mucked with the return the properly matching device, and wonder if this
couldn't be made more generic somehow.

Thoughts?

Thanks,
Matt

--
Matt Domsch
Sr. Software Engineer, Lead Engineer, Architect
Dell Linux Solutions http://www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com


2002-09-25 21:29:06

by Greg KH

[permalink] [raw]
Subject: Re: devicefs requests

On Wed, Sep 25, 2002 at 02:28:57PM -0500, [email protected] wrote:
> Pat,
>
> 1) As new drivers pick up the model, check that all xxx_bus_type objects
> get EXPORT_SYMBOLd and included in a include/xxxx header somewhere - My BIOS
> EDD code walks the list of bus types looking for attached devices to compare
> against (pci, ide, scsi, usb, ...).
> ide_bus_type is in include/linux/ide.h but isn't EXPORT_SYMBOL;
> usb_bus_type is in include/linux/usb.h but isn't EXPORT_SYMBOL;

But what do you do with the usb_bus_type? Why would your code use
anything that is private to the driver core?

thanks,

greg k-h

2002-09-25 21:29:29

by Greg KH

[permalink] [raw]
Subject: Re: devicefs requests

Oh yeah, it's "driverfs" not "devicefs" :)


2002-09-25 21:57:59

by Matt Domsch

[permalink] [raw]
Subject: RE: devicefs requests

> But what do you do with the usb_bus_type? Why would your code use
> anything that is private to the driver core?

Fair enough. I actually only need the 64-bit unique ID that the USB device
provides, and its parent PCI device. EDD provides this info as x86 BIOS
sees it, so my code compares the two, and will make a symlink between the
two. This lets the OS know which device BIOS thinks it is (i.e. to know
what disk you're booting from).

True, I don't (today) see a unique ID in struct usb_device. Hopefully
that's something that can be added in the future. Functions which expose
this info separate from exporting the bus type would be great.

SCSI has a different set of things that EDD needs exported (channel, id,
lun). IDE still different (channel, number (master/slave)), plus parent PCI
device.

> Oh yeah, it's "driverfs" not "devicefs" :)

Yes, my bad.

Thanks,
Matt

--
Matt Domsch
Sr. Software Engineer, Lead Engineer, Architect
Dell Linux Solutions http://www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com

2002-09-25 22:06:27

by Matt Domsch

[permalink] [raw]
Subject: RE: devicefs requests

> Fair enough. I actually only need the 64-bit unique ID that
> the USB device provides, and its parent PCI device.

Oh, and of course being able to walk the list of existing devices on that
bus (similar to bus_for_each_dev() now, with a callback mechanism that
allows comparison of one device (BIOSs idea of a device) with what the
device thinks of itself - to allow matching.

-Matt

--
Matt Domsch
Sr. Software Engineer, Lead Engineer, Architect
Dell Linux Solutions http://www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com

2002-09-25 22:42:15

by Greg KH

[permalink] [raw]
Subject: Re: devicefs requests

On Wed, Sep 25, 2002 at 05:03:09PM -0500, [email protected] wrote:
> > But what do you do with the usb_bus_type? Why would your code use
> > anything that is private to the driver core?
>
> Fair enough. I actually only need the 64-bit unique ID that the USB device
> provides, and its parent PCI device.

Um, what 64-bit unique id? USB devices do not have such a thing.

thanks,

greg k-h

2002-09-26 03:43:21

by Matt Domsch

[permalink] [raw]
Subject: RE: devicefs requests

> Um, what 64-bit unique id? USB devices do not have such a thing.

The EDD spec (http://www.t13.org/docs2002/d1572r0.pdf - T13 committee
project 1572D BIOS Enhanced Disk Drive Services - 3) says:
USB identifier: 64-bit Serial Number as defined in the USB Mass Storage
specifications

I assume that they mean the USB Mass Storage spec v1.0
(http://www.usb.org/developers/data/devclass/usbmassbulk_10.pdf) section
4.1.1 - Serial Number, which is 12-16 bytes long. drivers/usb/storage/usb.c
turns that into a 16-byte GUID in storage_probe(). I hadn't gotten so far
as to see that these two specs don't agree for USB - I'd been looking at the
IDE and SCSI descriptions so far. It wouldn't be the first time the EDD
spec needed editing, and given that few (if any) BIOSs yet implement it
apart from SCSI, is reason for the confusion.

I don't think Dell has a T13 committee representative right now, but I'll
see if we have a process for getting this cleared up through official
channels. As I'm not a USB expert, would you care to comment on the right
way to handle this (i.e. instead of a 64-bit serial number, use the 16-byte
GUID)?

Thanks,
Matt

--
Matt Domsch
Sr. Software Engineer, Lead Engineer, Architect
Dell Linux Solutions http://www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com
#1 US Linux Server provider for 2001 and Q1/2002! (IDC May 2002)

2002-09-26 04:10:28

by Greg KH

[permalink] [raw]
Subject: Re: devicefs requests

On Wed, Sep 25, 2002 at 10:48:31PM -0500, [email protected] wrote:
> > Um, what 64-bit unique id? USB devices do not have such a thing.
>
> The EDD spec (http://www.t13.org/docs2002/d1572r0.pdf - T13 committee
> project 1572D BIOS Enhanced Disk Drive Services - 3) says:
> USB identifier: 64-bit Serial Number as defined in the USB Mass Storage
> specifications

Ah, but that's a USB storage identifier, not a USB identifier. The usb
device structure does not contain this field, nor will it ever, sorry.

It seems that this spec is oriented toward storage devices. The USB
device structure if for all types of devices.

> I assume that they mean the USB Mass Storage spec v1.0
> (http://www.usb.org/developers/data/devclass/usbmassbulk_10.pdf) section
> 4.1.1 - Serial Number, which is 12-16 bytes long. drivers/usb/storage/usb.c
> turns that into a 16-byte GUID in storage_probe(). I hadn't gotten so far
> as to see that these two specs don't agree for USB - I'd been looking at the
> IDE and SCSI descriptions so far. It wouldn't be the first time the EDD
> spec needed editing, and given that few (if any) BIOSs yet implement it
> apart from SCSI, is reason for the confusion.

The majority of USB devices do not support serial numbers, as that field
was made optional in the spec. Even if it was required, it's a string
field, not a 64 bit number :(

> I don't think Dell has a T13 committee representative right now, but I'll
> see if we have a process for getting this cleared up through official
> channels. As I'm not a USB expert, would you care to comment on the right
> way to handle this (i.e. instead of a 64-bit serial number, use the 16-byte
> GUID)?

Um, what do you mean, "right way"? All USB devices do not have any such
serial number. Only a very small minority of devices contain a kind of
serial number, and that field is a string (and often times it is not
even unique, unfortunately.)

As for USB storage devices, I don't know if they all contain serial
numbers that are unique, you might want to go ask the author of the
usb-storage driver, Matt Dharm.

What are you trying to walk all of the USB devices for? What would you
do if you found a USB mass storage device that matched something in the
EDD tables?

thanks,

greg k-h

2002-09-26 14:41:00

by Randy.Dunlap

[permalink] [raw]
Subject: Re: devicefs requests

On Wed, 25 Sep 2002, Greg KH wrote:

| On Wed, Sep 25, 2002 at 10:48:31PM -0500, [email protected] wrote:
| > > Um, what 64-bit unique id? USB devices do not have such a thing.
| >
| > The EDD spec (http://www.t13.org/docs2002/d1572r0.pdf - T13 committee
| > project 1572D BIOS Enhanced Disk Drive Services - 3) says:
| > USB identifier: 64-bit Serial Number as defined in the USB Mass Storage
| > specifications
|
| Ah, but that's a USB storage identifier, not a USB identifier. The usb
| device structure does not contain this field, nor will it ever, sorry.
|
| It seems that this spec is oriented toward storage devices. The USB
| device structure if for all types of devices.

Yes, EDD would be oriented toward storage devices.

| > I assume that they mean the USB Mass Storage spec v1.0
| > (http://www.usb.org/developers/data/devclass/usbmassbulk_10.pdf) section
| > 4.1.1 - Serial Number, which is 12-16 bytes long. drivers/usb/storage/usb.c
| > turns that into a 16-byte GUID in storage_probe(). I hadn't gotten so far
| > as to see that these two specs don't agree for USB - I'd been looking at the
| > IDE and SCSI descriptions so far. It wouldn't be the first time the EDD
| > spec needed editing, and given that few (if any) BIOSs yet implement it
| > apart from SCSI, is reason for the confusion.
|
| The majority of USB devices do not support serial numbers, as that field
| was made optional in the spec. Even if it was required, it's a string
| field, not a 64 bit number :(

It's optional in the USB CBI spec. It's not even mentioned in the
USB UFI (floppy) spec, and USB floppy drives that I've seen do not
have it. It's not listed as optional in the USB bulk interface
storage spec, and my Zip drive and USB hard drive do have serial
numbers. At any rate, it cannot be depended on to be there.

| > I don't think Dell has a T13 committee representative right now, but I'll
| > see if we have a process for getting this cleared up through official
| > channels. As I'm not a USB expert, would you care to comment on the right
| > way to handle this (i.e. instead of a 64-bit serial number, use the 16-byte
| > GUID)?
|
| Um, what do you mean, "right way"? All USB devices do not have any such
| serial number. Only a very small minority of devices contain a kind of
| serial number, and that field is a string (and often times it is not
| even unique, unfortunately.)
|
| As for USB storage devices, I don't know if they all contain serial
| numbers that are unique, you might want to go ask the author of the
| usb-storage driver, Matt Dharm.
|
| What are you trying to walk all of the USB devices for? What would you
| do if you found a USB mass storage device that matched something in the
| EDD tables?

--
~Randy

2002-09-26 16:08:34

by Matt Domsch

[permalink] [raw]
Subject: RE: devicefs requests

> What are you trying to walk all of the USB devices for? What would you
> do if you found a USB mass storage device that matched something in the
> EDD tables?

My goal is simple, my approach may be flawed. :-)
x86 BIOS decides somehow what disk to boot from. In a single disk system,
that's a pretty simple choice. In a multi-disk system, BIOSs (either
on-board or add-in cards) enumerate devices and hook them to the int13
vector, and the system boots from device 80h, the first hard disk detected
and hooked to that vector. Problem is, Linux doesn't have a way to know
which disk BIOS thinks is the boot disk. Think installing onto a brand new
system with no data on any of its 8 internal disks, split across multiple
SCSI controllers, with an add-in RAID controller connecting a pile of
external storage. The Linux installer (at least) needs to know on which
disk to put lilo/grub in order to boot, and would like a hint as to where to
put /boot and / file systems, and right now that requires human intervention
and guesses - it's entirely possible to install on to such a system, reboot,
and the boot loader didn't get placed where BIOS goes to look for it. I've
got to restrict our factory preload configurations because of this.


EDD 3.0 is supposed to help solve this. We query BIOS early in the boot
process before switching to protected mode and store away the device path
information on a per-disk basis. I want to use this device path information
(PCI bus:dev.fn, {SCSI bus,id,lun; IDE controller,dev; USB - spec says
serial number); ...}) to compare against what the devices themselves
believe they're at under Linux, and provide a symlink in driverfs from a
BIOS device item to the Linux device item. Userspace hotplug will create
/dev/sdX by getting information from driverfs, and userspace tools like boot
loader installers could follow the symlink, get the kdev, make a temporary
device node, and operate on the right disk. (Temporary because it could
change on next boot if controllers or disks are are added/removed).

What I'm picturing is something like this (feedback welcome!):

/driverfs/
|-- bus
| |-- scsi
| | |-- devices
| | | |-- 0:0:0:0 -> ../../../root/pci2/02:06.0/scsi0/0:0:0:0
| | | |-- 0:0:0:0:disc ->
../../../root/pci2/02:06.0/scsi0/0:0:0:0/0:0:0:0:disc
| | | `-- 2:0:5:0 -> ../../../root/pci0/00:02.0/01:06.0/scsi2/2:0:5:0
| | | `-- 2:0:5:0:disc ->
../../../root/pci0/00:02.0/01:06.0/scsi2/2:0:5:0:disc
| | `-- drivers
| | `-- sd
`-- root
|-- BIOS_int13
| |-- 80
| | |-- disc -> ../../pci2/02:06.0/scsi0/0:0:0:0/0:0:0:0:disc/kdev
| | `-- info
| |-- 81
| | |-- disc -> ../../pci2/02:06.0/scsi0/2:0:5:0/2:0:5:0:disc/kdev
| | `-- info
|-- pci2
| |-- 02:06.0
| | |-- irq
| | |-- name
| | |-- power
| | |-- resource
| | `-- scsi0
| | |-- 0:0:0:0
| | | |-- 0:0:0:0:disc
| | | | |-- kdev


The only reason I'm doing even this much in driverfs is because I thought
the symlink idea would be nice. I could just as easily export two files per
BIOS device: interface_path and device_path, and make userspace read those
and walk the driverfs tree looking for the match. I was hoping that
driverfs could display this relationship between devices as it already does
for PCI {SCSI,IDE,...} devices. If I can't walk the list of devices from
inside the kernel looking for a match, I'll do it in userspace.

So far I've focused on SCSI because that's the type that can be most easily
constructed into really wierd controller and disk configurations, and what
we sell most of in our servers. Once SCSI works, I think IDE will follow
pretty easily. The EDD spec allows for a wide variety of interface paths:
ISA, PCI, PCI-X, InfiniBand, PCI Express, HyperTransport; and device paths:
ATA, ATAPI, SCSI, USB, 1394, Fibre, I2O, RAID, SATA.

> It seems that this spec is oriented toward storage devices. The USB
> device structure if for all types of devices.

Yes, the EDD spec is all about storage devices, particularly x86 BIOS int13
devices. I'm less worried about non-disk devices right now, I'm concerned
about being able to boot from disk devices.

> As for USB storage devices, I don't know if they all contain serial
> numbers that are unique, you might want to go ask the author of the
> usb-storage driver, Matt Dharm.

So the USB device structure isn't the right thing to look at, but us_data
which keeps the GUID probably is. It's got a pointer to the Scsi_Host,
which has its PCI information.

Thanks,
Matt

--
Matt Domsch
Sr. Software Engineer, Lead Engineer, Architect
Dell Linux Solutions http://www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com

2002-09-27 04:37:20

by Greg KH

[permalink] [raw]
Subject: Re: devicefs requests

On Thu, Sep 26, 2002 at 11:13:37AM -0500, [email protected] wrote:
>
> What I'm picturing is something like this (feedback welcome!):

<nice picture snipped>

Yes, I think this is a nice goal, and that driverfs is the right way to
do this. But you might want to walk the bus lists of the different
devices a bit differently. Here's a small example of how to walk all of
the USB devices in a system, and see if they match a specific vendor_id
and product_id:


static int match_device (struct usb_device *dev)
{
int retval = -ENODEV;
int child;

dbg ("looking at vendor %d, product %d\n",
dev->descriptor.idVendor,
dev->descriptor.idProduct);

/* see if this device matches */
if ((dev->descriptor.idVendor == vendor_id) &&
(dev->descriptor.idProduct == product_id)) {
dbg ("found the device!\n");
retval = 0;
goto exit;
}

/* look through all of the children of this device */
for (child = 0; child < dev->maxchild; ++child) {
if (dev->children[child]) {
retval = match_device (dev->children[child]);
if (retval == 0)
goto exit;
}
}
exit:
return retval;
}

static int find_usb_device (void)
{
struct list_head *buslist;
struct usb_bus *bus;
int retval = -ENODEV;

down (&usb_bus_list_lock);
for (buslist = usb_bus_list.next;
buslist != &usb_bus_list;
buslist = buslist->next) {
bus = container_of (buslist, struct usb_bus, bus_list);
retval = match_device(bus->root_hub);
if (retval == 0)
goto exit;
}
exit:
up (&usb_bus_list_lock);
return retval;
}

I think usb_bus_list_lock and usb_bus_list needs to be exported for
these functions to work outside of the USB core, but if you need them,
I'd don't have a problem with exporting them.

Doing something like this might be easier than trying to get the driver
core to let you walk all of its devices. But Pat could answer that
better than I could.

Good luck,

greg k-h

2002-10-01 01:24:40

by Patrick Mochel

[permalink] [raw]
Subject: Re: devicefs requests


> 1) As new drivers pick up the model, check that all xxx_bus_type objects
> get EXPORT_SYMBOLd and included in a include/xxxx header somewhere - My BIOS
> EDD code walks the list of bus types looking for attached devices to compare
> against (pci, ide, scsi, usb, ...).
> ide_bus_type is in include/linux/ide.h but isn't EXPORT_SYMBOL;
> usb_bus_type is in include/linux/usb.h but isn't EXPORT_SYMBOL;

Yes, sorry about that. I think I've added most of them, and forgot to
export them..

> Alternately, keep the list of registered bus types accessible via a
> list_for_each type macro. I like the exported symbols myself, it lets me
> do:

There is a master bus list: bus_drivers_list in drivers/base/bus.c. It
could easily be exportable, and may be a good idea for you firmware
people.

> static const struct edd_known_bus_types_s edd_known_bus_types[] = {
> {bus:&scsi_driverfs_bus_type, edd_type: "SCSI", match:
> edd_match_scsidev},
> // {bus:&ide_bus_type, edd_type: "ATA", match: NULL},
> // {bus:&usb_bus_type, edd_type: "USB", match: NULL},
> {bus:NULL, edd_type: NULL, match: NULL},
> };
>
> so I can supply my own match functions which match one type of device (e.g.
> EDD's idea of a SCSI device) to that of the standard device. I could
> accomplish the same using well-known names for bus_type I suppose, and doing
> a list_for_each until I find it. Just a different thing getting exported, a
> well-known name and a lookup method rather than the symbol itself.

Don't rely on the name, as it could change. It could, but at least the
compiler will warn you..

> 2) bus_for_each_dev() is really restrictive right now due to all the locking
> mechanisms in place. In my code I'd like to, given a struct device *, walk
> a list of devices on a given bus and compare each device with the given
> device, returning a match, or not. As it stands, bus_for_each_dev returns
> either success (the callback worked for each device on the list), or failure
> (the callback failed for some device on the list), but I don't see a
> mechanism to return which device failed without excessive abuse of the
> void*. For now I've made a private copy of bus_for_each_dev which I've
> mucked with the return the properly matching device, and wonder if this
> couldn't be made more generic somehow.

Yes, those helpers are restrictive, and not very useful to you in that
case. It's easy to make more complex versions, but I fear the resulting
code..

-pat

2002-10-01 01:32:15

by Patrick Mochel

[permalink] [raw]
Subject: RE: devicefs requests


On Wed, 25 Sep 2002 [email protected] wrote:

> > But what do you do with the usb_bus_type? Why would your code use
> > anything that is private to the driver core?
>
> Fair enough. I actually only need the 64-bit unique ID that the USB device
> provides, and its parent PCI device. EDD provides this info as x86 BIOS
> sees it, so my code compares the two, and will make a symlink between the
> two. This lets the OS know which device BIOS thinks it is (i.e. to know
> what disk you're booting from).
>
> True, I don't (today) see a unique ID in struct usb_device. Hopefully
> that's something that can be added in the future. Functions which expose
> this info separate from exporting the bus type would be great.

UUIDs are something that many people have asked for in struct device. I've
put it off because they're used in only a few places today, because it's
impossible to standardize them across different device types, and it's
difficult to extract one from devices that don't inherently support them.

It's a valid request though. What we've talked about is:

- making it struct device::char * uuid;

- the bus that discovers the device is responsible for allocating and
freeing the field.

- It must be a NULL-terminated ASCII string.

- It will be exported in the device's drivefs directory in a file 'uuid'.

Anything else?

-pat