Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/dma/qcom/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 6 kB image not shown  

Quelle  hidma_mgmt_sys.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Qualcomm Technologies HIDMA Management SYS interface
 *
 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
 */


#include <linux/sysfs.h>
#include <linux/platform_device.h>

#include "hidma_mgmt.h"

struct hidma_chan_attr {
 struct hidma_mgmt_dev *mdev;
 int index;
 struct kobj_attribute attr;
};

struct hidma_mgmt_fileinfo {
 char *name;
 int mode;
 int (*get)(struct hidma_mgmt_dev *mdev);
 int (*set)(struct hidma_mgmt_dev *mdev, u64 val);
};

#define IMPLEMENT_GETSET(name)     \
static int get_##name(struct hidma_mgmt_dev *mdev)  \
{        \
 return mdev->name;     \
}        \
static int set_##name(struct hidma_mgmt_dev *mdev, u64 val) \
{        \
 u64 tmp;      \
 int rc;       \
        \
 tmp = mdev->name;     \
 mdev->name = val;     \
 rc = hidma_mgmt_setup(mdev);    \
 if (rc)       \
  mdev->name = tmp;    \
 return rc;      \
}

#define DECLARE_ATTRIBUTE(name, mode)    \
 {#name, mode, get_##name, set_##name}

IMPLEMENT_GETSET(hw_version_major)
IMPLEMENT_GETSET(hw_version_minor)
IMPLEMENT_GETSET(max_wr_xactions)
IMPLEMENT_GETSET(max_rd_xactions)
IMPLEMENT_GETSET(max_write_request)
IMPLEMENT_GETSET(max_read_request)
IMPLEMENT_GETSET(dma_channels)
IMPLEMENT_GETSET(chreset_timeout_cycles)

static int set_priority(struct hidma_mgmt_dev *mdev, unsigned int i, u64 val)
{
 u64 tmp;
 int rc;

 if (i >= mdev->dma_channels)
  return -EINVAL;

 tmp = mdev->priority[i];
 mdev->priority[i] = val;
 rc = hidma_mgmt_setup(mdev);
 if (rc)
  mdev->priority[i] = tmp;
 return rc;
}

static int set_weight(struct hidma_mgmt_dev *mdev, unsigned int i, u64 val)
{
 u64 tmp;
 int rc;

 if (i >= mdev->dma_channels)
  return -EINVAL;

 tmp = mdev->weight[i];
 mdev->weight[i] = val;
 rc = hidma_mgmt_setup(mdev);
 if (rc)
  mdev->weight[i] = tmp;
 return rc;
}

static struct hidma_mgmt_fileinfo hidma_mgmt_files[] = {
 DECLARE_ATTRIBUTE(hw_version_major, S_IRUGO),
 DECLARE_ATTRIBUTE(hw_version_minor, S_IRUGO),
 DECLARE_ATTRIBUTE(dma_channels, S_IRUGO),
 DECLARE_ATTRIBUTE(chreset_timeout_cycles, S_IRUGO),
 DECLARE_ATTRIBUTE(max_wr_xactions, S_IRUGO),
 DECLARE_ATTRIBUTE(max_rd_xactions, S_IRUGO),
 DECLARE_ATTRIBUTE(max_write_request, S_IRUGO),
 DECLARE_ATTRIBUTE(max_read_request, S_IRUGO),
};

static ssize_t show_values(struct device *dev, struct device_attribute *attr,
      char *buf)
{
 struct hidma_mgmt_dev *mdev = dev_get_drvdata(dev);
 unsigned int i;

 buf[0] = 0;

 for (i = 0; i < ARRAY_SIZE(hidma_mgmt_files); i++) {
  if (strcmp(attr->attr.name, hidma_mgmt_files[i].name) == 0) {
   sprintf(buf, "%d\n", hidma_mgmt_files[i].get(mdev));
   break;
  }
 }
 return strlen(buf);
}

static ssize_t set_values(struct device *dev, struct device_attribute *attr,
     const char *buf, size_t count)
{
 struct hidma_mgmt_dev *mdev = dev_get_drvdata(dev);
 unsigned long tmp;
 unsigned int i;
 int rc;

 rc = kstrtoul(buf, 0, &tmp);
 if (rc)
  return rc;

 for (i = 0; i < ARRAY_SIZE(hidma_mgmt_files); i++) {
  if (strcmp(attr->attr.name, hidma_mgmt_files[i].name) == 0) {
   rc = hidma_mgmt_files[i].set(mdev, tmp);
   if (rc)
    return rc;

   break;
  }
 }
 return count;
}

static ssize_t show_values_channel(struct kobject *kobj,
       struct kobj_attribute *attr, char *buf)
{
 struct hidma_chan_attr *chattr;
 struct hidma_mgmt_dev *mdev;

 buf[0] = 0;
 chattr = container_of(attr, struct hidma_chan_attr, attr);
 mdev = chattr->mdev;
 if (strcmp(attr->attr.name, "priority") == 0)
  sprintf(buf, "%d\n", mdev->priority[chattr->index]);
 else if (strcmp(attr->attr.name, "weight") == 0)
  sprintf(buf, "%d\n", mdev->weight[chattr->index]);

 return strlen(buf);
}

static ssize_t set_values_channel(struct kobject *kobj,
      struct kobj_attribute *attr, const char *buf,
      size_t count)
{
 struct hidma_chan_attr *chattr;
 struct hidma_mgmt_dev *mdev;
 unsigned long tmp;
 int rc;

 chattr = container_of(attr, struct hidma_chan_attr, attr);
 mdev = chattr->mdev;

 rc = kstrtoul(buf, 0, &tmp);
 if (rc)
  return rc;

 if (strcmp(attr->attr.name, "priority") == 0) {
  rc = set_priority(mdev, chattr->index, tmp);
  if (rc)
   return rc;
 } else if (strcmp(attr->attr.name, "weight") == 0) {
  rc = set_weight(mdev, chattr->index, tmp);
  if (rc)
   return rc;
 }
 return count;
}

static int create_sysfs_entry(struct hidma_mgmt_dev *dev, char *name, int mode)
{
 struct device_attribute *attrs;
 char *name_copy;

 attrs = devm_kmalloc(&dev->pdev->dev,
        sizeof(struct device_attribute), GFP_KERNEL);
 if (!attrs)
  return -ENOMEM;

 name_copy = devm_kstrdup(&dev->pdev->dev, name, GFP_KERNEL);
 if (!name_copy)
  return -ENOMEM;

 attrs->attr.name = name_copy;
 attrs->attr.mode = mode;
 attrs->show = show_values;
 attrs->store = set_values;
 sysfs_attr_init(&attrs->attr);

 return device_create_file(&dev->pdev->dev, attrs);
}

static int create_sysfs_entry_channel(struct hidma_mgmt_dev *mdev, char *name,
          int mode, int index,
          struct kobject *parent)
{
 struct hidma_chan_attr *chattr;
 char *name_copy;

 chattr = devm_kmalloc(&mdev->pdev->dev, sizeof(*chattr), GFP_KERNEL);
 if (!chattr)
  return -ENOMEM;

 name_copy = devm_kstrdup(&mdev->pdev->dev, name, GFP_KERNEL);
 if (!name_copy)
  return -ENOMEM;

 chattr->mdev = mdev;
 chattr->index = index;
 chattr->attr.attr.name = name_copy;
 chattr->attr.attr.mode = mode;
 chattr->attr.show = show_values_channel;
 chattr->attr.store = set_values_channel;
 sysfs_attr_init(&chattr->attr.attr);

 return sysfs_create_file(parent, &chattr->attr.attr);
}

int hidma_mgmt_init_sys(struct hidma_mgmt_dev *mdev)
{
 unsigned int i;
 int rc;
 int required;
 struct kobject *chanops;

 required = sizeof(*mdev->chroots) * mdev->dma_channels;
 mdev->chroots = devm_kmalloc(&mdev->pdev->dev, required, GFP_KERNEL);
 if (!mdev->chroots)
  return -ENOMEM;

 chanops = kobject_create_and_add("chanops", &mdev->pdev->dev.kobj);
 if (!chanops)
  return -ENOMEM;

 /* create each channel directory here */
 for (i = 0; i < mdev->dma_channels; i++) {
  char name[20];

  snprintf(name, sizeof(name), "chan%d", i);
  mdev->chroots[i] = kobject_create_and_add(name, chanops);
  if (!mdev->chroots[i])
   return -ENOMEM;
 }

 /* populate common parameters */
 for (i = 0; i < ARRAY_SIZE(hidma_mgmt_files); i++) {
  rc = create_sysfs_entry(mdev, hidma_mgmt_files[i].name,
     hidma_mgmt_files[i].mode);
  if (rc)
   return rc;
 }

 /* populate parameters that are per channel */
 for (i = 0; i < mdev->dma_channels; i++) {
  rc = create_sysfs_entry_channel(mdev, "priority",
      (S_IRUGO | S_IWUGO), i,
      mdev->chroots[i]);
  if (rc)
   return rc;

  rc = create_sysfs_entry_channel(mdev, "weight",
      (S_IRUGO | S_IWUGO), i,
      mdev->chroots[i]);
  if (rc)
   return rc;
 }

 return 0;
}
EXPORT_SYMBOL_GPL(hidma_mgmt_init_sys);

Messung V0.5
C=95 H=96 G=95

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.