Opened 13 years ago

Last modified 13 years ago

#57 new task

Rework device API: one device in many classes

Reported by: Nicolas Pouillon Owned by: Nicolas Pouillon
Priority: blocker Milestone: Topology handling
Component: drivers Keywords:
Cc:

Description

We currently have a problem with devices that are in more than one driver class at the same time. We have to split them in subdevices, even if it is incorrect.

Some examples:

  • CPU nodes are also ICUs
  • soclib Xicu is timer and ICU

There once was a discussion about allowing devices to implement more than one class at the same time. How to do this ?

Attachments (1)

2010-10-01-multiclass-driver.diff (64.4 KB) - added by Nicolas Pouillon 13 years ago.
PoC

Download all attachments as: .zip

Change History (2)

comment:1 Changed 13 years ago by Nicolas Pouillon

Could we do something like:

API proposal

enum device_class_e
{
    DEVICE_CLASS_FOO,
#if defined(CONFIG_FEATURE_BAR)
    DEVICE_CLASS_BAR,
#endif
    DEVICE_CLASS_COUNT,
};

#define DEVICE_CLASS_UNAVAILABLE 0xff

struct driver_funcs_s
{
    union {
        struct {
            void (*op1)(struct device_s *dev,  );
            void (*op2)(struct device_s *dev,  );
        } foo;
#if defined(CONFIG_FEATURE_BAR)
        struct {
            void (*op1)(struct device_s *dev,  );
            void (*op2)(struct device_s *dev,  );
        } bar;
#endif
    };
}

struct driver_s
{
    error_t (*init)(struct device_s *dev, void *param);
    error_t (*cleanup)(struct device_s *dev);

#if defined(CONFIG_DRIVER_MULTICLASS)
    uint8_t funcs_offset[DEVICE_CLASS_COUNT];
#endif

    struct driver_funcs_s funcs[0];
};

Accessing functions of a given class

const struct driver_funcs_s *driver_class_funcs(
    const struct driver_s *drv,
    enum device_class_e class)
{
#if defined(CONFIG_DRIVER_MULTICLASS)
    const uint8_t offset = drv->funcs_offset[class];

    assert(offset != DEVICE_CLASS_UNAVAILABLE);
#else
    const uint8_t offset = 0;
#endif

    return &drv->funcs[offset];
}

Example for implementing a generic function of class BAR

void device_bar_op1(struct device_s *dev, )
{
    const struct driver_funcs_s *funcs =
        driver_class_funcs(dev->drv, DEVICE_CLASS_BAR);

    return funcs->bar.op1( dev,  );
}

Rationale

Added from current code, there is a new indirection through drv->funcs_offset.

  • There is a cost for a byte load in addition to current implementation
    • but as it is constant, this is cached data.
  • There is a cost for a table of byte
    • but as it is an index in a char, we loose at most DEVICE_CLASS_COUNT bytes per driver.
  • We can still make driver_class_funcs return &funcs[0] if there is no support for multiple drivers per device.

Is this acceptable ?

Last edited 13 years ago by Nicolas Pouillon (previous) (diff)

Changed 13 years ago by Nicolas Pouillon

PoC

Note: See TracTickets for help on using tickets.