Loading drivers/scsi/ufs/debugfs.c +63 −27 Original line number Diff line number Diff line Loading @@ -169,15 +169,17 @@ static void ufsdbg_setup_fault_injection(struct ufs_hba *hba) #endif /* CONFIG_UFS_FAULT_INJECTION */ #define BUFF_LINE_CAPACITY 16 #define TAB_CHARS 8 static int ufsdbg_tag_stats_show(struct seq_file *file, void *data) { struct ufs_hba *hba = (struct ufs_hba *)file->private; struct ufs_stats *ufs_stats; int i; int i, j; int max_depth; bool is_tag_empty = true; unsigned long flags; char *sep = " | * | "; if (!hba) goto exit; Loading @@ -186,27 +188,44 @@ static int ufsdbg_tag_stats_show(struct seq_file *file, void *data) if (!ufs_stats->enabled) { pr_debug("%s: ufs statistics are disabled\n", __func__); seq_puts(file, "ufs statistics are disabled"); goto exit; } max_depth = hba->nutrs; pr_debug("%s: UFS tag statistics:\n", __func__); pr_debug("%s: Max tagged command queue depth is %d", __func__, max_depth); spin_lock_irqsave(hba->host->host_lock, flags); for (i = 0 ; i < max_depth ; ++i) { if (hba->ufs_stats.tag_stats[i] != 0) { is_tag_empty = false; /* Header */ seq_printf(file, " Tag Stat\t\t%s Queue Fullness\n", sep); for (i = 0; i < TAB_CHARS * (TS_NUM_STATS + 4); i++) { seq_puts(file, "-"); if (i == (TAB_CHARS * 3 - 1)) seq_puts(file, sep); } seq_printf(file, "%s: Dispatched tag %d - %llu times\n", __func__, i, ufs_stats->tag_stats[i]); "\n #\tnum uses\t%s\t #\tAll\t Read\t Write\t Urgent\t Flush\n", sep); /* values */ for (i = 0; i < max_depth; i++) { if (ufs_stats->tag_stats[i][0] <= 0 && ufs_stats->tag_stats[i][1] <= 0 && ufs_stats->tag_stats[i][2] <= 0 && ufs_stats->tag_stats[i][3] <= 0 && ufs_stats->tag_stats[i][4] <= 0) continue; pr_debug("%s: Dispatched tag %d - %llu times\n", __func__, i, ufs_stats->tag_stats[i]); is_tag_empty = false; seq_printf(file, " %d\t ", i); for (j = 0; j < TS_NUM_STATS; j++) { seq_printf(file, "%llu\t ", ufs_stats->tag_stats[i][j]); if (j == 0) seq_printf(file, "\t%s\t %d\t%llu\t ", sep, i, ufs_stats->tag_stats[i][j+1] + ufs_stats->tag_stats[i][j+2] + ufs_stats->tag_stats[i][j+3]); } seq_puts(file, "\n"); } spin_unlock_irqrestore(hba->host->host_lock, flags); Loading @@ -229,7 +248,7 @@ static ssize_t ufsdbg_tag_stats_write(struct file *filp, struct ufs_hba *hba = filp->f_mapping->host->i_private; struct ufs_stats *ufs_stats; int val = 0; int ret; int ret, bit = 0; unsigned long flags; ret = kstrtoint_from_user(ubuf, cnt, 0, &val); Loading @@ -248,8 +267,15 @@ static ssize_t ufsdbg_tag_stats_write(struct file *filp, ufs_stats->enabled = true; pr_debug("%s: Enabling & Resetting UFS tag statistics", __func__); memset(ufs_stats->tag_stats, 0, sizeof(*ufs_stats->tag_stats) * hba->nutrs); memset(hba->ufs_stats.tag_stats[0], 0, sizeof(**hba->ufs_stats.tag_stats) * TS_NUM_STATS * hba->nutrs); /* initialize current queue depth */ ufs_stats->q_depth = 0; for_each_set_bit_from(bit, &hba->outstanding_reqs, hba->nutrs) ufs_stats->q_depth++; pr_debug("%s: Enabled UFS tag statistics", __func__); } spin_unlock_irqrestore(hba->host->host_lock, flags); Loading @@ -264,19 +290,29 @@ static const struct file_operations ufsdbg_tag_stats_fops = { static int ufshcd_init_tag_statistics(struct ufs_hba *hba) { struct ufs_stats *stats = &hba->ufs_stats; int ret = 0; int i; hba->ufs_stats.tag_stats = kzalloc(hba->nutrs * sizeof(u64), stats->enabled = false; stats->tag_stats = kzalloc(sizeof(*stats->tag_stats) * hba->nutrs, GFP_KERNEL); if (!hba->ufs_stats.tag_stats) { dev_err(hba->dev, "%s: Unable to allocate UFS tag_stats", __func__); ret = -ENOMEM; goto exit; } if (!hba->ufs_stats.tag_stats) goto no_mem; hba->ufs_stats.enabled = false; stats->tag_stats[0] = kzalloc(sizeof(**stats->tag_stats) * TS_NUM_STATS * hba->nutrs, GFP_KERNEL); if (!stats->tag_stats[0]) goto no_mem; for (i = 1; i < hba->nutrs; i++) stats->tag_stats[i] = &stats->tag_stats[0][i * TS_NUM_STATS]; goto exit; no_mem: dev_err(hba->dev, "%s: Unable to allocate UFS tag_stats", __func__); ret = -ENOMEM; exit: return ret; } Loading drivers/scsi/ufs/ufshcd.c +38 −9 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ * * This code is based on drivers/scsi/ufs/ufshcd.c * Copyright (C) 2011-2013 Samsung India Software Operations * Copyright (c) 2013, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * Authors: * Santosh Yaraganavi <santosh.sy@samsung.com> Loading Loading @@ -50,19 +50,47 @@ #ifdef CONFIG_DEBUG_FS #define UFSHCD_UPDATE_TAG_STATS(hba, tag) \ do { \ if (hba->ufs_stats.enabled) { \ hba->ufs_stats.tag_stats[tag]++; \ } \ } while (0); struct request *rq = hba->lrb[task_tag].cmd ? \ hba->lrb[task_tag].cmd->request : NULL; \ u64 **tag_stats = hba->ufs_stats.tag_stats; \ int rq_type = -1; \ if (!hba->ufs_stats.enabled) \ break; \ tag_stats[tag][TS_TAG]++; \ if (!rq) \ break; \ WARN_ON(hba->ufs_stats.q_depth > hba->nutrs); \ if (rq_data_dir(rq) == READ) \ rq_type = (rq->cmd_flags & REQ_URGENT) ?\ TS_URGENT : TS_READ; \ else if (rq_data_dir(rq) == WRITE) \ rq_type = TS_WRITE; \ else if (rq->cmd_flags & REQ_FLUSH) \ rq_type = TS_FLUSH; \ else \ break; \ tag_stats[hba->ufs_stats.q_depth++][rq_type]++; \ } while (0) #define UFSHCD_UPDATE_TAG_STATS_COMPLETION(hba, cmd) \ do { \ struct request *rq = cmd ? cmd->request : NULL; \ if (cmd->request && \ ((rq_data_dir(rq) == READ) || \ (rq_data_dir(rq) == WRITE) || \ (rq->cmd_flags & REQ_FLUSH))) \ hba->ufs_stats.q_depth--; \ } while (0) #define UFSDBG_ADD_DEBUGFS(hba) ufsdbg_add_debugfs(hba); #define UFSDBG_REMOVE_DEBUGFS(hba) ufsdbg_remove_debugfs(hba); #else #define UFSHCD_UPDATE_TAG_STATS(hba, tag) do {} while (0); #define UFSDBG_ADD_DEBUGFS(hba) do {} while (0); #define UFSDBG_REMOVE_DEBUGFS(hba) do {} while (0); #define UFSHCD_UPDATE_TAG_STATS(hba, tag) #define UFSHCD_UPDATE_TAG_STATS_COMPLETION(hba, cmd) #define UFSDBG_ADD_DEBUGFS(hba) #define UFSDBG_REMOVE_DEBUGFS(hba) #endif Loading Loading @@ -888,7 +916,7 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag) { __set_bit(task_tag, &hba->outstanding_reqs); ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL); UFSHCD_UPDATE_TAG_STATS(hba, task_tag) UFSHCD_UPDATE_TAG_STATS(hba, task_tag); } /** Loading Loading @@ -3285,6 +3313,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) lrbp = &hba->lrb[index]; cmd = lrbp->cmd; if (cmd) { UFSHCD_UPDATE_TAG_STATS_COMPLETION(hba, cmd); result = ufshcd_transfer_rsp_status(hba, lrbp); scsi_dma_unmap(cmd); cmd->result = result; Loading drivers/scsi/ufs/ufshcd.h +14 −1 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ * * This code is based on drivers/scsi/ufs/ufshcd.h * Copyright (C) 2011-2013 Samsung India Software Operations * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * Authors: * Santosh Yaraganavi <santosh.sy@samsung.com> Loading Loading @@ -206,8 +207,9 @@ struct ufs_dev_cmd { #ifdef CONFIG_DEBUG_FS struct ufs_stats { u64 *tag_stats; bool enabled; u64 **tag_stats; int q_depth; }; struct debugfs_files { Loading @@ -220,6 +222,17 @@ struct debugfs_files { struct fault_attr fail_attr; #endif }; /* tag stats statistics types */ enum ts_types { TS_NOT_SUPPORTED = -1, TS_TAG = 0, TS_READ = 1, TS_WRITE = 2, TS_URGENT = 3, TS_FLUSH = 4, TS_NUM_STATS = 5, }; #endif /** Loading Loading
drivers/scsi/ufs/debugfs.c +63 −27 Original line number Diff line number Diff line Loading @@ -169,15 +169,17 @@ static void ufsdbg_setup_fault_injection(struct ufs_hba *hba) #endif /* CONFIG_UFS_FAULT_INJECTION */ #define BUFF_LINE_CAPACITY 16 #define TAB_CHARS 8 static int ufsdbg_tag_stats_show(struct seq_file *file, void *data) { struct ufs_hba *hba = (struct ufs_hba *)file->private; struct ufs_stats *ufs_stats; int i; int i, j; int max_depth; bool is_tag_empty = true; unsigned long flags; char *sep = " | * | "; if (!hba) goto exit; Loading @@ -186,27 +188,44 @@ static int ufsdbg_tag_stats_show(struct seq_file *file, void *data) if (!ufs_stats->enabled) { pr_debug("%s: ufs statistics are disabled\n", __func__); seq_puts(file, "ufs statistics are disabled"); goto exit; } max_depth = hba->nutrs; pr_debug("%s: UFS tag statistics:\n", __func__); pr_debug("%s: Max tagged command queue depth is %d", __func__, max_depth); spin_lock_irqsave(hba->host->host_lock, flags); for (i = 0 ; i < max_depth ; ++i) { if (hba->ufs_stats.tag_stats[i] != 0) { is_tag_empty = false; /* Header */ seq_printf(file, " Tag Stat\t\t%s Queue Fullness\n", sep); for (i = 0; i < TAB_CHARS * (TS_NUM_STATS + 4); i++) { seq_puts(file, "-"); if (i == (TAB_CHARS * 3 - 1)) seq_puts(file, sep); } seq_printf(file, "%s: Dispatched tag %d - %llu times\n", __func__, i, ufs_stats->tag_stats[i]); "\n #\tnum uses\t%s\t #\tAll\t Read\t Write\t Urgent\t Flush\n", sep); /* values */ for (i = 0; i < max_depth; i++) { if (ufs_stats->tag_stats[i][0] <= 0 && ufs_stats->tag_stats[i][1] <= 0 && ufs_stats->tag_stats[i][2] <= 0 && ufs_stats->tag_stats[i][3] <= 0 && ufs_stats->tag_stats[i][4] <= 0) continue; pr_debug("%s: Dispatched tag %d - %llu times\n", __func__, i, ufs_stats->tag_stats[i]); is_tag_empty = false; seq_printf(file, " %d\t ", i); for (j = 0; j < TS_NUM_STATS; j++) { seq_printf(file, "%llu\t ", ufs_stats->tag_stats[i][j]); if (j == 0) seq_printf(file, "\t%s\t %d\t%llu\t ", sep, i, ufs_stats->tag_stats[i][j+1] + ufs_stats->tag_stats[i][j+2] + ufs_stats->tag_stats[i][j+3]); } seq_puts(file, "\n"); } spin_unlock_irqrestore(hba->host->host_lock, flags); Loading @@ -229,7 +248,7 @@ static ssize_t ufsdbg_tag_stats_write(struct file *filp, struct ufs_hba *hba = filp->f_mapping->host->i_private; struct ufs_stats *ufs_stats; int val = 0; int ret; int ret, bit = 0; unsigned long flags; ret = kstrtoint_from_user(ubuf, cnt, 0, &val); Loading @@ -248,8 +267,15 @@ static ssize_t ufsdbg_tag_stats_write(struct file *filp, ufs_stats->enabled = true; pr_debug("%s: Enabling & Resetting UFS tag statistics", __func__); memset(ufs_stats->tag_stats, 0, sizeof(*ufs_stats->tag_stats) * hba->nutrs); memset(hba->ufs_stats.tag_stats[0], 0, sizeof(**hba->ufs_stats.tag_stats) * TS_NUM_STATS * hba->nutrs); /* initialize current queue depth */ ufs_stats->q_depth = 0; for_each_set_bit_from(bit, &hba->outstanding_reqs, hba->nutrs) ufs_stats->q_depth++; pr_debug("%s: Enabled UFS tag statistics", __func__); } spin_unlock_irqrestore(hba->host->host_lock, flags); Loading @@ -264,19 +290,29 @@ static const struct file_operations ufsdbg_tag_stats_fops = { static int ufshcd_init_tag_statistics(struct ufs_hba *hba) { struct ufs_stats *stats = &hba->ufs_stats; int ret = 0; int i; hba->ufs_stats.tag_stats = kzalloc(hba->nutrs * sizeof(u64), stats->enabled = false; stats->tag_stats = kzalloc(sizeof(*stats->tag_stats) * hba->nutrs, GFP_KERNEL); if (!hba->ufs_stats.tag_stats) { dev_err(hba->dev, "%s: Unable to allocate UFS tag_stats", __func__); ret = -ENOMEM; goto exit; } if (!hba->ufs_stats.tag_stats) goto no_mem; hba->ufs_stats.enabled = false; stats->tag_stats[0] = kzalloc(sizeof(**stats->tag_stats) * TS_NUM_STATS * hba->nutrs, GFP_KERNEL); if (!stats->tag_stats[0]) goto no_mem; for (i = 1; i < hba->nutrs; i++) stats->tag_stats[i] = &stats->tag_stats[0][i * TS_NUM_STATS]; goto exit; no_mem: dev_err(hba->dev, "%s: Unable to allocate UFS tag_stats", __func__); ret = -ENOMEM; exit: return ret; } Loading
drivers/scsi/ufs/ufshcd.c +38 −9 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ * * This code is based on drivers/scsi/ufs/ufshcd.c * Copyright (C) 2011-2013 Samsung India Software Operations * Copyright (c) 2013, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * Authors: * Santosh Yaraganavi <santosh.sy@samsung.com> Loading Loading @@ -50,19 +50,47 @@ #ifdef CONFIG_DEBUG_FS #define UFSHCD_UPDATE_TAG_STATS(hba, tag) \ do { \ if (hba->ufs_stats.enabled) { \ hba->ufs_stats.tag_stats[tag]++; \ } \ } while (0); struct request *rq = hba->lrb[task_tag].cmd ? \ hba->lrb[task_tag].cmd->request : NULL; \ u64 **tag_stats = hba->ufs_stats.tag_stats; \ int rq_type = -1; \ if (!hba->ufs_stats.enabled) \ break; \ tag_stats[tag][TS_TAG]++; \ if (!rq) \ break; \ WARN_ON(hba->ufs_stats.q_depth > hba->nutrs); \ if (rq_data_dir(rq) == READ) \ rq_type = (rq->cmd_flags & REQ_URGENT) ?\ TS_URGENT : TS_READ; \ else if (rq_data_dir(rq) == WRITE) \ rq_type = TS_WRITE; \ else if (rq->cmd_flags & REQ_FLUSH) \ rq_type = TS_FLUSH; \ else \ break; \ tag_stats[hba->ufs_stats.q_depth++][rq_type]++; \ } while (0) #define UFSHCD_UPDATE_TAG_STATS_COMPLETION(hba, cmd) \ do { \ struct request *rq = cmd ? cmd->request : NULL; \ if (cmd->request && \ ((rq_data_dir(rq) == READ) || \ (rq_data_dir(rq) == WRITE) || \ (rq->cmd_flags & REQ_FLUSH))) \ hba->ufs_stats.q_depth--; \ } while (0) #define UFSDBG_ADD_DEBUGFS(hba) ufsdbg_add_debugfs(hba); #define UFSDBG_REMOVE_DEBUGFS(hba) ufsdbg_remove_debugfs(hba); #else #define UFSHCD_UPDATE_TAG_STATS(hba, tag) do {} while (0); #define UFSDBG_ADD_DEBUGFS(hba) do {} while (0); #define UFSDBG_REMOVE_DEBUGFS(hba) do {} while (0); #define UFSHCD_UPDATE_TAG_STATS(hba, tag) #define UFSHCD_UPDATE_TAG_STATS_COMPLETION(hba, cmd) #define UFSDBG_ADD_DEBUGFS(hba) #define UFSDBG_REMOVE_DEBUGFS(hba) #endif Loading Loading @@ -888,7 +916,7 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag) { __set_bit(task_tag, &hba->outstanding_reqs); ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL); UFSHCD_UPDATE_TAG_STATS(hba, task_tag) UFSHCD_UPDATE_TAG_STATS(hba, task_tag); } /** Loading Loading @@ -3285,6 +3313,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) lrbp = &hba->lrb[index]; cmd = lrbp->cmd; if (cmd) { UFSHCD_UPDATE_TAG_STATS_COMPLETION(hba, cmd); result = ufshcd_transfer_rsp_status(hba, lrbp); scsi_dma_unmap(cmd); cmd->result = result; Loading
drivers/scsi/ufs/ufshcd.h +14 −1 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ * * This code is based on drivers/scsi/ufs/ufshcd.h * Copyright (C) 2011-2013 Samsung India Software Operations * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. * * Authors: * Santosh Yaraganavi <santosh.sy@samsung.com> Loading Loading @@ -206,8 +207,9 @@ struct ufs_dev_cmd { #ifdef CONFIG_DEBUG_FS struct ufs_stats { u64 *tag_stats; bool enabled; u64 **tag_stats; int q_depth; }; struct debugfs_files { Loading @@ -220,6 +222,17 @@ struct debugfs_files { struct fault_attr fail_attr; #endif }; /* tag stats statistics types */ enum ts_types { TS_NOT_SUPPORTED = -1, TS_TAG = 0, TS_READ = 1, TS_WRITE = 2, TS_URGENT = 3, TS_FLUSH = 4, TS_NUM_STATS = 5, }; #endif /** Loading