drm/nv50: fix iommu errors caused by device reading from address 0
[safe/jmp/linux-2.6] / drivers / mmc / core / debugfs.c
index 133c6e5..53cb380 100644 (file)
 #include <linux/debugfs.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
+#include <linux/slab.h>
 #include <linux/stat.h>
 
+#include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 
 #include "core.h"
+#include "mmc_ops.h"
 
 /* The debugfs functions are optimized away when CONFIG_DEBUG_FS isn't set. */
 static int mmc_ios_show(struct seq_file *s, void *data)
@@ -162,3 +165,129 @@ void mmc_remove_host_debugfs(struct mmc_host *host)
 {
        debugfs_remove_recursive(host->debugfs_root);
 }
+
+static int mmc_dbg_card_status_get(void *data, u64 *val)
+{
+       struct mmc_card *card = data;
+       u32             status;
+       int             ret;
+
+       mmc_claim_host(card->host);
+
+       ret = mmc_send_status(data, &status);
+       if (!ret)
+               *val = status;
+
+       mmc_release_host(card->host);
+
+       return ret;
+}
+DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get,
+               NULL, "%08llx\n");
+
+#define EXT_CSD_STR_LEN 1025
+
+static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
+{
+       struct mmc_card *card = inode->i_private;
+       char *buf;
+       ssize_t n = 0;
+       u8 *ext_csd;
+       int err, i;
+
+       buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       ext_csd = kmalloc(512, GFP_KERNEL);
+       if (!ext_csd) {
+               err = -ENOMEM;
+               goto out_free;
+       }
+
+       mmc_claim_host(card->host);
+       err = mmc_send_ext_csd(card, ext_csd);
+       mmc_release_host(card->host);
+       if (err)
+               goto out_free;
+
+       for (i = 511; i >= 0; i--)
+               n += sprintf(buf + n, "%02x", ext_csd[i]);
+       n += sprintf(buf + n, "\n");
+       BUG_ON(n != EXT_CSD_STR_LEN);
+
+       filp->private_data = buf;
+       kfree(ext_csd);
+       return 0;
+
+out_free:
+       kfree(buf);
+       kfree(ext_csd);
+       return err;
+}
+
+static ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf,
+                               size_t cnt, loff_t *ppos)
+{
+       char *buf = filp->private_data;
+
+       return simple_read_from_buffer(ubuf, cnt, ppos,
+                                      buf, EXT_CSD_STR_LEN);
+}
+
+static int mmc_ext_csd_release(struct inode *inode, struct file *file)
+{
+       kfree(file->private_data);
+       return 0;
+}
+
+static const struct file_operations mmc_dbg_ext_csd_fops = {
+       .open           = mmc_ext_csd_open,
+       .read           = mmc_ext_csd_read,
+       .release        = mmc_ext_csd_release,
+};
+
+void mmc_add_card_debugfs(struct mmc_card *card)
+{
+       struct mmc_host *host = card->host;
+       struct dentry   *root;
+
+       if (!host->debugfs_root)
+               return;
+
+       root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root);
+       if (IS_ERR(root))
+               /* Don't complain -- debugfs just isn't enabled */
+               return;
+       if (!root)
+               /* Complain -- debugfs is enabled, but it failed to
+                * create the directory. */
+               goto err;
+
+       card->debugfs_root = root;
+
+       if (!debugfs_create_x32("state", S_IRUSR, root, &card->state))
+               goto err;
+
+       if (mmc_card_mmc(card) || mmc_card_sd(card))
+               if (!debugfs_create_file("status", S_IRUSR, root, card,
+                                       &mmc_dbg_card_status_fops))
+                       goto err;
+
+       if (mmc_card_mmc(card))
+               if (!debugfs_create_file("ext_csd", S_IRUSR, root, card,
+                                       &mmc_dbg_ext_csd_fops))
+                       goto err;
+
+       return;
+
+err:
+       debugfs_remove_recursive(root);
+       card->debugfs_root = NULL;
+       dev_err(&card->dev, "failed to initialize debugfs\n");
+}
+
+void mmc_remove_card_debugfs(struct mmc_card *card)
+{
+       debugfs_remove_recursive(card->debugfs_root);
+}