[Feature][task-view-1335]Add command to query EMMC health status
Only Configure: No
Affected branch: master
Affected module: EMMC
Is it affected on both ZXIC and MTK:only zxic
Self-test: Yes
Doc Update:Yes
Change-Id: Ibb57d00bdd21b54b0aab7ee85c1bb201ac0c8b49
diff --git a/cap/zx297520v3/zxic_code/zxic_source/linux-5.10/drivers/mmc/core/block.c b/cap/zx297520v3/zxic_code/zxic_source/linux-5.10/drivers/mmc/core/block.c
old mode 100644
new mode 100755
index 6622e32..af57016
--- a/cap/zx297520v3/zxic_code/zxic_source/linux-5.10/drivers/mmc/core/block.c
+++ b/cap/zx297520v3/zxic_code/zxic_source/linux-5.10/drivers/mmc/core/block.c
@@ -132,6 +132,9 @@
/* debugfs files (only in main mmc_blk_data) */
struct dentry *status_dentry;
struct dentry *ext_csd_dentry;
+//cz.li@20250420 for emmc health begin
+ struct dentry *health_dentry;
+//cz.li@20250420 for emmc health begin
};
/* Device type for RPMB character devices */
@@ -1042,6 +1045,12 @@
ext_csd = mq_rq->drv_op_data;
ret = mmc_get_ext_csd(card, ext_csd);
break;
+//cz.li@20250420 for emmc health begin
+ case MMC_DRV_OP_GET_HEALTH:
+ ext_csd = mq_rq->drv_op_data;
+ ret = mmc_get_ext_csd(card, ext_csd);
+ break;
+//cz.li@20250420 for emmc health end
default:
pr_err("%s: unknown driver specific operation\n",
md->disk->disk_name);
@@ -2837,6 +2846,92 @@
.llseek = default_llseek,
};
+//cz.li@20250420 for emmc health begin
+#define HEALTH_STR_LEN 2
+static int mmc_health_open(struct inode *inode, struct file *filp)
+{
+ struct mmc_card *card = inode->i_private;
+ struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
+ struct mmc_queue *mq = &md->queue;
+ struct request *req;
+ char *buf;
+ u8 *ext_csd = NULL;
+ int err;
+ ssize_t n;
+ unsigned int health;
+ char health_buf[64];
+ //printk("cy-health open\n");
+ buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* Ask the block layer for the EXT CSD */
+ req = blk_get_request(mq->queue, REQ_OP_DRV_IN, 0);
+ if (IS_ERR(req)) {
+ err = PTR_ERR(req);
+ goto out_free;
+ }
+ req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_HEALTH;
+ req_to_mmc_queue_req(req)->drv_op_data = &ext_csd;
+ //printk("cy- blk_execute_rq begin\n");
+ blk_execute_rq(mq->queue, NULL, req, 0);
+ //printk("cy- blk_execute_rq end\n");
+ err = req_to_mmc_queue_req(req)->drv_op_result;
+ //printk("cy-blk_put_request begin\n");
+ blk_put_request(req);
+ //printk("cy-blk_put_request end\n");
+ if (ext_csd == NULL) {
+ printk("EXT_CSD IF NULL\n");
+ goto out_free;
+ }
+ if (err) {
+ pr_err("FAILED %d\n", err);
+ if (ext_csd != NULL)
+ kfree(ext_csd);
+ goto out_free;
+ }
+
+ health = ext_csd[269];
+ //printk("cy-bad health %d\n",ext_csd[269]);
+ n = sprintf(buf, "%02x", health);
+ if (n != HEALTH_STR_LEN) {
+ //printk("cy-bad count %d , %d\n", (int)n , HEALTH_STR_LEN);
+ err = -EINVAL;
+ kfree(ext_csd);
+ goto out_free;
+ }
+
+ filp->private_data = buf;
+ kfree(ext_csd);
+ return 0;
+out_free:
+ kfree(buf);
+ return err;
+}
+
+static ssize_t mmc_health_read(struct file *filp, char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ char *buf = filp->private_data;
+ printk("cy-mmc_ext_csd_read\n");
+ return simple_read_from_buffer(ubuf, cnt, ppos,
+ buf, HEALTH_STR_LEN);
+}
+
+static int mmc_health_release(struct inode *inode, struct file *file)
+{
+ kfree(file->private_data);
+ return 0;
+}
+
+static const struct file_operations mmc_dbg_health_fops = {
+ .open = mmc_health_open,
+ .read = mmc_health_read,
+ .release = mmc_health_release,
+ .llseek = default_llseek,
+};
+//cz.li@20250420 for emmc health end
+
static int mmc_blk_add_debugfs(struct mmc_card *card, struct mmc_blk_data *md)
{
struct dentry *root;
@@ -2862,7 +2957,13 @@
if (!md->ext_csd_dentry)
return -EIO;
}
-
+//cz.li@20250420 for emmc health begin
+ if (mmc_card_mmc(card)) {
+ md->health_dentry=
+ debugfs_create_file("health", S_IRUSR, root, card,
+ &mmc_dbg_health_fops);
+ }
+//cz.li@20250420 for emmc health end
return 0;
}
@@ -2881,6 +2982,13 @@
debugfs_remove(md->ext_csd_dentry);
md->ext_csd_dentry = NULL;
}
+
+//cz.li@20250420 for emmc health begin
+ if (!IS_ERR_OR_NULL(md->health_dentry)) {
+ debugfs_remove(md->health_dentry);
+ md->health_dentry= NULL;
+ }
+//cz.li@20250420 for emmc health end
}
#else
diff --git a/cap/zx297520v3/zxic_code/zxic_source/linux-5.10/drivers/mmc/core/queue.h b/cap/zx297520v3/zxic_code/zxic_source/linux-5.10/drivers/mmc/core/queue.h
old mode 100644
new mode 100755
index fd11491..6713585
--- a/cap/zx297520v3/zxic_code/zxic_source/linux-5.10/drivers/mmc/core/queue.h
+++ b/cap/zx297520v3/zxic_code/zxic_source/linux-5.10/drivers/mmc/core/queue.h
@@ -59,6 +59,9 @@
MMC_DRV_OP_BOOT_WP,
MMC_DRV_OP_GET_CARD_STATUS,
MMC_DRV_OP_GET_EXT_CSD,
+//cz.li@20250420 for emmc health begin
+ MMC_DRV_OP_GET_HEALTH,
+//cz.li@20250420 for emmc health end
};
struct mmc_queue_req {