• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2020 Intel Corporation
3 
4 #include <linux/debugfs.h>
5 
6 #include "ufs-debugfs.h"
7 #include "ufshcd.h"
8 
9 static struct dentry *ufs_debugfs_root;
10 
ufs_debugfs_init(void)11 void __init ufs_debugfs_init(void)
12 {
13 	ufs_debugfs_root = debugfs_create_dir("ufshcd", NULL);
14 }
15 
ufs_debugfs_exit(void)16 void ufs_debugfs_exit(void)
17 {
18 	debugfs_remove_recursive(ufs_debugfs_root);
19 }
20 
ufs_debugfs_stats_show(struct seq_file * s,void * data)21 static int ufs_debugfs_stats_show(struct seq_file *s, void *data)
22 {
23 	struct ufs_hba *hba = s->private;
24 	struct ufs_event_hist *e = hba->ufs_stats.event;
25 
26 #define PRT(fmt, typ) \
27 	seq_printf(s, fmt, e[UFS_EVT_ ## typ].cnt)
28 
29 	PRT("PHY Adapter Layer errors (except LINERESET): %llu\n", PA_ERR);
30 	PRT("Data Link Layer errors: %llu\n", DL_ERR);
31 	PRT("Network Layer errors: %llu\n", NL_ERR);
32 	PRT("Transport Layer errors: %llu\n", TL_ERR);
33 	PRT("Generic DME errors: %llu\n", DME_ERR);
34 	PRT("Auto-hibernate errors: %llu\n", AUTO_HIBERN8_ERR);
35 	PRT("IS Fatal errors (CEFES, SBFES, HCFES, DFES): %llu\n", FATAL_ERR);
36 	PRT("DME Link Startup errors: %llu\n", LINK_STARTUP_FAIL);
37 	PRT("PM Resume errors: %llu\n", RESUME_ERR);
38 	PRT("PM Suspend errors : %llu\n", SUSPEND_ERR);
39 	PRT("Logical Unit Resets: %llu\n", DEV_RESET);
40 	PRT("Host Resets: %llu\n", HOST_RESET);
41 	PRT("SCSI command aborts: %llu\n", ABORT);
42 #undef PRT
43 	return 0;
44 }
45 DEFINE_SHOW_ATTRIBUTE(ufs_debugfs_stats);
46 
ee_usr_mask_get(void * data,u64 * val)47 static int ee_usr_mask_get(void *data, u64 *val)
48 {
49 	struct ufs_hba *hba = data;
50 
51 	*val = hba->ee_usr_mask;
52 	return 0;
53 }
54 
ufs_debugfs_get_user_access(struct ufs_hba * hba)55 static int ufs_debugfs_get_user_access(struct ufs_hba *hba)
56 __acquires(&hba->host_sem)
57 {
58 	down(&hba->host_sem);
59 	if (!ufshcd_is_user_access_allowed(hba)) {
60 		up(&hba->host_sem);
61 		return -EBUSY;
62 	}
63 	ufshcd_rpm_get_sync(hba);
64 	return 0;
65 }
66 
ufs_debugfs_put_user_access(struct ufs_hba * hba)67 static void ufs_debugfs_put_user_access(struct ufs_hba *hba)
68 __releases(&hba->host_sem)
69 {
70 	ufshcd_rpm_put_sync(hba);
71 	up(&hba->host_sem);
72 }
73 
ee_usr_mask_set(void * data,u64 val)74 static int ee_usr_mask_set(void *data, u64 val)
75 {
76 	struct ufs_hba *hba = data;
77 	int err;
78 
79 	if (val & ~(u64)MASK_EE_STATUS)
80 		return -EINVAL;
81 	err = ufs_debugfs_get_user_access(hba);
82 	if (err)
83 		return err;
84 	err = ufshcd_update_ee_usr_mask(hba, val, MASK_EE_STATUS);
85 	ufs_debugfs_put_user_access(hba);
86 	return err;
87 }
88 
89 DEFINE_DEBUGFS_ATTRIBUTE(ee_usr_mask_fops, ee_usr_mask_get, ee_usr_mask_set, "%#llx\n");
90 
ufs_debugfs_exception_event(struct ufs_hba * hba,u16 status)91 void ufs_debugfs_exception_event(struct ufs_hba *hba, u16 status)
92 {
93 	bool chgd = false;
94 	u16 ee_ctrl_mask;
95 	int err = 0;
96 
97 	if (!hba->debugfs_ee_rate_limit_ms || !status)
98 		return;
99 
100 	mutex_lock(&hba->ee_ctrl_mutex);
101 	ee_ctrl_mask = hba->ee_drv_mask | (hba->ee_usr_mask & ~status);
102 	chgd = ee_ctrl_mask != hba->ee_ctrl_mask;
103 	if (chgd) {
104 		err = __ufshcd_write_ee_control(hba, ee_ctrl_mask);
105 		if (err)
106 			dev_err(hba->dev, "%s: failed to write ee control %d\n",
107 				__func__, err);
108 	}
109 	mutex_unlock(&hba->ee_ctrl_mutex);
110 
111 	if (chgd && !err) {
112 		unsigned long delay = msecs_to_jiffies(hba->debugfs_ee_rate_limit_ms);
113 
114 		queue_delayed_work(system_freezable_wq, &hba->debugfs_ee_work, delay);
115 	}
116 }
117 
ufs_debugfs_restart_ee(struct work_struct * work)118 static void ufs_debugfs_restart_ee(struct work_struct *work)
119 {
120 	struct ufs_hba *hba = container_of(work, struct ufs_hba, debugfs_ee_work.work);
121 
122 	if (!hba->ee_usr_mask || pm_runtime_suspended(hba->dev) ||
123 	    ufs_debugfs_get_user_access(hba))
124 		return;
125 	ufshcd_write_ee_control(hba);
126 	ufs_debugfs_put_user_access(hba);
127 }
128 
ufs_debugfs_hba_init(struct ufs_hba * hba)129 void ufs_debugfs_hba_init(struct ufs_hba *hba)
130 {
131 	/* Set default exception event rate limit period to 20ms */
132 	hba->debugfs_ee_rate_limit_ms = 20;
133 	INIT_DELAYED_WORK(&hba->debugfs_ee_work, ufs_debugfs_restart_ee);
134 	hba->debugfs_root = debugfs_create_dir(dev_name(hba->dev), ufs_debugfs_root);
135 	debugfs_create_file("stats", 0400, hba->debugfs_root, hba, &ufs_debugfs_stats_fops);
136 	debugfs_create_file("exception_event_mask", 0600, hba->debugfs_root,
137 			    hba, &ee_usr_mask_fops);
138 	debugfs_create_u32("exception_event_rate_limit_ms", 0600, hba->debugfs_root,
139 			   &hba->debugfs_ee_rate_limit_ms);
140 }
141 
ufs_debugfs_hba_exit(struct ufs_hba * hba)142 void ufs_debugfs_hba_exit(struct ufs_hba *hba)
143 {
144 	debugfs_remove_recursive(hba->debugfs_root);
145 	cancel_delayed_work_sync(&hba->debugfs_ee_work);
146 }
147