drm/nv50: fix iommu errors caused by device reading from address 0
[safe/jmp/linux-2.6] / drivers / mmc / core / debugfs.c
index 1237bb4..53cb380 100644 (file)
@@ -10,6 +10,7 @@
 #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>
@@ -184,6 +185,68 @@ static int mmc_dbg_card_status_get(void *data, u64 *val)
 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;
@@ -211,6 +274,11 @@ void mmc_add_card_debugfs(struct mmc_card *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: