qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Philippe Mathieu-Daudé" <philmd@redhat.com>
To: Damien Hedde <damien.hedde@greensocs.com>, qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org, berrange@redhat.com,
	ehabkost@redhat.com, alistair@alistair23.me,
	mark.burton@greensocs.com, marcandre.lureau@redhat.com,
	qemu-arm@nongnu.org, pbonzini@redhat.com,
	edgar.iglesias@gmail.com
Subject: Re: [PATCH v6 3/9] qdev: add clock input&output support to devices.
Date: Mon, 25 Nov 2019 14:30:46 +0100	[thread overview]
Message-ID: <a7d0808d-b57a-f8a7-93ea-ec69aee81cf9@redhat.com> (raw)
In-Reply-To: <20190904125531.27545-4-damien.hedde@greensocs.com>

Nitpick: remove trailing dot in patch subject

On 9/4/19 2:55 PM, Damien Hedde wrote:
> Add functions to easily add input or output clocks to a device.
> A clock objects is added as a child of the device.

<newline>?

> The api is very similar the gpio's one.

Maybe "This API is very similar to the QDEV GPIO API."

> 
> This is based on the original work of Frederic Konrad.
> 
> Signed-off-by: Damien Hedde <damien.hedde@greensocs.com>
> 
> ---
> I've removed the reviewed-by/tested-by of Philippe because I did a small
> modification.
> 
> qdev_connect_clock() which allowed to connect an input to an output is
> now split in 2:
> + qdev_get_clock_in() which gets a given input from a device
> + qdev_connect_clock_out() which connect a given output to a clock
> (previously fetched by qdev_get_clock_in())
> This part is located in (qdev-clock.[c|h]).
> It better matches gpios api and also add the possibility to connect a
> device's input clock to a random output clock (used in patch 9).
> 
> Also add missing qdev-clock in the test-qdev-global-props so that tests
> pass.
> ---
>   hw/core/Makefile.objs   |   2 +-
>   hw/core/qdev-clock.c    | 155 ++++++++++++++++++++++++++++++++++++++++
>   hw/core/qdev.c          |  32 +++++++++
>   include/hw/qdev-clock.h |  67 +++++++++++++++++
>   include/hw/qdev-core.h  |  14 ++++
>   tests/Makefile.include  |   1 +

Please setup the scripts/git.orderfile to ease reviews.

>   6 files changed, 270 insertions(+), 1 deletion(-)
>   create mode 100644 hw/core/qdev-clock.c
>   create mode 100644 include/hw/qdev-clock.h
> 
> diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
> index 8fcebf2e67..4523d3b5c7 100644
> --- a/hw/core/Makefile.objs
> +++ b/hw/core/Makefile.objs
> @@ -1,5 +1,5 @@
>   # core qdev-related obj files, also used by *-user:
> -common-obj-y += qdev.o qdev-properties.o
> +common-obj-y += qdev.o qdev-properties.o qdev-clock.o
>   common-obj-y += bus.o reset.o
>   common-obj-y += resettable.o
>   common-obj-$(CONFIG_SOFTMMU) += qdev-fw.o
> diff --git a/hw/core/qdev-clock.c b/hw/core/qdev-clock.c
> new file mode 100644
> index 0000000000..bebdd8fa15
> --- /dev/null
> +++ b/hw/core/qdev-clock.c
> @@ -0,0 +1,155 @@
> +/*
> + * Device's clock
> + *
> + * Copyright GreenSocs 2016-2018

2019

> + *
> + * Authors:
> + *  Frederic Konrad <fred.konrad@greensocs.com>
> + *  Damien Hedde <damien.hedde@greensocs.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/qdev-clock.h"
> +#include "hw/qdev-core.h"
> +#include "qapi/error.h"
> +
> +static NamedClockList *qdev_init_clocklist(DeviceState *dev, const char *name,
> +        bool forward)

Indentation off.

> +{
> +    NamedClockList *ncl;
> +
> +    /*
> +     * The clock path will be computed by the device's realize function call.
> +     * This is required to ensure the clock's canonical path is right and log
> +     * messages are meaningfull.
> +     */
> +    assert(name);
> +    assert(!dev->realized);
> +
> +    /* The ncl structure will be freed in device's finalize function call */
> +    ncl = g_malloc0(sizeof(*ncl));

