diff options
-rw-r--r-- | drivers/mmc/core/debugfs.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 1237bb4c722b..610dbd1fcc82 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c | |||
@@ -184,6 +184,68 @@ static int mmc_dbg_card_status_get(void *data, u64 *val) | |||
184 | DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get, | 184 | DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get, |
185 | NULL, "%08llx\n"); | 185 | NULL, "%08llx\n"); |
186 | 186 | ||
187 | #define EXT_CSD_STR_LEN 1025 | ||
188 | |||
189 | static int mmc_ext_csd_open(struct inode *inode, struct file *filp) | ||
190 | { | ||
191 | struct mmc_card *card = inode->i_private; | ||
192 | char *buf; | ||
193 | ssize_t n = 0; | ||
194 | u8 *ext_csd; | ||
195 | int err, i; | ||
196 | |||
197 | buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL); | ||
198 | if (!buf) | ||
199 | return -ENOMEM; | ||
200 | |||
201 | ext_csd = kmalloc(512, GFP_KERNEL); | ||
202 | if (!ext_csd) { | ||
203 | err = -ENOMEM; | ||
204 | goto out_free; | ||
205 | } | ||
206 | |||
207 | mmc_claim_host(card->host); | ||
208 | err = mmc_send_ext_csd(card, ext_csd); | ||
209 | mmc_release_host(card->host); | ||
210 | if (err) | ||
211 | goto out_free; | ||
212 | |||
213 | for (i = 511; i >= 0; i--) | ||
214 | n += sprintf(buf + n, "%02x", ext_csd[i]); | ||
215 | n += sprintf(buf + n, "\n"); | ||
216 | BUG_ON(n != EXT_CSD_STR_LEN); | ||
217 | |||
218 | filp->private_data = buf; | ||
219 | kfree(ext_csd); | ||
220 | return 0; | ||
221 | |||
222 | out_free: | ||
223 | kfree(buf); | ||
224 | kfree(ext_csd); | ||
225 | return err; | ||
226 | } | ||
227 | |||
228 | static ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf, | ||
229 | size_t cnt, loff_t *ppos) | ||
230 | { | ||
231 | char *buf = filp->private_data; | ||
232 | |||
233 | return simple_read_from_buffer(ubuf, cnt, ppos, | ||
234 | buf, EXT_CSD_STR_LEN); | ||
235 | } | ||
236 | |||
237 | static int mmc_ext_csd_release(struct inode *inode, struct file *file) | ||
238 | { | ||
239 | kfree(file->private_data); | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static struct file_operations mmc_dbg_ext_csd_fops = { | ||
244 | .open = mmc_ext_csd_open, | ||
245 | .read = mmc_ext_csd_read, | ||
246 | .release = mmc_ext_csd_release, | ||
247 | }; | ||
248 | |||
187 | void mmc_add_card_debugfs(struct mmc_card *card) | 249 | void mmc_add_card_debugfs(struct mmc_card *card) |
188 | { | 250 | { |
189 | struct mmc_host *host = card->host; | 251 | struct mmc_host *host = card->host; |
@@ -211,6 +273,11 @@ void mmc_add_card_debugfs(struct mmc_card *card) | |||
211 | &mmc_dbg_card_status_fops)) | 273 | &mmc_dbg_card_status_fops)) |
212 | goto err; | 274 | goto err; |
213 | 275 | ||
276 | if (mmc_card_mmc(card)) | ||
277 | if (!debugfs_create_file("ext_csd", S_IRUSR, root, card, | ||
278 | &mmc_dbg_ext_csd_fops)) | ||
279 | goto err; | ||
280 | |||
214 | return; | 281 | return; |
215 | 282 | ||
216 | err: | 283 | err: |