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 17:32:44
	[ I hope you're not too annoyed by discussion of this... but I think
	  the goal here really is to come up with the right interface... ]

[Not yet....]

	eeh@netbsd.org writes:
	> 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.

	we already return a pointer (or not) based on whether the device is
	configured, right?  if it's gonna be like this, the caller should
	never have to destroy.

O.K.  Change that so *config_found() always consumes the
peroperty container and either returns a pointer to a full
device or NULL.

	> 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.

	Right, but by your description, inheritance really isn't so useful
	except in fairly abnormal cases.  (That seems like a mistake.)

I never said it wasn't useful.  I said it was dangerous and
should only be used with care or BAD THINGS(tm) can happen.

	> 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.

	Really?  you've got a pointer to a device in the tree from the fake
	property holder, but you don't have to insert the fake property holder
	into the device tree until it's been made real.

So the question is: how important is inheritance during probe?
It could be provided, but has potential complications.  Or it
can be explicitly documented not to work and suggest the use
of the parent device pointer during probe.

	> 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.

	Right, exactly.  That's how I got to the question of, can you delete
	things, whiteout them, or mark a device as 'stopping' the inheritance.

The way to stop inheritence is to define a property with the same
name and different (or no) data at a lower level in the tree.  Then
dev_getprop() will return it rather than one higher up in the tree.

If you want to see a property higher up the tree you can walk the
tree yourself.

Adding whiteouts and/or `stops' will add complexity not only for
property retrieval, both for the retrieval routines and devices
that want to bypass those obstacles and walk the tree themselves,
but also for property creation.  If we would add whiteouts, the
only reasonable way would be to add a flag that's passed in to
dev_setpropt() and attached to a property that tells dev_getprop()
if it's found to immediately terminate the property search and
return an error.  But I don't know what sort of interaction that
would have with md_getprop().

	> 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.

	If you can stop the inheritance, it's _Exactly_ what you want to do.

	If a bus is a SCSI bus or has _any_ other device-specific property
	(e.g. chipset info), why should each child have to be told that
	information separately?  it's wasteful, unnecessary, and puts the data
	in the wrong place.

	If the data's associated with the bus, it should be associated with
	the bus.  If it's associated with the individual children, it should
	be with them.

If you want to do this you really don't want to stop inheritence.
Instead you want each bus node to have a "bus-type" property associated
with it to advertise its type.  Then when a device calls dev_getprop()
with inheritence it will retrieve the lowest "bus-type" property,
which masks out any higher level properties.

Once again this is a protocol rather than functionality issue.  Once
device properties are added and function a set of protocols need to
be defined to describe how they should be used.  I have not done this
since each bus probably has its own issues.


	the problem is, because of the issue of inheritance:

	(1) either you have to waste a bunch of space providing extra
	properties where they really don't make sense (e.g. bus chipset tag
	attached as a device property), or

	(2) you have to provide a way of stopping inheritance at a given level
	where it ceases to make sense, or to delete certain properties.

	One way to do (2) would be to provide a limited form of inheritance,
	like:

		parent			child		child child
		  | props	    props | props      props |   
		  | for		     from | for         from |
		  | children	   parent | children  parent |

	where each | can be (perhaps "must be") a barrier that stops
	inheritance.

I do not think this is needed.  For instance:


	Node		Properties
	---------	--------------
	Top		"bus-type"="root"	"power-management"="off"
	mainbus		"bus-type"="mainbus"
	fhc		"bus-type"="fhc"	"address"=0
	upabus		"bus-type"="upa"	"address"=1
	pci		"bus-type"="pci"	"pcitag"=0xf00
	pci-bridge				"pcitag"=0xbad	"address"=3
	siop		"bus-type"="scsi"	"address"=4
	sd					"address"=0	"lun"=1

Using inheritance, `sd' will see that it's "address" is 0 and "lun" is 1,
so it's disk0, LUN1.  The "bus-type" it sees is "scsi".  In this case, both
"address" and "lun" will be assigned to it either by it's parent or from the
locators.  But to determine the state of "power-management" it needs to
go all the way up to the top device node.

`siop' will attach and find it has "address"=4 assigned to it, which is
where it looks for it's registers.  It is the one that generates the 
"bus-type" field, so when it initialli attaches it queries "bus-type"
and finds "bus-type"="pci" from the `pci' node.  But it finds the
"pcitag"=0xbad from the `pci-bridge' node.

	Do you have any examples where you _really_ need to go over the head
	of a device's parent?

Only for things like that "power-management" attribute that are globally
applicable.

	> 	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.

	Except, (1) is irrelevant.  If the parent device doesn't provide it
	directly, for all you know martians are beaming it into the system.
	It's either given directly to you, or you inherit it from who knows
	where.

If it's extremely important to you, say your register's physical
address, and the parent has not provided it, you cannot attach.
[So either probe should fail or we need to provide some way to
communicate attach failure which I think we should add for cases
like allocation failures.]


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

	Right, sure.

	We need much more than that though if you're going to replace the
	'aux' structures.  (e.g. pointers that don't correspond to real
	hardware stuff, kernel internal stuff, bus_space_tags which may not be
	obviously hardware related...)

There is no reason you can't pass that information through
properties.  The only issue is to make sure that if you
pass pointers through properties, the objects they point
to do not go away unexpectedly.


	> 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.

	You could certainly do that, but I think you're better off doing it
	with separate bus attachments.

	(what if a port doesn't supply headers for all busses?  what if a
	kernel config doesn't include all busses?  what if you want to provide
	a new bus attachment via a loadable module?  etc.)

	I think there's code size savings, as well as more flexibility, by
	keeping bus attachments independent of each other.

I don't want to get into this argument right now.  The
costs/benefits from merging bus attachments will become
more clear after we have been using device properties
for a while.  We should revisit the issue then.

Eduardo