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

Quelle  ufs-debugfs.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2020 Intel Corporation

#include <linux/debugfs.h>

#include "ufs-debugfs.h"
#include <ufs/ufshcd.h>
#include "ufshcd-priv.h"

static struct dentry *ufs_debugfs_root;

struct ufs_debugfs_attr {
 const char   *name;
 mode_t    mode;
 const struct file_operations *fops;
};

/* @file corresponds to a debugfs attribute in directory hba->debugfs_root. */
static inline struct ufs_hba *hba_from_file(const struct file *file)
{
 return d_inode(file->f_path.dentry->d_parent)->i_private;
}

void __init ufs_debugfs_init(void)
{
 ufs_debugfs_root = debugfs_create_dir("ufshcd", NULL);
}

void ufs_debugfs_exit(void)
{
 debugfs_remove_recursive(ufs_debugfs_root);
}

static int ufs_debugfs_stats_show(struct seq_file *s, void *data)
{
 struct ufs_hba *hba = hba_from_file(s->file);
 struct ufs_event_hist *e = hba->ufs_stats.event;

#define PRT(fmt, typ) \
 seq_printf(s, fmt, e[UFS_EVT_ ## typ].cnt)

 PRT("PHY Adapter Layer errors (except LINERESET): %llu\n", PA_ERR);
 PRT("Data Link Layer errors: %llu\n", DL_ERR);
 PRT("Network Layer errors: %llu\n", NL_ERR);
 PRT("Transport Layer errors: %llu\n", TL_ERR);
 PRT("Generic DME errors: %llu\n", DME_ERR);
 PRT("Auto-hibernate errors: %llu\n", AUTO_HIBERN8_ERR);
 PRT("IS Fatal errors (CEFES, SBFES, HCFES, DFES): %llu\n", FATAL_ERR);
 PRT("DME Link Startup errors: %llu\n", LINK_STARTUP_FAIL);
 PRT("PM Resume errors: %llu\n", RESUME_ERR);
 PRT("PM Suspend errors : %llu\n", SUSPEND_ERR);
 PRT("Logical Unit Resets: %llu\n", DEV_RESET);
 PRT("Host Resets: %llu\n", HOST_RESET);
 PRT("SCSI command aborts: %llu\n", ABORT);
#undef PRT
 return 0;
}
DEFINE_SHOW_ATTRIBUTE(ufs_debugfs_stats);

static int ee_usr_mask_get(void *data, u64 *val)
{
 struct ufs_hba *hba = data;

 *val = hba->ee_usr_mask;
 return 0;
}

static int ufs_debugfs_get_user_access(struct ufs_hba *hba)
__acquires(&hba->host_sem)
{
 down(&hba->host_sem);
 if (!ufshcd_is_user_access_allowed(hba)) {
  up(&hba->host_sem);
  return -EBUSY;
 }
 ufshcd_rpm_get_sync(hba);
 return 0;
}

static void ufs_debugfs_put_user_access(struct ufs_hba *hba)
__releases(&hba->host_sem)
{
 ufshcd_rpm_put_sync(hba);
 up(&hba->host_sem);
}

static int ee_usr_mask_set(void *data, u64 val)
{
 struct ufs_hba *hba = data;
 int err;

 if (val & ~(u64)MASK_EE_STATUS)
  return -EINVAL;
 err = ufs_debugfs_get_user_access(hba);
 if (err)
  return err;
 err = ufshcd_update_ee_usr_mask(hba, val, MASK_EE_STATUS);
 ufs_debugfs_put_user_access(hba);
 return err;
}

DEFINE_DEBUGFS_ATTRIBUTE(ee_usr_mask_fops, ee_usr_mask_get, ee_usr_mask_set, "%#llx\n");

void ufs_debugfs_exception_event(struct ufs_hba *hba, u16 status)
{
 bool chgd = false;
 u16 ee_ctrl_mask;
 int err = 0;

 if (!hba->debugfs_ee_rate_limit_ms || !status)
  return;

 mutex_lock(&hba->ee_ctrl_mutex);
 ee_ctrl_mask = hba->ee_drv_mask | (hba->ee_usr_mask & ~status);
 chgd = ee_ctrl_mask != hba->ee_ctrl_mask;
 if (chgd) {
  err = __ufshcd_write_ee_control(hba, ee_ctrl_mask);
  if (err)
   dev_err(hba->dev, "%s: failed to write ee control %d\n",
    __func__, err);
 }
 mutex_unlock(&hba->ee_ctrl_mutex);

 if (chgd && !err) {
  unsigned long delay = msecs_to_jiffies(hba->debugfs_ee_rate_limit_ms);

  queue_delayed_work(system_freezable_wq, &hba->debugfs_ee_work, delay);
 }
}

static void ufs_debugfs_restart_ee(struct work_struct *work)
{
 struct ufs_hba *hba = container_of(work, struct ufs_hba, debugfs_ee_work.work);

 if (!hba->ee_usr_mask || pm_runtime_suspended(hba->dev) ||
     ufs_debugfs_get_user_access(hba))
  return;
 ufshcd_write_ee_control(hba);
 ufs_debugfs_put_user_access(hba);
}

static int ufs_saved_err_show(struct seq_file *s, void *data)
{
 struct ufs_debugfs_attr *attr = s->private;
 struct ufs_hba *hba = hba_from_file(s->file);
 const int *p;

 if (strcmp(attr->name, "saved_err") == 0) {
  p = &hba->saved_err;
 } else if (strcmp(attr->name, "saved_uic_err") == 0) {
  p = &hba->saved_uic_err;
 } else {
  return -ENOENT;
 }

 seq_printf(s, "%d\n", *p);
 return 0;
}

static ssize_t ufs_saved_err_write(struct file *file, const char __user *buf,
       size_t count, loff_t *ppos)
{
 struct ufs_debugfs_attr *attr = file->f_inode->i_private;
 struct ufs_hba *hba = hba_from_file(file);
 char val_str[16] = { };
 int val, ret;

 if (count > sizeof(val_str))
  return -EINVAL;
 if (copy_from_user(val_str, buf, count))
  return -EFAULT;
 ret = kstrtoint(val_str, 0, &val);
 if (ret < 0)
  return ret;

 spin_lock_irq(hba->host->host_lock);
 if (strcmp(attr->name, "saved_err") == 0) {
  hba->saved_err = val;
 } else if (strcmp(attr->name, "saved_uic_err") == 0) {
  hba->saved_uic_err = val;
 } else {
  ret = -ENOENT;
 }
 if (ret == 0)
  ufshcd_schedule_eh_work(hba);
 spin_unlock_irq(hba->host->host_lock);

 return ret < 0 ? ret : count;
}

static int ufs_saved_err_open(struct inode *inode, struct file *file)
{
 return single_open(file, ufs_saved_err_show, inode->i_private);
}

static const struct file_operations ufs_saved_err_fops = {
 .owner  = THIS_MODULE,
 .open  = ufs_saved_err_open,
 .read  = seq_read,
 .write  = ufs_saved_err_write,
 .llseek  = seq_lseek,
 .release = single_release,
};

static const struct ufs_debugfs_attr ufs_attrs[] = {
 { "stats", 0400, &ufs_debugfs_stats_fops },
 { "saved_err", 0600, &ufs_saved_err_fops },
 { "saved_uic_err", 0600, &ufs_saved_err_fops },
 { }
};

void ufs_debugfs_hba_init(struct ufs_hba *hba)
{
 const struct ufs_debugfs_attr *attr;
 struct dentry *root;

 /* Set default exception event rate limit period to 20ms */
 hba->debugfs_ee_rate_limit_ms = 20;
 INIT_DELAYED_WORK(&hba->debugfs_ee_work, ufs_debugfs_restart_ee);

 root = debugfs_create_dir(dev_name(hba->dev), ufs_debugfs_root);
 if (IS_ERR_OR_NULL(root))
  return;
 hba->debugfs_root = root;
 d_inode(root)->i_private = hba;
 for (attr = ufs_attrs; attr->name; attr++)
  debugfs_create_file(attr->name, attr->mode, root, (void *)attr,
        attr->fops);
 debugfs_create_file("exception_event_mask", 0600, hba->debugfs_root,
       hba, &ee_usr_mask_fops);
 debugfs_create_u32("exception_event_rate_limit_ms", 0600, hba->debugfs_root,
      &hba->debugfs_ee_rate_limit_ms);
}

void ufs_debugfs_hba_exit(struct ufs_hba *hba)
{
 debugfs_remove_recursive(hba->debugfs_root);
 cancel_delayed_work_sync(&hba->debugfs_ee_work);
}

Messung V0.5
C=97 H=100 G=98

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© 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.