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