debugfs.c revision 6038f373a3dc1f1c26496e60b6c40b164716f07e
16edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen/* 26edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * Debugfs support for hosts and cards 36edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * 46edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * Copyright (C) 2008 Atmel Corporation 56edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * 66edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * This program is free software; you can redistribute it and/or modify 76edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * it under the terms of the GNU General Public License version 2 as 86edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * published by the Free Software Foundation. 96edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen */ 106edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/debugfs.h> 116edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/fs.h> 126edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/seq_file.h> 135a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 146edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/stat.h> 156edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 16f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen#include <linux/mmc/card.h> 176edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include <linux/mmc/host.h> 186edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 196edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen#include "core.h" 20f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen#include "mmc_ops.h" 216edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 226edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen/* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */ 236edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenstatic int mmc_ios_show(struct seq_file *s, void *data) 246edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{ 256edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen static const char *vdd_str[] = { 266edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [8] = "2.0", 276edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [9] = "2.1", 286edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [10] = "2.2", 296edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [11] = "2.3", 306edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [12] = "2.4", 316edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [13] = "2.5", 326edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [14] = "2.6", 336edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [15] = "2.7", 346edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [16] = "2.8", 356edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [17] = "2.9", 366edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [18] = "3.0", 376edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [19] = "3.1", 386edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [20] = "3.2", 396edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [21] = "3.3", 406edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [22] = "3.4", 416edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [23] = "3.5", 426edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen [24] = "3.6", 436edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen }; 446edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen struct mmc_host *host = s->private; 456edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen struct mmc_ios *ios = &host->ios; 466edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen const char *str; 476edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 486edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen seq_printf(s, "clock:\t\t%u Hz\n", ios->clock); 496edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen seq_printf(s, "vdd:\t\t%u ", ios->vdd); 506edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen if ((1 << ios->vdd) & MMC_VDD_165_195) 516edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen seq_printf(s, "(1.65 - 1.95 V)\n"); 526edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen else if (ios->vdd < (ARRAY_SIZE(vdd_str) - 1) 536edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen && vdd_str[ios->vdd] && vdd_str[ios->vdd + 1]) 546edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen seq_printf(s, "(%s ~ %s V)\n", vdd_str[ios->vdd], 556edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen vdd_str[ios->vdd + 1]); 566edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen else 576edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen seq_printf(s, "(invalid)\n"); 586edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 596edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen switch (ios->bus_mode) { 606edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen case MMC_BUSMODE_OPENDRAIN: 616edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "open drain"; 626edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 636edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen case MMC_BUSMODE_PUSHPULL: 646edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "push-pull"; 656edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 666edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen default: 676edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "invalid"; 686edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 696edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen } 706edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen seq_printf(s, "bus mode:\t%u (%s)\n", ios->bus_mode, str); 716edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 726edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen switch (ios->chip_select) { 736edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen case MMC_CS_DONTCARE: 746edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "don't care"; 756edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 766edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen case MMC_CS_HIGH: 776edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "active high"; 786edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 796edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen case MMC_CS_LOW: 806edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "active low"; 816edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 826edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen default: 836edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "invalid"; 846edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 856edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen } 866edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen seq_printf(s, "chip select:\t%u (%s)\n", ios->chip_select, str); 876edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 886edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen switch (ios->power_mode) { 896edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen case MMC_POWER_OFF: 906edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "off"; 916edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 926edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen case MMC_POWER_UP: 936edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "up"; 946edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 956edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen case MMC_POWER_ON: 966edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "on"; 976edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 986edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen default: 996edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "invalid"; 1006edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 1016edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen } 1026edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen seq_printf(s, "power mode:\t%u (%s)\n", ios->power_mode, str); 1036edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen seq_printf(s, "bus width:\t%u (%u bits)\n", 1046edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen ios->bus_width, 1 << ios->bus_width); 1056edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 1066edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen switch (ios->timing) { 1076edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen case MMC_TIMING_LEGACY: 1086edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "legacy"; 1096edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 1106edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen case MMC_TIMING_MMC_HS: 1116edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "mmc high-speed"; 1126edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 1136edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen case MMC_TIMING_SD_HS: 1146edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "sd high-speed"; 1156edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 1166edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen default: 1176edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen str = "invalid"; 1186edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen break; 1196edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen } 1206edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str); 1216edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 1226edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen return 0; 1236edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen} 1246edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 1256edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenstatic int mmc_ios_open(struct inode *inode, struct file *file) 1266edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{ 1276edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen return single_open(file, mmc_ios_show, inode->i_private); 1286edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen} 1296edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 1306edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenstatic const struct file_operations mmc_ios_fops = { 1316edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen .open = mmc_ios_open, 1326edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen .read = seq_read, 1336edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen .llseek = seq_lseek, 1346edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen .release = single_release, 1356edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen}; 1366edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 1376edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenvoid mmc_add_host_debugfs(struct mmc_host *host) 1386edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{ 1396edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen struct dentry *root; 1406edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 1416edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen root = debugfs_create_dir(mmc_hostname(host), NULL); 1426edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen if (IS_ERR(root)) 1436edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen /* Don't complain -- debugfs just isn't enabled */ 1446edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen return; 1456edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen if (!root) 1466edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen /* Complain -- debugfs is enabled, but it failed to 1476edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen * create the directory. */ 1486edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen goto err_root; 1496edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 1506edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen host->debugfs_root = root; 1516edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 1526edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) 1536edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen goto err_ios; 1546edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 1556edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen return; 1566edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 1576edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenerr_ios: 1586edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen debugfs_remove_recursive(root); 1596edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen host->debugfs_root = NULL; 1606edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenerr_root: 1616edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen dev_err(&host->class_dev, "failed to initialize debugfs\n"); 1626edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen} 1636edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen 1646edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoenvoid mmc_remove_host_debugfs(struct mmc_host *host) 1656edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen{ 1666edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen debugfs_remove_recursive(host->debugfs_root); 1676edd8ee60ac9b974bd6ec3b1bcb2aab02762fa8cHaavard Skinnemoen} 168f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 169f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenstatic int mmc_dbg_card_status_get(void *data, u64 *val) 170f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen{ 171f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen struct mmc_card *card = data; 172f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen u32 status; 173f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen int ret; 174f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 175f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen mmc_claim_host(card->host); 176f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 177f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen ret = mmc_send_status(data, &status); 178f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (!ret) 179f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen *val = status; 180f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 181f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen mmc_release_host(card->host); 182f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 183f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen return ret; 184f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen} 185f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard SkinnemoenDEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get, 186f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen NULL, "%08llx\n"); 187f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 188736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter#define EXT_CSD_STR_LEN 1025 189736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 190736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterstatic int mmc_ext_csd_open(struct inode *inode, struct file *filp) 191736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter{ 192736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter struct mmc_card *card = inode->i_private; 193736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter char *buf; 194736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter ssize_t n = 0; 195736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter u8 *ext_csd; 196736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter int err, i; 197736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 198736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL); 199736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter if (!buf) 200736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter return -ENOMEM; 201736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 202736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter ext_csd = kmalloc(512, GFP_KERNEL); 203736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter if (!ext_csd) { 204736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter err = -ENOMEM; 205736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter goto out_free; 206736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter } 207736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 208736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter mmc_claim_host(card->host); 209736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter err = mmc_send_ext_csd(card, ext_csd); 210736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter mmc_release_host(card->host); 211736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter if (err) 212736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter goto out_free; 213736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 214736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter for (i = 511; i >= 0; i--) 215736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter n += sprintf(buf + n, "%02x", ext_csd[i]); 216736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter n += sprintf(buf + n, "\n"); 217736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter BUG_ON(n != EXT_CSD_STR_LEN); 218736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 219736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter filp->private_data = buf; 220736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter kfree(ext_csd); 221736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter return 0; 222736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 223736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterout_free: 224736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter kfree(buf); 225736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter kfree(ext_csd); 226736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter return err; 227736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter} 228736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 229736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterstatic ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf, 230736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter size_t cnt, loff_t *ppos) 231736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter{ 232736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter char *buf = filp->private_data; 233736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 234736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter return simple_read_from_buffer(ubuf, cnt, ppos, 235736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter buf, EXT_CSD_STR_LEN); 236736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter} 237736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 238736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunterstatic int mmc_ext_csd_release(struct inode *inode, struct file *file) 239736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter{ 240736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter kfree(file->private_data); 241736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter return 0; 242736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter} 243736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 244828c09509b9695271bcbdc53e9fc9a6a737148d2Alexey Dobriyanstatic const struct file_operations mmc_dbg_ext_csd_fops = { 245736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter .open = mmc_ext_csd_open, 246736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter .read = mmc_ext_csd_read, 247736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter .release = mmc_ext_csd_release, 2486038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann .llseek = default_llseek, 249736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter}; 250736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 251f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenvoid mmc_add_card_debugfs(struct mmc_card *card) 252f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen{ 253f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen struct mmc_host *host = card->host; 254f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen struct dentry *root; 255f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 256f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (!host->debugfs_root) 257f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen return; 258f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 259f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root); 260f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (IS_ERR(root)) 261f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen /* Don't complain -- debugfs just isn't enabled */ 262f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen return; 263f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (!root) 264f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen /* Complain -- debugfs is enabled, but it failed to 265f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen * create the directory. */ 266f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen goto err; 267f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 268f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen card->debugfs_root = root; 269f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 270f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (!debugfs_create_x32("state", S_IRUSR, root, &card->state)) 271f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen goto err; 272f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 273f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (mmc_card_mmc(card) || mmc_card_sd(card)) 274f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen if (!debugfs_create_file("status", S_IRUSR, root, card, 275f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen &mmc_dbg_card_status_fops)) 276f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen goto err; 277f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 278736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter if (mmc_card_mmc(card)) 279736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter if (!debugfs_create_file("ext_csd", S_IRUSR, root, card, 280736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter &mmc_dbg_ext_csd_fops)) 281736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter goto err; 282736bb6bb01a2a180b6f062e792bd03658d57ab7eAdrian Hunter 283f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen return; 284f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 285f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenerr: 286f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen debugfs_remove_recursive(root); 287f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen card->debugfs_root = NULL; 288f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen dev_err(&card->dev, "failed to initialize debugfs\n"); 289f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen} 290f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen 291f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoenvoid mmc_remove_card_debugfs(struct mmc_card *card) 292f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen{ 293f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen debugfs_remove_recursive(card->debugfs_root); 294f4b7f927b531ca350cfc4ca1bdc3377dac7f9a32Haavard Skinnemoen} 295