Subject: Re: Device Properties: The Next Generation
To: None <cgd@sibyte.com, eeh@netbsd.org>
From: None <eeh@netbsd.org>
List: tech-kern
Date: 02/16/2001 04:25:30
	eeh@netbsd.org writes:
	> 	I didn't get anything from your latest message that said "checks to
	> 	see if it's unused" or similar...
	> 
	> 	(how do you propose to do this?)
	> 
	> Simple: a device is not used if it's not linked in to
	> the device tree (dv_parent is NULL and dv_list.tqe_next
	> is NULL).

	This is fairly ... "magical" from the perspective of the caller.

	It really seems best to me to not magically re-use the containers
	they're providing, and punt on the whole 'is it used' question.  if
	they make it it's fake, if it's fake it stays fake, and if they try to
	destroy something non-fake, they die.

	If you're going to make a create-and-hand-off interface, go all the
	way: make config_found() or config_search() actually consume the
	device container provided for them.  (I.e. it's used for a device, or
	it's destroyed.)  If you get a ptr back, something was attached.  If
	you get NULL back, nothing was and for that device you're done.

	Personally, though, i prefer to avoid create-and-hand-off interfaces
	except where there's some overriding reason to use them.

	What you've proposed in the last draft and/or your followup messages
	seems to be 'create and kind-of hand off but still require effort to
	be done' thing, which will cause more problems than either a
	create-and-hand-off or create-loan-destroy interface...

Ideally, it is not a create-and-hand-off interface, but a
create-and-give-me-an-early-peak interface.  Solaris uses
callbacks for this, which causes problems when trying to
pass state around.  I think returning a pointer to it is
better than a callback.

The only reason for the separate destructor call was because
the first implementation must reallocate the device structure
to resize it for the appropriate softc.  It could easily destroy
the structure instead.

	> No.  A device does not have parents until it's linked into
	> the device tree.  If an attach routine wants to query its
	> parent's properties it is passed in the pointer to its
	> parent and can query it directly.

	I guess this fits in with the notion that inheritance is ~never to be
	used.

	(I find that kind of unfortunate, since it means that a _lot_ of
	memory will be wasted for inheritable things...  *sigh*)

Well, at attach time the device is in the tree so inheritence
will work.  And the parent device is always in the tree and
can be queried using inheritence at any time.

It would be possible to pass the parent device node in to
dev_create() so it is attached in the right place on creation.
That would make inheritance work, but then you have issues
about empty device nodes in the device tree.

The reason you need to be careful about inheritence is that
you don't know where the property is coming from.  If it comes
from the wrong place it could be the wrong property.  If you
want to query your "frequency" but you don't have the property
and mainbus does, and you enable inheritence, you will get the
mainbus "frequency" property which may be completely different
from your property.

You do not want to use inheritence when searching to decide what
type of bus you're attached to because you may search too far and
thing you're on a different type of bus altogether.


	> 	you've gotta be very careful about whether or not you use
	> 	PROP_INHERIT.  (I'd expect that, in general, you'd always say "yes, do
	> 	inherit."  What are you expecting the default usage to be?  Or do you
	> 	think it'll really depend on which attribute you're asking about?)
	> 
	> It really depends on the attribute.  This is mostly useful when
	> a device doesn't really know how many nodes are between it and
	> the node that contains the values it needs, such as when there 
	> are several bridges between a card and the bus controller.
	> [ ... ]
	> In general, the parent should attach properties a device should
	> use to the device node.  That way the device would query itself
	> to find what properties it should use.  Inheritence should be
	> used for obscure things such as when a driver needs to know the
	> frequency of the bus it's attached to.

	Actually, right now, bus speed is something passed down via aux on at
	least some busses, because it's "important enough."

Just as `aux' is a protocol that must be designed for
each set of parent and child devices, properties need
to be used in an appropriate protocol.

	believe it or not, I think that in fact you might want 'speed' to be
	set closer to the device, in terms of the inheritance chain, than bus
	chipset info.  consider a (taken from real life) example like:

		rfpchb
		pci @ rfpchb		# really fast pci-like bus; not exactly PCI,
					# but OS software can't tell the diff.
		ppb @ rfpci		# really fast -> 64x66 bridge
		dev @ ppb

	the bus chipset info should be provided by rfpchb.  The clock speed
	could be provided by rfpchb and by ppb.

	This use of inheritance seems inconsistent.  If you're going to get
	bus speed via inheritance, why wouldn't you also get other bus chipset
	information of various varieties?  It's absolutely unchanging, and you
	may not know the distance between you and the bus bridge...  I don't
	understand how it's different than 'speed,' except that it happens to
	be used more often.

It depends on:

1) How important it is to you.

2) How important the parent device thinks it is.

3) Where the property is located with respect to you.


	It's not like lookup speed matters; you do the lookup once at match
	time & once at attach time, then you're done...

	If you think about a hypothetical utility to dump properties
	associated with a device... why would the bus chipset info be
	associated with a device, any more than the bus speed is?

	Do you have another example?  I'm thinking, if you don't want to use
	inheritance for obvious stuff like bus chipset info, why in fact would
	you want to use it at all?



	Also, it seems that several of your suggestions so far have assumed a
	set of expected properties that would be used.  Can you provide a
	list?  (such a list should come with the documentation for a change
	like this anyway... 8-)

O.K.  The way properties are used on Solaris is to provide
devices with things like their SCSI ID, SBus slot, physical
address, etc.

Let's take a typical excerpt from a SPARC's device properties
as an example.  Now Solaris likes to use properties to display
state information, which I consider a particularly evil thing
to do, so ignore those bits:

    sbus, instance #0

This is the SBus controller.

        Driver properties:
            name <interrupt-priorities> length <24>
                value <0x0000000c0000000b0000000c0000000c000000090000000c>.

Here is all the register information:

        Register Specifications:
            Bus Type=0x1fe, Address=0x0, Size=0x8000
        Range Specifications:
            Ch: 00,00000000 Pa: 1ff,00000000, Sz: 10000000
            Ch: 01,00000000 Pa: 1ff,10000000, Sz: 10000000
            Ch: 02,00000000 Pa: 1ff,20000000, Sz: 10000000
            Ch: 03,00000000 Pa: 1ff,30000000, Sz: 10000000
            Ch: 0d,00000000 Pa: 1ff,d0000000, Sz: 10000000
            Ch: 0e,00000000 Pa: 1ff,e0000000, Sz: 10000000
            Ch: 0f,00000000 Pa: 1ff,f0000000, Sz: 10000000
        SUNW,CS4231 (driver not attached)
        auxio (driver not attached)
        flashprom (driver not attached)
        SUNW,fdtwo (driver not attached)
        eeprom (driver not attached)
        zs, instance #0

Register information for the `zs' chip:

            Register Specifications:
                Bus Type=0xf, Address=0x1100000, Size=0x4
        zs, instance #1
            Register Specifications:
                Bus Type=0xf, Address=0x1000000, Size=0x4
        sc (driver not attached)
        SUNW,pll (driver not attached)
        espdma, instance #0

`esp' contoller:

            Register Specifications:
                Bus Type=0xe, Address=0x8400000, Size=0x10
            esp, instance #0
                Driver properties:

Some of these properties are from config
files:

                    name <target6-sync-speed> length <4>
                        value <0x00002710>.
                    name <target4-sync-speed> length <4>
                        value <0x00002710>.
                    name <target3-sync-speed> length <4>
                        value <0x00002710>.
                    name <target1-sync-speed> length <4>
                        value <0x00002710>.
                    name <target0-sync-speed> length <4>
                        value <0x00002710>.
                    name <target4-TQ> length <0> -- <no value>.
                    name <target3-TQ> length <0> -- <no value>.
                    name <target1-TQ> length <0> -- <no value>.
                    name <target0-TQ> length <0> -- <no value>.
                    name <scsi-selection-timeout> length <4>
                        value <0x000000fa>.
                    name <scsi-options> length <4>
                        value <0x00001ff8>.
                    name <scsi-watchdog-tick> length <4>
                        value <0x0000000a>.
                    name <scsi-tag-age-limit> length <4>
                        value <0x00000002>.
                    name <scsi-reset-delay> length <4>
                        value <0x00000bb8>.
                Register Specifications:
                    Bus Type=0xe, Address=0x8800000, Size=0x40
                sd (driver not attached)
                st (driver not attached)
                sd, instance #0

Here we have a SCSI disk.  The properties
provide the TARGET ID, LUN, class, etc.

                    System properties:
                        name <lun> length <4>
                            value <0x00000000>.
                        name <target> length <4>
                            value <0x00000000>.

The following are interesting.  Driver classes
are used to sort between different buses and bus
protocols.  We could do similarly by specifying
the type of the parent bus with a property.  That
way a device could quickly sort out what type of
bus it's attached to and what properties it needs 
to find.

But that's protocol rather than interface...

                        name <class_prop> length <6>
                            value 'atapi'
                        name <class> length <5>
                            value 'scsi'
                    Driver properties:
                        name <pm-hardware-state> length <21>
                            value 'needs-suspend-resume'
                        name <ddi-kernel-ioctl> length <0> -- <no value>.