^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * DMA-BUF sysfs statistics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2021 Google LLC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/dma-buf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/dma-resv.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kobject.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/printk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "dma-buf-sysfs-stats.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define to_dma_buf_entry_from_kobj(x) container_of(x, struct dma_buf_sysfs_entry, kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct dma_buf_stats_attribute {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) ssize_t (*show)(struct dma_buf *dmabuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct dma_buf_stats_attribute *attr, char *buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define to_dma_buf_stats_attr(x) container_of(x, struct dma_buf_stats_attribute, attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static ssize_t dma_buf_stats_attribute_show(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct dma_buf_stats_attribute *attribute;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct dma_buf_sysfs_entry *sysfs_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct dma_buf *dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) attribute = to_dma_buf_stats_attr(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) sysfs_entry = to_dma_buf_entry_from_kobj(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) dmabuf = sysfs_entry->dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (!dmabuf || !attribute->show)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return attribute->show(dmabuf, attribute, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static const struct sysfs_ops dma_buf_stats_sysfs_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .show = dma_buf_stats_attribute_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static ssize_t exporter_name_show(struct dma_buf *dmabuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct dma_buf_stats_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return sysfs_emit(buf, "%s\n", dmabuf->exp_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static ssize_t size_show(struct dma_buf *dmabuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct dma_buf_stats_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return sysfs_emit(buf, "%zu\n", dmabuf->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static struct dma_buf_stats_attribute exporter_name_attribute =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) __ATTR_RO(exporter_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static struct dma_buf_stats_attribute size_attribute = __ATTR_RO(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static struct attribute *dma_buf_stats_default_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) &exporter_name_attribute.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) &size_attribute.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) ATTRIBUTE_GROUPS(dma_buf_stats_default);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static void dma_buf_sysfs_release(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct dma_buf_sysfs_entry *sysfs_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) sysfs_entry = to_dma_buf_entry_from_kobj(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) kfree(sysfs_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static struct kobj_type dma_buf_ktype = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .sysfs_ops = &dma_buf_stats_sysfs_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .release = dma_buf_sysfs_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .default_groups = dma_buf_stats_default_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) void dma_buf_stats_teardown(struct dma_buf *dmabuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct dma_buf_sysfs_entry *sysfs_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) sysfs_entry = dmabuf->sysfs_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (!sysfs_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) kobject_del(&sysfs_entry->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) kobject_put(&sysfs_entry->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * Statistics files do not need to send uevents.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int dmabuf_sysfs_uevent_filter(struct kset *kset, struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static const struct kset_uevent_ops dmabuf_sysfs_no_uevent_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .filter = dmabuf_sysfs_uevent_filter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static struct kset *dma_buf_stats_kset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static struct kset *dma_buf_per_buffer_stats_kset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int dma_buf_init_sysfs_statistics(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) dma_buf_stats_kset = kset_create_and_add("dmabuf",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) &dmabuf_sysfs_no_uevent_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) kernel_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (!dma_buf_stats_kset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) dma_buf_per_buffer_stats_kset = kset_create_and_add("buffers",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) &dmabuf_sysfs_no_uevent_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) &dma_buf_stats_kset->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (!dma_buf_per_buffer_stats_kset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) kset_unregister(dma_buf_stats_kset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) void dma_buf_uninit_sysfs_statistics(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) kset_unregister(dma_buf_per_buffer_stats_kset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) kset_unregister(dma_buf_stats_kset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int dma_buf_stats_setup(struct dma_buf *dmabuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct dma_buf_sysfs_entry *sysfs_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (!dmabuf || !dmabuf->file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (!dmabuf->exp_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) pr_err("exporter name must not be empty if stats needed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) sysfs_entry = kzalloc(sizeof(struct dma_buf_sysfs_entry), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (!sysfs_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) sysfs_entry->kobj.kset = dma_buf_per_buffer_stats_kset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) sysfs_entry->dmabuf = dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) dmabuf->sysfs_entry = sysfs_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* create the directory for buffer stats */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) ret = kobject_init_and_add(&sysfs_entry->kobj, &dma_buf_ktype, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) "%lu", file_inode(dmabuf->file)->i_ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) goto err_sysfs_dmabuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) err_sysfs_dmabuf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) kobject_put(&sysfs_entry->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) dmabuf->sysfs_entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }