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 
11 struct ufs_debugfs_attr {
12 	const char			*name;
13 	mode_t				mode;
14 	const struct file_operations	*fops;
15 };
16 
17 /* @file corresponds to a debugfs attribute in directory hba->debugfs_root. */
hba_from_file(const struct file * file)18 static inline struct ufs_hba *hba_from_file(const struct file *file)
19 {
20 	return d_inode(file->f_path.dentry->d_parent)->i_private;
21 }
22 
ufs_debugfs_init(void)23 void __init ufs_debugfs_init(void)
24 {
25 	ufs_debugfs_root = debugfs_create_dir("ufshcd", NULL);
26 }
27 
ufs_debugfs_exit(void)28 void ufs_debugfs_exit(void)
29 {
30 	debugfs_remove_recursive(ufs_debugfs_root);
31 }
32 
ufs_debugfs_stats_show(struct seq_file * s,void * data)33 static int ufs_debugfs_stats_show(struct seq_file *s, void *data)
34 {
35 	struct ufs_hba *hba = hba_from_file(s->file);
36 	struct ufs_event_hist *e = hba->ufs_stats.event;
37 
38 #define PRT(fmt, typ) \
39 	seq_printf(s, fmt, e[UFS_EVT_ ## typ].cnt)
40 
41 	PRT("PHY Adapter Layer errors (except LINERESET): %llu\n", PA_ERR);
42 	PRT("Data Link Layer errors: %llu\n", DL_ERR);
43 	PRT("Network Layer errors: %llu\n", NL_ERR);
44 	PRT("Transport Layer errors: %llu\n", TL_ERR);
45 	PRT("Generic DME errors: %llu\n", DME_ERR);
46 	PRT("Auto-hibernate errors: %llu\n", AUTO_HIBERN8_ERR);
47 	PRT("IS Fatal errors (CEFES, SBFES, HCFES, DFES): %llu\n", FATAL_ERR);
48 	PRT("DME Link Startup errors: %llu\n", LINK_STARTUP_FAIL);
49 	PRT("PM Resume errors: %llu\n", RESUME_ERR);
50 	PRT("PM Suspend errors : %llu\n", SUSPEND_ERR);
51 	PRT("Logical Unit Resets: %llu\n", DEV_RESET);
52 	PRT("Host Resets: %llu\n", HOST_RESET);
53 	PRT("SCSI command aborts: %llu\n", ABORT);
54 #undef PRT
55 	return 0;
56 }
57 DEFINE_SHOW_ATTRIBUTE(ufs_debugfs_stats);
58 
ee_usr_mask_get(void * data,u64 * val)59 static int ee_usr_mask_get(void *data, u64 *val)
60 {
61 	struct ufs_hba *hba = data;
62 
63 	*val = hba->ee_usr_mask;
64 	return 0;
65 }
66 
ufs_debugfs_get_user_access(struct ufs_hba * hba)67 static int ufs_debugfs_get_user_access(struct ufs_hba *hba)
68 __acquires(&hba->host_sem)
69 {
70 	down(&hba->host_sem);
71 	if (!ufshcd_is_user_access_allowed(hba)) {
72 		up(&hba->host_sem);
73 		return -EBUSY;
74 	}
75 	ufshcd_rpm_get_sync(hba);
76 	return 0;
77 }
78 
ufs_debugfs_put_user_access(struct ufs_hba * hba)79 static void ufs_debugfs_put_user_access(struct ufs_hba *hba)
80 __releases(&hba->host_sem)
81 {
82 	ufshcd_rpm_put_sync(hba);
83 	up(&hba->host_sem);
84 }
85 
ee_usr_mask_set(void * data,u64 val)86 static int ee_usr_mask_set(void *data, u64 val)
87 {
88 	struct ufs_hba *hba = data;
89 	int err;
90 
91 	if (val & ~(u64)MASK_EE_STATUS)
92 		return -EINVAL;
93 	err = ufs_debugfs_get_user_access(hba);
94 	if (err)
95 		return err;
96 	err = ufshcd_update_ee_usr_mask(hba, val, MASK_EE_STATUS);
97 	ufs_debugfs_put_user_access(hba);
98 	return err;
99 }
100 
101 DEFINE_DEBUGFS_ATTRIBUTE(ee_usr_mask_fops, ee_usr_mask_get, ee_usr_mask_set, "%#llx\n");
102 
ufs_debugfs_exception_event(struct ufs_hba * hba,u16 status)103 void ufs_debugfs_exception_event(struct ufs_hba *hba, u16 status)
104 {
105 	bool chgd = false;
106 	u16 ee_ctrl_mask;
107 	int err = 0;
108 
109 	if (!hba->debugfs_ee_rate_limit_ms || !status)
110 		return;
111 
112 	mutex_lock(&hba->ee_ctrl_mutex);
113 	ee_ctrl_mask = hba->ee_drv_mask | (hba->ee_usr_mask & ~status);
114 	chgd = ee_ctrl_mask != hba->ee_ctrl_mask;
115 	if (chgd) {
116 		err = __ufshcd_write_ee_control(hba, ee_ctrl_mask);
117 		if (err)
118 			dev_err(hba->dev, "%s: failed to write ee control %d\n",
119 				__func__, err);
120 	}
121 	mutex_unlock(&hba->ee_ctrl_mutex);
122 
123 	if (chgd && !err) {
124 		unsigned long delay = msecs_to_jiffies(hba->debugfs_ee_rate_limit_ms);
125 
126 		queue_delayed_work(system_freezable_wq, &hba->debugfs_ee_work, delay);
127 	}
128 }
129 
ufs_debugfs_restart_ee(struct work_struct * work)130 static void ufs_debugfs_restart_ee(struct work_struct *work)
131 {
132 	struct ufs_hba *hba = container_of(work, struct ufs_hba, debugfs_ee_work.work);
133 
134 	if (!hba->ee_usr_mask || pm_runtime_suspended(hba->dev) ||
135 	    ufs_debugfs_get_user_access(hba))
136 		return;
137 	ufshcd_write_ee_control(hba);
138 	ufs_debugfs_put_user_access(hba);
139 }
140 
ufs_saved_err_show(struct seq_file * s,void * data)141 static int ufs_saved_err_show(struct seq_file *s, void *data)
142 {
143 	struct ufs_debugfs_attr *attr = s->private;
144 	struct ufs_hba *hba = hba_from_file(s->file);
145 	const int *p;
146 
147 	if (strcmp(attr->name, "saved_err") == 0) {
148 		p = &hba->saved_err;
149 	} else if (strcmp(attr->name, "saved_uic_err") == 0) {
150 		p = &hba->saved_uic_err;
151 	} else {
152 		return -ENOENT;
153 	}
154 
155 	seq_printf(s, "%d\n", *p);
156 	return 0;
157 }
158 
ufs_saved_err_write(struct file * file,const char __user * buf,size_t count,loff_t * ppos)159 static ssize_t ufs_saved_err_write(struct file *file, const char __user *buf,
160 				   size_t count, loff_t *ppos)
161 {
162 	struct ufs_debugfs_attr *attr = file->f_inode->i_private;
163 	struct ufs_hba *hba = hba_from_file(file);
164 	char val_str[16] = { };
165 	int val, ret;
166 
167 	if (count > sizeof(val_str))
168 		return -EINVAL;
169 	if (copy_from_user(val_str, buf, count))
170 		return -EFAULT;
171 	ret = kstrtoint(val_str, 0, &val);
172 	if (ret < 0)
173 		return ret;
174 
175 	spin_lock_irq(hba->host->host_lock);
176 	if (strcmp(attr->name, "saved_err") == 0) {
177 		hba->saved_err = val;
178 	} else if (strcmp(attr->name, "saved_uic_err") == 0) {
179 		hba->saved_uic_err = val;
180 	} else {
181 		ret = -ENOENT;
182 	}
183 	if (ret == 0)
184 		ufshcd_schedule_eh_work(hba);
185 	spin_unlock_irq(hba->host->host_lock);
186 
187 	return ret < 0 ? ret : count;
188 }
189 
ufs_saved_err_open(struct inode * inode,struct file * file)190 static int ufs_saved_err_open(struct inode *inode, struct file *file)
191 {
192 	return single_open(file, ufs_saved_err_show, inode->i_private);
193 }
194 
195 static const struct file_operations ufs_saved_err_fops = {
196 	.owner		= THIS_MODULE,
197 	.open		= ufs_saved_err_open,
198 	.read		= seq_read,
199 	.write		= ufs_saved_err_write,
200 	.llseek		= seq_lseek,
201 	.release	= single_release,
202 };
203 
204 static const struct ufs_debugfs_attr ufs_attrs[] = {
205 	{ "stats", 0400, &ufs_debugfs_stats_fops },
206 	{ "saved_err", 0600, &ufs_saved_err_fops },
207 	{ "saved_uic_err", 0600, &ufs_saved_err_fops },
208 	{ }
209 };
210 
ufs_debugfs_hba_init(struct ufs_hba * hba)211 void ufs_debugfs_hba_init(struct ufs_hba *hba)
212 {
213 	const struct ufs_debugfs_attr *attr;
214 	struct dentry *root;
215 
216 	/* Set default exception event rate limit period to 20ms */
217 	hba->debugfs_ee_rate_limit_ms = 20;
218 	INIT_DELAYED_WORK(&hba->debugfs_ee_work, ufs_debugfs_restart_ee);
219 
220 	root = debugfs_create_dir(dev_name(hba->dev), ufs_debugfs_root);
221 	if (IS_ERR_OR_NULL(root))
222 		return;
223 	hba->debugfs_root = root;
224 	d_inode(root)->i_private = hba;
225 	for (attr = ufs_attrs; attr->name; attr++)
226 		debugfs_create_file(attr->name, attr->mode, root, (void *)attr,
227 				    attr->fops);
228 	debugfs_create_file("exception_event_mask", 0600, hba->debugfs_root,
229 			    hba, &ee_usr_mask_fops);
230 	debugfs_create_u32("exception_event_rate_limit_ms", 0600, hba->debugfs_root,
231 			   &hba->debugfs_ee_rate_limit_ms);
232 }
233 
ufs_debugfs_hba_exit(struct ufs_hba * hba)234 void ufs_debugfs_hba_exit(struct ufs_hba *hba)
235 {
236 	debugfs_remove_recursive(hba->debugfs_root);
237 	cancel_delayed_work_sync(&hba->debugfs_ee_work);
238 }
239