Similar but easier to review:

        ncl = g_new0(NamedClockList, 1)

> +    ncl->name = g_strdup(name);
> +    ncl->forward = forward;
> +
> +    QLIST_INSERT_HEAD(&dev->clocks, ncl, node);
> +    return ncl;
> +}
> +
> +ClockOut *qdev_init_clock_out(DeviceState *dev, const char *name)
> +{
> +    NamedClockList *ncl;
> +    Object *clk;
> +
> +    ncl = qdev_init_clocklist(dev, name, false);
> +
> +    clk = object_new(TYPE_CLOCK_OUT);
> +
> +    /* will fail if name already exists */
> +    object_property_add_child(OBJECT(dev), name, clk, &error_abort);
> +    object_unref(clk); /* remove the initial ref made by object_new */
> +
> +    ncl->out = CLOCK_OUT(clk);
> +    return ncl->out;
> +}
> +
> +ClockIn *qdev_init_clock_in(DeviceState *dev, const char *name,
> +                        ClockCallback *callback, void *opaque)

Indentation off.

> +{
> +    NamedClockList *ncl;
> +    Object *clk;
> +
> +    ncl = qdev_init_clocklist(dev, name, false);
> +
> +    clk = object_new(TYPE_CLOCK_IN);
> +    /*
> +     * the ref initialized by object_new will be cleared during dev finalize.
> +     * It allows us to safely remove the callback.
> +     */
> +
> +    /* will fail if name already exists */
> +    object_property_add_child(OBJECT(dev), name, clk, &error_abort);
> +
> +    ncl->in = CLOCK_IN(clk);
> +    if (callback) {
> +        clock_set_callback(ncl->in, callback, opaque);
> +    }
> +    return ncl->in;
> +}
> +
> +static NamedClockList *qdev_get_clocklist(DeviceState *dev, const char *name)
> +{
> +    NamedClockList *ncl;
> +
> +    QLIST_FOREACH(ncl, &dev->clocks, node) {
> +        if (strcmp(name, ncl->name) == 0) {
> +            return ncl;
> +        }
> +    }
> +
> +    return NULL;
> +}
> +
> +void qdev_pass_clock(DeviceState *dev, const char *name,
> +                     DeviceState *container, const char *cont_name)
> +{
> +    NamedClockList *original_ncl, *ncl;
> +    Object **clk;

Is it really a Object** or a Object*?

> +
> +    assert(container && cont_name);
> +
> +    original_ncl = qdev_get_clocklist(container, cont_name);
> +    assert(original_ncl); /* clock must exist in origin */
> +
> +    ncl = qdev_init_clocklist(dev, name, true);
> +
> +    if (ncl->out) {
> +        clk = (Object **)&ncl->out;
> +    } else {
> +        clk = (Object **)&ncl->in;
> +    }
> +
> +    /* will fail if name already exists */
> +    object_property_add_link(OBJECT(dev), name, object_get_typename(*clk),
> +                             clk, NULL, OBJ_PROP_LINK_STRONG, &error_abort);
> +}
> +
> +ClockIn *qdev_get_clock_in(DeviceState *dev, const char *name)
> +{
> +    NamedClockList *ncl;
> +
> +    assert(dev && name);
> +
> +    ncl = qdev_get_clocklist(dev, name);
> +    return ncl ? ncl->in : NULL;
> +}
> +
> +static ClockOut *qdev_get_clock_out(DeviceState *dev, const char *name)
> +{
> +    NamedClockList *ncl;
> +
> +    assert(dev && name);
> +
> +    ncl = qdev_get_clocklist(dev, name);
> +    return ncl ? ncl->out : NULL;
> +}
> +
> +void qdev_connect_clock_out(DeviceState *dev, const char *name, ClockIn *clk,
> +                            Error **errp)
> +{
> +    ClockOut *clkout = qdev_get_clock_out(dev, name);
> +
> +    if (!clk) {
> +        error_setg(errp, "NULL input clock");
> +        return;
> +    }
> +
> +    if (!clkout) {
> +        error_setg(errp, "no output clock '%s' in device", name);
> +        return;
> +    }
> +
> +    clock_connect(clk, clkout);
> +}
> diff --git a/hw/core/qdev.c b/hw/core/qdev.c
> index 9095f2b9c1..eae6cd3e09 100644
> --- a/hw/core/qdev.c
> +++ b/hw/core/qdev.c
> @@ -37,6 +37,7 @@
>   #include "hw/qdev-properties.h"
>   #include "hw/boards.h"
>   #include "hw/sysbus.h"
> +#include "hw/clock.h"
>   #include "migration/vmstate.h"
>   
>   bool qdev_hotplug = false;
> @@ -821,6 +822,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
>       DeviceClass *dc = DEVICE_GET_CLASS(dev);
>       HotplugHandler *hotplug_ctrl;
>       BusState *bus;
> +    NamedClockList *clk;
>       Error *local_err = NULL;
>       bool unattached_parent = false;
>       static int unattached_count;
> @@ -869,6 +871,15 @@ static void device_set_realized(Object *obj, bool value, Error **errp)
>            */
>           g_free(dev->canonical_path);
>           dev->canonical_path = object_get_canonical_path(OBJECT(dev));
> +        QLIST_FOREACH(clk, &dev->clocks, node) {
> +            if (clk->forward) {
> +                continue;
> +            } else if (clk->in != NULL) {
> +                clock_in_setup_canonical_path(clk->in);
> +            } else {
> +                clock_out_setup_canonical_path(clk->out);
> +            }
> +        }
>   
>           if (qdev_get_vmsd(dev)) {
>               if (vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev,
> @@ -999,6 +1010,7 @@ static void device_initfn(Object *obj)
>                                (Object **)&dev->parent_bus, NULL, 0,
>                                &error_abort);
>       QLIST_INIT(&dev->gpios);
> +    QLIST_INIT(&dev->clocks);
>   }
>   
>   static void device_post_init(Object *obj)
> @@ -1015,6 +1027,7 @@ static void device_post_init(Object *obj)
>   static void device_finalize(Object *obj)
>   {
>       NamedGPIOList *ngl, *next;
> +    NamedClockList *clk, *clk_next;
>   
>       DeviceState *dev = DEVICE(obj);
>   
> @@ -1028,6 +1041,25 @@ static void device_finalize(Object *obj)
>            */
>       }
>   
> +    QLIST_FOREACH_SAFE(clk, &dev->clocks, node, clk_next) {
> +        QLIST_REMOVE(clk, node);
> +        if (!clk->forward && clk->in) {
> +            /*
> +             * if this clock is not forwarded, clk->in is a child of dev.
> +             * At this point the child property and associated reference is
> +             * already deleted but we kept a ref on clk->in to ensure it lives
> +             * up to this point and we can safely remove the callback.
> +             * It avoids having a lost callback to a deleted device if the
> +             * clk->in is still referenced somewhere else (eg: by a clock
> +             * output).
> +             */
> +            clock_clear_callback(clk->in);
> +            object_unref(OBJECT(clk->in));
> +        }
> +        g_free(clk->name);
> +        g_free(clk);
> +    }
> +
>       /* Only send event if the device had been completely realized */
>       if (dev->pending_deleted_event) {
>           g_assert(dev->canonical_path);
> diff --git a/include/hw/qdev-clock.h b/include/hw/qdev-clock.h
> new file mode 100644
> index 0000000000..c4ea912fdc
> --- /dev/null
> +++ b/include/hw/qdev-clock.h
> @@ -0,0 +1,67 @@
> +#ifndef QDEV_CLOCK_H
> +#define QDEV_CLOCK_H
> +
> +#include "hw/clock.h"
> +
> +/**
> + * qdev_init_clock_in:
> + * @dev: the device in which to add a clock
> + * @name: the name of the clock (can't be NULL).

I'd drop the trailing dot in property descriptions.

> + * @callback: optional callback to be called on update or NULL.
> + * @opaque:   argument for the callback
> + * @returns: a pointer to the newly added clock
> + *
> + * Add a input clock to device @dev as a clock named @name.
> + * This adds a child<> property.
> + * The callback will be called with @dev as opaque parameter.
> + */
> +ClockIn *qdev_init_clock_in(DeviceState *dev, const char *name,
> +                            ClockCallback *callback, void *opaque);
> +
> +/**
> + * qdev_init_clock_out:
> + * @dev: the device to add a clock to
> + * @name: the name of the clock (can't be NULL).
> + * @callback: optional callback to be called on update or NULL.
> + * @returns: a pointer to the newly added clock
> + *
> + * Add a output clock to device @dev as a clock named @name.
> + * This adds a child<> property.
> + */
> +ClockOut *qdev_init_clock_out(DeviceState *dev, const char *name);
> +
> +/**
> + * qdev_get_clock_in:
> + * @dev: the device which has the clock
> + * @name: the name of the clock (can't be NULL).
> + * @returns: a pointer to the clock
> + *
> + * Get the clock @name from @dev or NULL if does not exists.
> + */
> +ClockIn *qdev_get_clock_in(DeviceState *dev, const char *name);
> +
> +/**
> + * qdev_connect_clock_out:
> + * @dev: the device which has the clock
> + * @name: the name of the clock (can't be NULL).
> + * @errp: error report
> + *
> + * Connect @clk to the output clock @name of @dev.
> + * Reports an error if clk is NULL or @name does not exists in @dev.
> + */
> +void qdev_connect_clock_out(DeviceState *dev, const char *name, ClockIn *clk,
> +                            Error **errp);
> +
> +/**
> + * qdev_pass_clock:
> + * @dev: the device to forward the clock to
> + * @name: the name of the clock to be added (can't be NULL)
> + * @container: the device which already has the clock
> + * @cont_name: the name of the clock in the container device
> + *
> + * Add a clock @name to @dev which forward to the clock @cont_name in @container
> + */
> +void qdev_pass_clock(DeviceState *dev, const char *name,
> +                     DeviceState *container, const char *cont_name);
> +
> +#endif /* QDEV_CLOCK_H */
> diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
> index eb11f0f801..60a65f6142 100644
> --- a/include/hw/qdev-core.h
> +++ b/include/hw/qdev-core.h
> @@ -131,6 +131,19 @@ struct NamedGPIOList {
>       QLIST_ENTRY(NamedGPIOList) node;
>   };
>   
> +typedef struct NamedClockList NamedClockList;
> +
> +typedef struct ClockIn ClockIn;
> +typedef struct ClockOut ClockOut;
> +
> +struct NamedClockList {
> +    char *name;
> +    bool forward;
> +    ClockIn *in;
> +    ClockOut *out;
> +    QLIST_ENTRY(NamedClockList) node;
> +};
> +
>   /**
>    * DeviceState:
>    * @realized: Indicates whether the device has been fully constructed.
> @@ -152,6 +165,7 @@ struct DeviceState {
>       int hotplugged;
>       BusState *parent_bus;
>       QLIST_HEAD(, NamedGPIOList) gpios;
> +    QLIST_HEAD(, NamedClockList) clocks;
>       QLIST_HEAD(, BusState) child_bus;
>       int num_child_bus;
>       int instance_id_alias;
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index f0b4628cc6..5c54beb29e 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -566,6 +566,7 @@ tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
>   	hw/core/irq.o \
>   	hw/core/fw-path-provider.o \
>   	hw/core/reset.o \
> +	hw/core/clock.o \
>   	$(test-qapi-obj-y)
>   tests/test-vmstate$(EXESUF): tests/test-vmstate.o \
>   	migration/vmstate.o migration/vmstate-types.o migration/qemu-file.o \
> 

Except the cosmetic comments:
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>

(Note, this series needs a rebase now).



  reply	other threads:[~2019-11-25 13:32 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-04 12:55 [Qemu-devel] [PATCH v6 0/9] Clock framework API Damien Hedde
2019-09-04 12:55 ` [Qemu-devel] [PATCH v6 1/9] hw/core/clock: introduce clock objects Damien Hedde
2019-11-25 13:07   ` Philippe Mathieu-Daudé
2019-11-25 13:37   ` Philippe Mathieu-Daudé
2019-12-03 15:14     ` Damien Hedde
2019-12-02 13:42   ` Peter Maydell
2019-12-03 15:28     ` Damien Hedde
2019-09-04 12:55 ` [Qemu-devel] [PATCH v6 2/9] hw/core/clock-vmstate: define a vmstate entry for clock state Damien Hedde
2019-11-25 13:05   ` Philippe Mathieu-Daudé
2019-12-02 13:44   ` Peter Maydell
2019-09-04 12:55 ` [Qemu-devel] [PATCH v6 3/9] qdev: add clock input&output support to devices Damien Hedde
2019-11-25 13:30   ` Philippe Mathieu-Daudé [this message]
2019-12-03 15:35     ` Damien Hedde
2019-12-02 14:34   ` Peter Maydell
2019-12-04  9:05     ` Damien Hedde
2019-12-04  9:53       ` Philippe Mathieu-Daudé
2019-12-04 11:58         ` Damien Hedde
2019-09-04 12:55 ` [Qemu-devel] [PATCH v6 4/9] qdev-monitor: print the device's clock with info qtree Damien Hedde
2019-12-02 14:35   ` Peter Maydell
2019-09-04 12:55 ` [Qemu-devel] [PATCH v6 5/9] qdev-clock: introduce an init array to ease the device construction Damien Hedde
2019-12-02 15:13   ` Peter Maydell
2019-12-04 11:04     ` Damien Hedde
2019-09-04 12:55 ` [Qemu-devel] [PATCH v6 6/9] docs/clocks: add device's clock documentation Damien Hedde
2019-12-02 15:17   ` Peter Maydell
2019-12-04 12:11     ` Damien Hedde
2019-09-04 12:55 ` [Qemu-devel] [PATCH v6 7/9] hw/misc/zynq_slcr: add clock generation for uarts Damien Hedde
2019-12-02 15:20   ` Peter Maydell
2019-12-04 12:51     ` Damien Hedde
2019-09-04 12:55 ` [Qemu-devel] [PATCH v6 8/9] hw/char/cadence_uart: add clock support Damien Hedde
2019-12-02 15:24   ` Peter Maydell
2019-12-04 13:35     ` Damien Hedde
2019-09-04 12:55 ` [Qemu-devel] [PATCH v6 9/9] hw/arm/xilinx_zynq: connect uart clocks to slcr Damien Hedde
2019-12-02 15:34   ` Peter Maydell
2019-12-03 14:59     ` Damien Hedde
2019-12-03 15:29       ` Philippe Mathieu-Daudé
2019-12-02 16:15 ` [PATCH v6 0/9] Clock framework API Peter Maydell
2019-12-04 16:40   ` Damien Hedde
2019-12-04 20:34     ` Philippe Mathieu-Daudé
2019-12-05  9:36       ` Damien Hedde
2019-12-05  9:59         ` Philippe Mathieu-Daudé
2019-12-05 10:21           ` Dr. David Alan Gilbert
2019-12-05 10:44             ` Philippe Mathieu-Daudé
2019-12-05 10:56               ` Dr. David Alan Gilbert
2019-12-05 11:01                 ` Philippe Mathieu-Daudé
2019-12-06 12:46                   ` Cleber Rosa
2019-12-06 13:48                     ` Dr. David Alan Gilbert

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=a7d0808d-b57a-f8a7-93ea-ec69aee81cf9@redhat.com \
    --to=philmd@redhat.com \
    --cc=alistair@alistair23.me \
    --cc=berrange@redhat.com \
    --cc=damien.hedde@greensocs.com \
    --cc=edgar.iglesias@gmail.com \
    --cc=ehabkost@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=mark.burton@greensocs.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).