2007-08-20 22:55:28

by Tony Jones

[permalink] [raw]
Subject: [patch 09/14] Convert from class_device to device for SPI

--
Content-Disposition: inline; filename=spi.patch

Convert from class_device to device for drivers/spi. This is part of the work
to eliminate struct class_device.

---
drivers/spi/spi.c | 36 ++++++++++++++++++------------------
drivers/spi/spi_bitbang.c | 2 +-
drivers/spi/spi_lm70llp.c | 2 +-
include/linux/spi/spi.h | 12 ++++++------
4 files changed, 26 insertions(+), 26 deletions(-)

--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -207,7 +207,7 @@ struct spi_device *spi_new_device(struct
struct spi_board_info *chip)
{
struct spi_device *proxy;
- struct device *dev = master->cdev.dev;
+ struct device *dev = master->dev.parent;
int status;

/* NOTE: caller did any chip->bus_num checks necessary.
@@ -242,7 +242,7 @@ struct spi_device *spi_new_device(struct
proxy->modalias = chip->modalias;

snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
- "%s.%u", master->cdev.class_id,
+ "%s.%u", master->dev.bus_id,
chip->chip_select);
proxy->dev.parent = dev;
proxy->dev.bus = &spi_bus_type;
@@ -341,18 +341,18 @@ static void scan_boardinfo(struct spi_ma

/*-------------------------------------------------------------------------*/

-static void spi_master_release(struct class_device *cdev)
+static void spi_master_release(struct device *dev)
{
struct spi_master *master;

- master = container_of(cdev, struct spi_master, cdev);
+ master = container_of(dev, struct spi_master, dev);
kfree(master);
}

static struct class spi_master_class = {
.name = "spi_master",
.owner = THIS_MODULE,
- .release = spi_master_release,
+ .dev_release = spi_master_release,
};


@@ -360,7 +360,7 @@ static struct class spi_master_class = {
* spi_alloc_master - allocate SPI master controller
* @dev: the controller, possibly using the platform_bus
* @size: how much zeroed driver-private data to allocate; the pointer to this
- * memory is in the class_data field of the returned class_device,
+ * memory is in the driver_data field of the returned device,
* accessible with spi_master_get_devdata().
* Context: can sleep
*
@@ -386,9 +386,9 @@ struct spi_master *spi_alloc_master(stru
if (!master)
return NULL;

- class_device_initialize(&master->cdev);
- master->cdev.class = &spi_master_class;
- master->cdev.dev = get_device(dev);
+ device_initialize(&master->dev);
+ master->dev.class = &spi_master_class;
+ master->dev.parent = get_device(dev);
spi_master_set_devdata(master, &master[1]);

return master;
@@ -418,7 +418,7 @@ EXPORT_SYMBOL_GPL(spi_alloc_master);
int spi_register_master(struct spi_master *master)
{
static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
- struct device *dev = master->cdev.dev;
+ struct device *dev = master->dev.parent;
int status = -ENODEV;
int dynamic = 0;

@@ -443,12 +443,12 @@ int spi_register_master(struct spi_maste
/* register the device, then userspace will see it.
* registration fails if the bus ID is in use.
*/
- snprintf(master->cdev.class_id, sizeof master->cdev.class_id,
+ snprintf(master->dev.bus_id, sizeof master->dev.bus_id,
"spi%u", master->bus_num);
- status = class_device_add(&master->cdev);
+ status = device_add(&master->dev);
if (status < 0)
goto done;
- dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id,
+ dev_dbg(dev, "registered master %s%s\n", master->dev.bus_id,
dynamic ? " (dynamic)" : "");

/* populate children from any spi device tables */
@@ -481,8 +481,8 @@ void spi_unregister_master(struct spi_ma
{
int dummy;

- dummy = device_for_each_child(master->cdev.dev, NULL, __unregister);
- class_device_unregister(&master->cdev);
+ dummy = device_for_each_child(master->dev.parent, NULL, __unregister);
+ device_unregister(&master->dev);
}
EXPORT_SYMBOL_GPL(spi_unregister_master);

@@ -498,13 +498,13 @@ EXPORT_SYMBOL_GPL(spi_unregister_master)
*/
struct spi_master *spi_busnum_to_master(u16 bus_num)
{
- struct class_device *cdev;
+ struct device *dev;
struct spi_master *master = NULL;
struct spi_master *m;

down(&spi_master_class.sem);
- list_for_each_entry(cdev, &spi_master_class.children, node) {
- m = container_of(cdev, struct spi_master, cdev);
+ list_for_each_entry(dev, &spi_master_class.children, node) {
+ m = container_of(dev, struct spi_master, dev);
if (m->bus_num == bus_num) {
master = spi_master_get(m);
break;
--- a/drivers/spi/spi_lm70llp.c
+++ b/drivers/spi/spi_lm70llp.c
@@ -82,7 +82,7 @@ struct spi_lm70llp {
struct pardevice *pd;
struct spi_device *spidev_lm70;
struct spi_board_info info;
- struct class_device *cdev;
+ //struct device *dev;
};

/* REVISIT : ugly global ; provides "exclusive open" facility */
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -195,7 +195,7 @@ static inline void spi_unregister_driver

/**
* struct spi_master - interface to SPI master controller
- * @cdev: class interface to this driver
+ * @dev: device interface to this driver
* @bus_num: board-specific (and often SOC-specific) identifier for a
* given SPI controller.
* @num_chipselect: chipselects are used to distinguish individual
@@ -222,7 +222,7 @@ static inline void spi_unregister_driver
* message's completion function when the transaction completes.
*/
struct spi_master {
- struct class_device cdev;
+ struct device dev;

/* other than negative (== assign one dynamically), bus_num is fully
* board-specific. usually that simplifies to being SOC-specific.
@@ -268,17 +268,17 @@ struct spi_master {

static inline void *spi_master_get_devdata(struct spi_master *master)
{
- return class_get_devdata(&master->cdev);
+ return dev_get_drvdata(&master->dev);
}

static inline void spi_master_set_devdata(struct spi_master *master, void *data)
{
- class_set_devdata(&master->cdev, data);
+ dev_set_drvdata(&master->dev, data);
}

static inline struct spi_master *spi_master_get(struct spi_master *master)
{
- if (!master || !class_device_get(&master->cdev))
+ if (!master || !get_device(&master->dev))
return NULL;
return master;
}
@@ -286,7 +286,7 @@ static inline struct spi_master *spi_mas
static inline void spi_master_put(struct spi_master *master)
{
if (master)
- class_device_put(&master->cdev);
+ put_device(&master->dev);
}


--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -472,7 +472,7 @@ int spi_bitbang_start(struct spi_bitbang
/* this task is the only thing to touch the SPI bits */
bitbang->busy = 0;
bitbang->workqueue = create_singlethread_workqueue(
- bitbang->master->cdev.dev->bus_id);
+ bitbang->master->dev.parent->bus_id);
if (bitbang->workqueue == NULL) {
status = -EBUSY;
goto err1;

--


2007-08-21 15:03:26

by Tony Jones

[permalink] [raw]
Subject: Re: [patch 09/14] Convert from class_device to device for SPI

On Mon, Aug 20, 2007 at 03:48:15PM -0700, [email protected] wrote:
> --
> Content-Disposition: inline; filename=spi.patch
>
> Convert from class_device to device for drivers/spi. This is part of the work
> to eliminate struct class_device.

Signed-off-by: Tony Jones <[email protected]>

2007-08-21 18:36:56

by David Brownell

[permalink] [raw]
Subject: Re: [patch 09/14] Convert from class_device to device for SPI

On Tuesday 21 August 2007, Tony Jones wrote:
> On Mon, Aug 20, 2007 at 03:48:15PM -0700, [email protected] wrote:
> >
> > Convert from class_device to device for drivers/spi. This is part of the work
> > to eliminate struct class_device.
>
> Signed-off-by: Tony Jones <[email protected]>

Yeah, "no signoff" was one of my first reactions to that. :)


Can you update the Documentation/spi/spi-summary text which is
invalidated by this change? That's part of why I rejected an
earlier version of this patch: since it broke the documentation,
it was incomplete.

The other reason was to explore removing the "struct class" too,
since it's not necessary. But it turns out to be simpler to
keep it in there to allocate the bus IDs. So I've changed my
mind, and will merge a patch like $SUBJECT if it's complete
(i.e. doesn't leave broken/invalid docs).

- Dave

2007-08-21 18:50:27

by Tony Jones

[permalink] [raw]
Subject: Re: [patch 09/14] Convert from class_device to device for SPI

On Tue, Aug 21, 2007 at 11:28:28AM -0700, David Brownell wrote:
> On Tuesday 21 August 2007, Tony Jones wrote:
> > On Mon, Aug 20, 2007 at 03:48:15PM -0700, [email protected] wrote:
> > >
> > > Convert from class_device to device for drivers/spi. This is part of the work
> > > to eliminate struct class_device.
> >
> > Signed-off-by: Tony Jones <[email protected]>
>
> Yeah, "no signoff" was one of my first reactions to that. :)

Yeah, sorry, had it in the first patch but cut-n-pasted it into oblivion :)

> Can you update the Documentation/spi/spi-summary text which is
> invalidated by this change? That's part of why I rejected an

Will do. Thanks!

Tony

2007-08-22 03:07:01

by Tony Jones

[permalink] [raw]
Subject: Re: [patch 09/14] Convert from class_device to device for SPI

On Tue, Aug 21, 2007 at 11:28:28AM -0700, David Brownell wrote:
> Can you update the Documentation/spi/spi-summary text which is
> invalidated by this change? That's part of why I rejected an
> earlier version of this patch: since it broke the documentation,
> it was incomplete.

I believe this is the necessary documentation changes. Alas I can't write
verbiage you are necessarily happy with, only you can do that, if there is
a factual error, I'll be happy to correct but feel free to edit for personal
style. I'll be gone thru Sunday so if it needs more adjustment I'll do it
then.

Tony

------------------------------------------------------------------------------

Convert from class_device to device for drivers/spi. This is part of the work
to eliminate struct class_device.

Signed-off-by: Tony Jones <[email protected]>

---
Documentation/spi/spi-summary | 13 +++++++------
drivers/spi/spi.c | 36 ++++++++++++++++++------------------
drivers/spi/spi_bitbang.c | 2 +-
drivers/spi/spi_lm70llp.c | 2 +-
include/linux/spi/spi.h | 12 ++++++------
5 files changed, 33 insertions(+), 32 deletions(-)

--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -207,7 +207,7 @@ struct spi_device *spi_new_device(struct
struct spi_board_info *chip)
{
struct spi_device *proxy;
- struct device *dev = master->cdev.dev;
+ struct device *dev = master->dev.parent;
int status;

/* NOTE: caller did any chip->bus_num checks necessary.
@@ -242,7 +242,7 @@ struct spi_device *spi_new_device(struct
proxy->modalias = chip->modalias;

snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id,
- "%s.%u", master->cdev.class_id,
+ "%s.%u", master->dev.bus_id,
chip->chip_select);
proxy->dev.parent = dev;
proxy->dev.bus = &spi_bus_type;
@@ -341,18 +341,18 @@ static void scan_boardinfo(struct spi_ma

/*-------------------------------------------------------------------------*/

-static void spi_master_release(struct class_device *cdev)
+static void spi_master_release(struct device *dev)
{
struct spi_master *master;

- master = container_of(cdev, struct spi_master, cdev);
+ master = container_of(dev, struct spi_master, dev);
kfree(master);
}

static struct class spi_master_class = {
.name = "spi_master",
.owner = THIS_MODULE,
- .release = spi_master_release,
+ .dev_release = spi_master_release,
};


@@ -360,7 +360,7 @@ static struct class spi_master_class = {
* spi_alloc_master - allocate SPI master controller
* @dev: the controller, possibly using the platform_bus
* @size: how much zeroed driver-private data to allocate; the pointer to this
- * memory is in the class_data field of the returned class_device,
+ * memory is in the driver_data field of the returned device,
* accessible with spi_master_get_devdata().
* Context: can sleep
*
@@ -386,9 +386,9 @@ struct spi_master *spi_alloc_master(stru
if (!master)
return NULL;

- class_device_initialize(&master->cdev);
- master->cdev.class = &spi_master_class;
- master->cdev.dev = get_device(dev);
+ device_initialize(&master->dev);
+ master->dev.class = &spi_master_class;
+ master->dev.parent = get_device(dev);
spi_master_set_devdata(master, &master[1]);

return master;
@@ -418,7 +418,7 @@ EXPORT_SYMBOL_GPL(spi_alloc_master);
int spi_register_master(struct spi_master *master)
{
static atomic_t dyn_bus_id = ATOMIC_INIT((1<<15) - 1);
- struct device *dev = master->cdev.dev;
+ struct device *dev = master->dev.parent;
int status = -ENODEV;
int dynamic = 0;

@@ -443,12 +443,12 @@ int spi_register_master(struct spi_maste
/* register the device, then userspace will see it.
* registration fails if the bus ID is in use.
*/
- snprintf(master->cdev.class_id, sizeof master->cdev.class_id,
+ snprintf(master->dev.bus_id, sizeof master->dev.bus_id,
"spi%u", master->bus_num);
- status = class_device_add(&master->cdev);
+ status = device_add(&master->dev);
if (status < 0)
goto done;
- dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id,
+ dev_dbg(dev, "registered master %s%s\n", master->dev.bus_id,
dynamic ? " (dynamic)" : "");

/* populate children from any spi device tables */
@@ -481,8 +481,8 @@ void spi_unregister_master(struct spi_ma
{
int dummy;

- dummy = device_for_each_child(master->cdev.dev, NULL, __unregister);
- class_device_unregister(&master->cdev);
+ dummy = device_for_each_child(master->dev.parent, NULL, __unregister);
+ device_unregister(&master->dev);
}
EXPORT_SYMBOL_GPL(spi_unregister_master);

@@ -498,13 +498,13 @@ EXPORT_SYMBOL_GPL(spi_unregister_master)
*/
struct spi_master *spi_busnum_to_master(u16 bus_num)
{
- struct class_device *cdev;
+ struct device *dev;
struct spi_master *master = NULL;
struct spi_master *m;

down(&spi_master_class.sem);
- list_for_each_entry(cdev, &spi_master_class.children, node) {
- m = container_of(cdev, struct spi_master, cdev);
+ list_for_each_entry(dev, &spi_master_class.children, node) {
+ m = container_of(dev, struct spi_master, dev);
if (m->bus_num == bus_num) {
master = spi_master_get(m);
break;
--- a/drivers/spi/spi_lm70llp.c
+++ b/drivers/spi/spi_lm70llp.c
@@ -82,7 +82,7 @@ struct spi_lm70llp {
struct pardevice *pd;
struct spi_device *spidev_lm70;
struct spi_board_info info;
- struct class_device *cdev;
+ //struct device *dev;
};

/* REVISIT : ugly global ; provides "exclusive open" facility */
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -195,7 +195,7 @@ static inline void spi_unregister_driver

/**
* struct spi_master - interface to SPI master controller
- * @cdev: class interface to this driver
+ * @dev: device interface to this driver
* @bus_num: board-specific (and often SOC-specific) identifier for a
* given SPI controller.
* @num_chipselect: chipselects are used to distinguish individual
@@ -222,7 +222,7 @@ static inline void spi_unregister_driver
* message's completion function when the transaction completes.
*/
struct spi_master {
- struct class_device cdev;
+ struct device dev;

/* other than negative (== assign one dynamically), bus_num is fully
* board-specific. usually that simplifies to being SOC-specific.
@@ -268,17 +268,17 @@ struct spi_master {

static inline void *spi_master_get_devdata(struct spi_master *master)
{
- return class_get_devdata(&master->cdev);
+ return dev_get_drvdata(&master->dev);
}

static inline void spi_master_set_devdata(struct spi_master *master, void *data)
{
- class_set_devdata(&master->cdev, data);
+ dev_set_drvdata(&master->dev, data);
}

static inline struct spi_master *spi_master_get(struct spi_master *master)
{
- if (!master || !class_device_get(&master->cdev))
+ if (!master || !get_device(&master->dev))
return NULL;
return master;
}
@@ -286,7 +286,7 @@ static inline struct spi_master *spi_mas
static inline void spi_master_put(struct spi_master *master)
{
if (master)
- class_device_put(&master->cdev);
+ put_device(&master->dev);
}


--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -472,7 +472,7 @@ int spi_bitbang_start(struct spi_bitbang
/* this task is the only thing to touch the SPI bits */
bitbang->busy = 0;
bitbang->workqueue = create_singlethread_workqueue(
- bitbang->master->cdev.dev->bus_id);
+ bitbang->master->dev.parent->bus_id);
if (bitbang->workqueue == NULL) {
status = -EBUSY;
goto err1;
--- a/Documentation/spi/spi-summary
+++ b/Documentation/spi/spi-summary
@@ -167,9 +167,9 @@ shows up in sysfs in several locations:

/sys/bus/spi/drivers/D ... driver for one or more spi*.* devices

- /sys/class/spi_master/spiB ... class device for the controller
- managing bus "B". All the spiB.* devices share the same
- physical SPI bus segment, with SCLK, MOSI, and MISO.
+ /sys/class/spi_master/spiB ... device for the controller managing bus "B".
+ All the spiB.* devices share the same physical SPI bus segment, with
+ SCLK, MOSI, and MISO.


How does board-specific init code declare SPI devices?
@@ -337,7 +337,8 @@ SPI protocol drivers somewhat resemble p

The driver core will autmatically attempt to bind this driver to any SPI
device whose board_info gave a modalias of "CHIP". Your probe() code
-might look like this unless you're creating a class_device:
+might look like this unless you're creating a device which is managing a bus
+(appearing under /sys/class/spi_master).

static int __devinit CHIP_probe(struct spi_device *spi)
{
@@ -442,7 +443,7 @@ An SPI controller will probably be regis
a driver to bind to the device, whichever bus is involved.

The main task of this type of driver is to provide an "spi_master".
-Use spi_alloc_master() to allocate the master, and class_get_devdata()
+Use spi_alloc_master() to allocate the master, and spi_master_get_devdata()
to get the driver-private data allocated for that device.

struct spi_master *master;
@@ -452,7 +453,7 @@ to get the driver-private data allocated
if (!master)
return -ENODEV;

- c = class_get_devdata(&master->cdev);
+ c = spi_master_get_devdata(master);

The driver will initialize the fields of that spi_master, including the
bus number (maybe the same as the platform device ID) and three methods


2007-08-23 21:54:49

by David Brownell

[permalink] [raw]
Subject: Re: [patch 09/14] Convert from class_device to device for SPI

On Tuesday 21 August 2007, Tony Jones wrote:
> I believe this is the necessary documentation changes.

Thanks. I have an update, plus updates for the mmc_spi
driver (now in MM) which you didn't update.

By the way, it's worth noting an incompatibility introduced
through these conversions and CONFIG_SYSFS_DEPRECATED=n:

- previously .../controller/spi_master:spi2 would be a
symlink to /sys/class/spi_master/spi2

- now, /sys/class/spi_master/spi2 is a symlink to
.../controller/spi_master (with DEPRECATED=n).

The symlink direction is just noise ... the issue is that with
this approach it's no longer possible to have one controller
handle multiple SPI busses! A fix would involve maintaining
the original "spi_master:spi2" name.

I don't happen to know of such a controller, and one would
surprise me a bit. Exactly like the fact that several I2C
adapters work that way was a surprise: one PCI function
controlling several different I2C busses, rather than one
function per bus.

- Dave

2007-08-23 22:08:50

by Kay Sievers

[permalink] [raw]
Subject: Re: [patch 09/14] Convert from class_device to device for SPI

On Thu, 2007-08-23 at 14:03 -0700, David Brownell wrote:
> On Tuesday 21 August 2007, Tony Jones wrote:
> > I believe this is the necessary documentation changes.
>
> Thanks. I have an update, plus updates for the mmc_spi
> driver (now in MM) which you didn't update.
>
> By the way, it's worth noting an incompatibility introduced
> through these conversions and CONFIG_SYSFS_DEPRECATED=n:
>
> - previously .../controller/spi_master:spi2 would be a
> symlink to /sys/class/spi_master/spi2

These "find the class device which has me as the parent"-symlinks are
removed with CONFIG_SYSFS_DEPRECATED=n, because these devices are direct
child directories now below the bus device and there is no need for such
links.

> - now, /sys/class/spi_master/spi2 is a symlink to
> .../controller/spi_master (with DEPRECATED=n).

Ugh! Are you sure, that is doesn't point to:
.../controller/spi_master/spi2/ ?

> The symlink direction is just noise ... the issue is that with
> this approach it's no longer possible to have one controller
> handle multiple SPI busses! A fix would involve maintaining
> the original "spi_master:spi2" name.

Sounds like a bug if that's what happened. Can you paste the output of
"tree" for the relevant parts here?

Thanks,
Kay


2007-08-26 19:54:26

by David Brownell

[permalink] [raw]
Subject: Re: [patch 09/14] Convert from class_device to device for SPI

On Thursday 23 August 2007, Kay Sievers wrote:
> On Thu, 2007-08-23 at 14:03 -0700, David Brownell wrote:
> > On Tuesday 21 August 2007, Tony Jones wrote:
> > > I believe this is the necessary documentation changes.
> >
> > Thanks. I have an update, plus updates for the mmc_spi
> > driver (now in MM) which you didn't update.
> >
> > By the way, it's worth noting an incompatibility introduced
> > through these conversions and CONFIG_SYSFS_DEPRECATED=n:
> >
> > ...
> >
> > - now, /sys/class/spi_master/spi2 is a symlink to
> > .../controller/spi_master (with DEPRECATED=n).
>
> Ugh! Are you sure, that is doesn't point to:
> .../controller/spi_master/spi2/ ?

Turns out that it does -- once you tell Minicom to change its
bogus default of discarding data rather than line wrapping!
Which means there can still be multiple class instances that
get coupled to a given physical device; no lossage there.

Sigh. It's hard sometimes to remember to apply all the
right bug workarounds, when some of them are in userspace.

Still, that's a needless incompatibility. Why isn't that
pointing to a .../controller/spi_master:spi2 directory,
so that the pathnames don't change (only symlink polarity)?

- Dave

2007-08-26 20:17:06

by Kay Sievers

[permalink] [raw]
Subject: Re: [patch 09/14] Convert from class_device to device for SPI

On Sun, 2007-08-26 at 12:54 -0700, David Brownell wrote:
> On Thursday 23 August 2007, Kay Sievers wrote:
> > On Thu, 2007-08-23 at 14:03 -0700, David Brownell wrote:
> > > On Tuesday 21 August 2007, Tony Jones wrote:
> > > > I believe this is the necessary documentation changes.
> > >
> > > Thanks. I have an update, plus updates for the mmc_spi
> > > driver (now in MM) which you didn't update.
> > >
> > > By the way, it's worth noting an incompatibility introduced
> > > through these conversions and CONFIG_SYSFS_DEPRECATED=n:
> > >
> > > ...
> > >
> > > - now, /sys/class/spi_master/spi2 is a symlink to
> > > .../controller/spi_master (with DEPRECATED=n).
> >
> > Ugh! Are you sure, that is doesn't point to:
> > .../controller/spi_master/spi2/ ?
>
> Turns out that it does -- once you tell Minicom to change its
> bogus default of discarding data rather than line wrapping!
> Which means there can still be multiple class instances that
> get coupled to a given physical device; no lossage there.

Great.

> Sigh. It's hard sometimes to remember to apply all the
> right bug workarounds, when some of them are in userspace.

Yeah, it's a mess, I totally know that feeling. :)

> Still, that's a needless incompatibility. Why isn't that
> pointing to a .../controller/spi_master:spi2 directory,
> so that the pathnames don't change (only symlink polarity)?

The directory name is the kernel's kobject name used by userspace, we
can't change the name. Most of these names are used to name the device
nodes.

Also the link would just point to the direct child directory with the
same name, which would be kind of strange. We could add them back, if
really needed, but they didn't exist for long, so we think it's fine to
get rid of them when !DEPRECATED is used.

With the hierarchy of class devices in recently changed subsytems, it
would be totally inconsistent to make a difference between a class
device parent/child (no "device" link, no <class>:<devname> link) and a
bus device parent/child (links). For userspace, there is no interesting
difference between class or bus device parents.

These links are really only needed with the !DEPRECATED mode, with the
directories all spread around in different places, and you need to use
these magic links to reconstruct the virtual device tree from it. They
are the counterpart of the "device" link which is also not too useful in
!DEPRECATED mode, because it's always just the next parent device.

With !DEPRECATED we get a big unified device tree with all devices in
_one_ hierarchy. All Child/parent relationships can be read by just
walking the up and down the tree. All the classification directories
(bus/, class/, block/) will only be lists of symlinks pointing to a
specific entry point in the unified tree. From there you can walk upward
or downwards the path, without any magic rules.

Thanks,
Kay