*uclass_countp = uclass_get_count();
}
+void dev_collect_stats(struct dm_stats *stats, const struct udevice *parent)
+{
+ const struct udevice *dev;
+ int i;
+
+ stats->dev_count++;
+ stats->dev_size += sizeof(struct udevice);
+ stats->dev_name_size += strlen(parent->name) + 1;
+ for (i = 0; i < DM_TAG_ATTACH_COUNT; i++) {
+ int size = dev_get_attach_size(parent, i);
+
+ if (size ||
+ (i == DM_TAG_DRIVER_DATA && parent->driver_data)) {
+ stats->attach_count[i]++;
+ stats->attach_size[i] += size;
+ stats->attach_count_total++;
+ stats->attach_size_total += size;
+ }
+ }
+
+ list_for_each_entry(dev, &parent->child_head, sibling_node)
+ dev_collect_stats(stats, dev);
+}
+
+void uclass_collect_stats(struct dm_stats *stats)
+{
+ struct uclass *uc;
+
+ list_for_each_entry(uc, gd->uclass_root, sibling_node) {
+ int size;
+
+ stats->uc_count++;
+ stats->uc_size += sizeof(struct uclass);
+ size = uc->uc_drv->priv_auto;
+ if (size) {
+ stats->uc_attach_count++;
+ stats->uc_attach_size += size;
+ }
+ }
+}
+
+void dm_get_mem(struct dm_stats *stats)
+{
+ memset(stats, '\0', sizeof(*stats));
+ dev_collect_stats(stats, gd->dm_root);
+ uclass_collect_stats(stats);
+ dev_tag_collect_stats(stats);
+
+ stats->total_size = stats->dev_size + stats->uc_size +
+ stats->attach_size_total + stats->uc_attach_size +
+ stats->tag_size;
+}
+
#ifdef CONFIG_ACPIGEN
static int root_acpi_get_name(const struct udevice *dev, char *out_name)
{
#include <malloc.h>
#include <asm/global_data.h>
+#include <dm/root.h>
#include <dm/tag.h>
#include <linux/err.h>
#include <linux/list.h>
return -ENOENT;
}
+
+void dev_tag_collect_stats(struct dm_stats *stats)
+{
+ struct dmtag_node *node;
+
+ list_for_each_entry(node, &gd->dmtag_list, sibling) {
+ stats->tag_count++;
+ stats->tag_size += sizeof(struct dmtag_node);
+ }
+}
#ifndef _DM_ROOT_H_
#define _DM_ROOT_H_
+#include <dm/tag.h>
+
struct udevice;
/* Head of the uclass list if CONFIG_OF_PLATDATA_INST is enabled */
extern struct list_head uclass_head;
+/**
+ * struct dm_stats - Information about driver model memory usage
+ *
+ * @total_size: All data
+ * @dev_count: Number of devices
+ * @dev_size: Size of all devices (just the struct udevice)
+ * @dev_name_size: Bytes used by device names
+ * @uc_count: Number of uclasses
+ * @uc_size: Size of all uclasses (just the struct uclass)
+ * @tag_count: Number of tags
+ * @tag_size: Bytes used by all tags
+ * @uc_attach_count: Number of uclasses with attached data (priv)
+ * @uc_attach_size: Total size of that attached data
+ * @attach_count_total: Total number of attached data items for all udevices and
+ * uclasses
+ * @attach_size_total: Total number of bytes of attached data
+ * @attach_count: Number of devices with attached, for each type
+ * @attach_size: Total number of bytes of attached data, for each type
+ */
+struct dm_stats {
+ int total_size;
+ int dev_count;
+ int dev_size;
+ int dev_name_size;
+ int uc_count;
+ int uc_size;
+ int tag_count;
+ int tag_size;
+ int uc_attach_count;
+ int uc_attach_size;
+ int attach_count_total;
+ int attach_size_total;
+ int attach_count[DM_TAG_ATTACH_COUNT];
+ int attach_size[DM_TAG_ATTACH_COUNT];
+};
+
/**
* dm_root() - Return pointer to the top of the driver tree
*
*/
void dm_get_stats(int *device_countp, int *uclass_countp);
+/**
+ * dm_get_mem() - Get stats on memory usage in driver model
+ *
+ * @mem: Place to put the information
+ */
+void dm_get_mem(struct dm_stats *stats);
+
#endif
#include <linux/list.h>
#include <linux/types.h>
+struct dm_stats;
struct udevice;
enum dm_tag_t {
*/
int dev_tag_del_all(struct udevice *dev);
+/**
+ * dev_tag_collect_stats() - Collect information on driver model performance
+ *
+ * This collects information on how driver model is performing. For now it only
+ * includes memory usage
+ *
+ * @stats: Place to put the collected information
+ */
+void dev_tag_collect_stats(struct dm_stats *stats);
+
#endif /* _DM_TAG_H */
return 0;
}
DM_TEST(dm_test_dev_get_attach_bus, UT_TESTF_SCAN_FDT);
+
+/* Test getting information about tags attached to bus devices */
+static int dm_test_dev_get_mem(struct unit_test_state *uts)
+{
+ struct dm_stats stats;
+
+ dm_get_mem(&stats);
+
+ return 0;
+}
+DM_TEST(dm_test_dev_get_mem, UT_TESTF_SCAN_FDT);