Re: [PATCH v7 3/3] drivers/bus: Device driver for FSL-MC DPRC devices

From: Alexander Graf
Date: Thu Feb 26 2015 - 09:08:14 EST




On 24.02.15 23:21, J. German Rivera wrote:
> A DPRC (Data Path Resource Container) is an isolation device
> that contains a set of DPAA networking devices to be
> assigned to an isolation domain (e.g., a virtual machine).
>
> Signed-off-by: J. German Rivera <German.Rivera@xxxxxxxxxxxxx>
> Signed-off-by: Stuart Yoder <stuart.yoder@xxxxxxxxxxxxx>
> ---
> Changes in v7:
> - Create fsl_mc_io object in dprc_probe()
>
> Changes in v6:
> - Fixed new checkpatch warnings
>
> Changes in v5:
> None
>
> Changes in v4:
> - Addressed comments from Alex Graf:
> * Fixed typo in comment
>
> Changes in v3:
> - Addressed comments from Kim Phillips:
> * Renamed files:
> drivers/bus/fsl-mc/fsl_mc_dprc.c -> drivers/bus/fsl-mc/dprc-driver.c
>
> - Addressed comments from Timur Tabi:
> * Changed dprc_scan_container() to just return dprc_scan_objects()
> * Changed all functions that had goto out/error when no common cleanup
> was done, to just have multiple return points.
> * Replaced error cleanup boolean flags with multiple exit points.
> * REmoved __must_chewck from dprc_scan_*() functions
>
> Changes in v2:
> - Addressed comments from Kim Phillips:
> * Fix warning in drivers/bus/fsl-mc/fsl_mc_dprc.c:173
> * Fixed linker errors when MC bus driver built as module
>
> drivers/bus/fsl-mc/Makefile | 3 +-
> drivers/bus/fsl-mc/dprc-driver.c | 384 +++++++++++++++++++++++++++++++++++++++
> drivers/bus/fsl-mc/mc-bus.c | 8 +
> include/linux/fsl/mc-private.h | 10 +
> 4 files changed, 404 insertions(+), 1 deletion(-)
> create mode 100644 drivers/bus/fsl-mc/dprc-driver.c
>
> diff --git a/drivers/bus/fsl-mc/Makefile b/drivers/bus/fsl-mc/Makefile
> index decd339..424e58e 100644
> --- a/drivers/bus/fsl-mc/Makefile
> +++ b/drivers/bus/fsl-mc/Makefile
> @@ -10,5 +10,6 @@ obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o
> mc-bus-driver-objs := mc-bus.o \
> mc-sys.o \
> dprc.o \
> - dpmng.o
> + dpmng.o \
> + dprc-driver.o
>
> diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
> new file mode 100644
> index 0000000..a231d00
> --- /dev/null
> +++ b/drivers/bus/fsl-mc/dprc-driver.c
> @@ -0,0 +1,384 @@
> +/*
> + * Freescale data path resource container (DPRC) driver
> + *
> + * Copyright (C) 2014 Freescale Semiconductor, Inc.
> + * Author: German Rivera <German.Rivera@xxxxxxxxxxxxx>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#include <linux/fsl/mc-private.h>
> +#include <linux/fsl/mc-sys.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include "dprc-cmd.h"
> +
> +struct dprc_child_objs {
> + int child_count;
> + struct dprc_obj_desc *child_array;
> +};
> +
> +static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
> +{
> + int i;
> + struct dprc_child_objs *objs;
> + struct fsl_mc_device *mc_dev;
> +
> + WARN_ON(!dev);
> + WARN_ON(!data);
> + mc_dev = to_fsl_mc_device(dev);
> + objs = data;
> +
> + for (i = 0; i < objs->child_count; i++) {
> + struct dprc_obj_desc *obj_desc = &objs->child_array[i];
> +
> + if (strlen(obj_desc->type) != 0 &&
> + FSL_MC_DEVICE_MATCH(mc_dev, obj_desc))
> + break;
> + }
> +
> + if (i == objs->child_count)
> + fsl_mc_device_remove(mc_dev);
> +
> + return 0;
> +}
> +
> +static int __fsl_mc_device_remove(struct device *dev, void *data)
> +{
> + WARN_ON(!dev);
> + WARN_ON(data);
> + fsl_mc_device_remove(to_fsl_mc_device(dev));
> + return 0;
> +}
> +
> +/**
> + * dprc_remove_devices - Removes devices for objects removed from a DPRC
> + *
> + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
> + * @obj_desc_array: array of object descriptors for child objects currently
> + * present in the DPRC in the MC.
> + * @num_child_objects_in_mc: number of entries in obj_desc_array
> + *
> + * Synchronizes the state of the Linux bus driver with the actual state of
> + * the MC by removing devices that represent MC objects that have
> + * been dynamically removed in the physical DPRC.
> + */
> +static void dprc_remove_devices(struct fsl_mc_device *mc_bus_dev,
> + struct dprc_obj_desc *obj_desc_array,
> + int num_child_objects_in_mc)
> +{
> + if (num_child_objects_in_mc != 0) {
> + /*
> + * Remove child objects that are in the DPRC in Linux,
> + * but not in the MC:
> + */
> + struct dprc_child_objs objs;
> +
> + objs.child_count = num_child_objects_in_mc;
> + objs.child_array = obj_desc_array;
> + device_for_each_child(&mc_bus_dev->dev, &objs,
> + __fsl_mc_device_remove_if_not_in_mc);
> + } else {
> + /*
> + * There are no child objects for this DPRC in the MC.
> + * So, remove all the child devices from Linux:
> + */
> + device_for_each_child(&mc_bus_dev->dev, NULL,
> + __fsl_mc_device_remove);
> + }
> +}
> +
> +static int __fsl_mc_device_match(struct device *dev, void *data)
> +{
> + struct dprc_obj_desc *obj_desc = data;
> + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
> +
> + return FSL_MC_DEVICE_MATCH(mc_dev, obj_desc);
> +}
> +
> +static struct fsl_mc_device *fsl_mc_device_lookup(struct dprc_obj_desc
> + *obj_desc,
> + struct fsl_mc_device
> + *mc_bus_dev)
> +{
> + struct device *dev;
> +
> + dev = device_find_child(&mc_bus_dev->dev, obj_desc,
> + __fsl_mc_device_match);
> +
> + return dev ? to_fsl_mc_device(dev) : NULL;
> +}
> +
> +/**
> + * dprc_add_new_devices - Adds devices to the logical bus for a DPRC
> + *
> + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
> + * @obj_desc_array: array of device descriptors for child devices currently
> + * present in the physical DPRC.
> + * @num_child_objects_in_mc: number of entries in obj_desc_array
> + *
> + * Synchronizes the state of the Linux bus driver with the actual
> + * state of the MC by adding objects that have been newly discovered
> + * in the physical DPRC.
> + */
> +static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
> + struct dprc_obj_desc *obj_desc_array,
> + int num_child_objects_in_mc)
> +{
> + int error;
> + int i;
> +
> + for (i = 0; i < num_child_objects_in_mc; i++) {
> + struct fsl_mc_device *child_dev;
> + struct fsl_mc_io *mc_io = NULL;
> + struct dprc_obj_desc *obj_desc = &obj_desc_array[i];
> +
> + if (strlen(obj_desc->type) == 0)
> + continue;
> +
> + /*
> + * Check if device is already known to Linux:
> + */
> + child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev);
> + if (child_dev)
> + continue;
> +
> + error = fsl_mc_device_add(obj_desc, mc_io, &mc_bus_dev->dev,
> + &child_dev);
> + if (error < 0) {
> + if (mc_io)
> + fsl_destroy_mc_io(mc_io);
> +
> + continue;
> + }
> + }
> +}
> +
> +/**
> + * dprc_scan_objects - Discover objects in a DPRC
> + *
> + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
> + *
> + * Detects objects added and removed from a DPRC and synchronizes the
> + * state of the Linux bus driver, MC by adding and removing
> + * devices accordingly.
> + */
> +int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev)
> +{
> + int num_child_objects;
> + int dprc_get_obj_failures;
> + int error;
> + struct dprc_obj_desc *child_obj_desc_array = NULL;
> +
> + error = dprc_get_obj_count(mc_bus_dev->mc_io,
> + mc_bus_dev->mc_handle,
> + &num_child_objects);
> + if (error < 0) {
> + dev_err(&mc_bus_dev->dev, "dprc_get_obj_count() failed: %d\n",
> + error);
> + return error;
> + }
> +
> + if (num_child_objects != 0) {
> + int i;
> +
> + child_obj_desc_array =
> + devm_kmalloc_array(&mc_bus_dev->dev, num_child_objects,
> + sizeof(*child_obj_desc_array),
> + GFP_KERNEL);
> + if (!child_obj_desc_array)
> + return -ENOMEM;
> +
> + /*
> + * Discover objects currently present in the physical DPRC:
> + */
> + dprc_get_obj_failures = 0;
> + for (i = 0; i < num_child_objects; i++) {
> + struct dprc_obj_desc *obj_desc =
> + &child_obj_desc_array[i];
> +
> + error = dprc_get_obj(mc_bus_dev->mc_io,
> + mc_bus_dev->mc_handle,
> + i, obj_desc);
> + if (error < 0) {
> + dev_err(&mc_bus_dev->dev,
> + "dprc_get_obj(i=%d) failed: %d\n",
> + i, error);
> + /*
> + * Mark the obj entry as "invalid", by using the
> + * empty string as obj type:
> + */
> + obj_desc->type[0] = '\0';
> + obj_desc->id = error;
> + dprc_get_obj_failures++;
> + continue;
> + }
> +
> + dev_dbg(&mc_bus_dev->dev,
> + "Discovered object: type %s, id %d\n",
> + obj_desc->type, obj_desc->id);
> + }
> +
> + if (dprc_get_obj_failures != 0) {
> + dev_err(&mc_bus_dev->dev,
> + "%d out of %d devices could not be retrieved\n",
> + dprc_get_obj_failures, num_child_objects);
> + }
> + }
> +
> + dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
> + num_child_objects);
> +
> + dprc_add_new_devices(mc_bus_dev, child_obj_desc_array,
> + num_child_objects);
> +
> + if (child_obj_desc_array)
> + devm_kfree(&mc_bus_dev->dev, child_obj_desc_array);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(dprc_scan_objects);

Why is this exported?

> +
> +/**
> + * dprc_scan_container - Scans a physical DPRC and synchronizes Linux bus state
> + *
> + * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object
> + *
> + * Scans the physical DPRC and synchronizes the state of the Linux
> + * bus driver with the actual state of the MC by adding and removing
> + * devices as appropriate.
> + */
> +int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
> +{
> + int error;
> + struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
> +
> + /*
> + * Discover objects in the DPRC:
> + */
> + mutex_lock(&mc_bus->scan_mutex);
> + error = dprc_scan_objects(mc_bus_dev);
> + mutex_unlock(&mc_bus->scan_mutex);
> + return error;
> +}

Or rather why does the split exist at all? Can't you just fold the
locking into the scan function?


Alex
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/