mmc: core: Add MMC BKOPS statistics and debugfs ability to print them
The BKOPS statistics are used for BKOPS unit tests and APT tests to determine test success or failure. The BKOPS statstics provide the following information: The number of times BKOPS were issued according to its severity level The number of times manual BKOPS was started/stopped (HPI) The number of times auto BKOPS was enabled/disabled In order to enable and reset the statistics: echo 1 > /sys/kernel/debug/mmc0/mmc0:0001/bkops_stats In order to disable the statistics: echo 0 > /sys/kernel/debug/mmc0/mmc0:0001/bkops_stats In order to view the statistics: cat /sys/kernel/debug/mmc0/mmc0:0001/bkops_stats Change-Id: Ib84319aedfb49dc022bc27efbda842a5db38c7e9 Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org> Signed-off-by: Dov Levenglick <dovl@codeaurora.org> [subhashj@codeaurora.org: fixed trivial merge conflicts] Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
This commit is contained in:
parent
650d2e1086
commit
b98e6c2fa1
5 changed files with 209 additions and 2 deletions
|
@ -294,6 +294,7 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
|
|||
card->dev.type = type;
|
||||
|
||||
spin_lock_init(&card->wr_pack_stats.lock);
|
||||
spin_lock_init(&card->bkops.stats.lock);
|
||||
|
||||
return card;
|
||||
}
|
||||
|
|
|
@ -912,6 +912,77 @@ static void mmc_start_cmdq_request(struct mmc_host *host,
|
|||
__func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* mmc_blk_init_bkops_statistics - initialize bkops statistics
|
||||
* @card: MMC card to start BKOPS
|
||||
*
|
||||
* Initialize and enable the bkops statistics
|
||||
*/
|
||||
void mmc_blk_init_bkops_statistics(struct mmc_card *card)
|
||||
{
|
||||
int i;
|
||||
struct mmc_bkops_stats *stats;
|
||||
|
||||
if (!card)
|
||||
return;
|
||||
|
||||
stats = &card->bkops.stats;
|
||||
spin_lock(&stats->lock);
|
||||
|
||||
stats->manual_start = 0;
|
||||
stats->hpi = 0;
|
||||
stats->auto_start = 0;
|
||||
stats->auto_stop = 0;
|
||||
for (i = 0 ; i < MMC_BKOPS_NUM_SEVERITY_LEVELS ; i++)
|
||||
stats->level[i] = 0;
|
||||
stats->enabled = true;
|
||||
|
||||
spin_unlock(&stats->lock);
|
||||
}
|
||||
EXPORT_SYMBOL(mmc_blk_init_bkops_statistics);
|
||||
|
||||
static void mmc_update_bkops_hpi(struct mmc_bkops_stats *stats)
|
||||
{
|
||||
spin_lock_irq(&stats->lock);
|
||||
if (stats->enabled)
|
||||
stats->hpi++;
|
||||
spin_unlock_irq(&stats->lock);
|
||||
}
|
||||
|
||||
static void mmc_update_bkops_start(struct mmc_bkops_stats *stats)
|
||||
{
|
||||
spin_lock_irq(&stats->lock);
|
||||
if (stats->enabled)
|
||||
stats->manual_start++;
|
||||
spin_unlock_irq(&stats->lock);
|
||||
}
|
||||
|
||||
static void mmc_update_bkops_auto_on(struct mmc_bkops_stats *stats)
|
||||
{
|
||||
spin_lock_irq(&stats->lock);
|
||||
if (stats->enabled)
|
||||
stats->auto_start++;
|
||||
spin_unlock_irq(&stats->lock);
|
||||
}
|
||||
|
||||
static void mmc_update_bkops_auto_off(struct mmc_bkops_stats *stats)
|
||||
{
|
||||
spin_lock_irq(&stats->lock);
|
||||
if (stats->enabled)
|
||||
stats->auto_stop++;
|
||||
spin_unlock_irq(&stats->lock);
|
||||
}
|
||||
|
||||
static void mmc_update_bkops_level(struct mmc_bkops_stats *stats,
|
||||
unsigned level)
|
||||
{
|
||||
BUG_ON(level >= MMC_BKOPS_NUM_SEVERITY_LEVELS);
|
||||
spin_lock_irq(&stats->lock);
|
||||
if (stats->enabled)
|
||||
stats->level[level]++;
|
||||
spin_unlock_irq(&stats->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* mmc_set_auto_bkops - set auto BKOPS for supported cards
|
||||
* @card: MMC card to start BKOPS
|
||||
|
@ -950,10 +1021,13 @@ int mmc_set_auto_bkops(struct mmc_card *card, bool enable)
|
|||
pr_err("%s: %s: error in setting auto bkops to %d (%d)\n",
|
||||
mmc_hostname(card->host), __func__, enable, ret);
|
||||
} else {
|
||||
if (enable)
|
||||
if (enable) {
|
||||
mmc_card_set_auto_bkops(card);
|
||||
else
|
||||
mmc_update_bkops_auto_on(&card->bkops.stats);
|
||||
} else {
|
||||
mmc_card_clr_auto_bkops(card);
|
||||
mmc_update_bkops_auto_off(&card->bkops.stats);
|
||||
}
|
||||
card->ext_csd.man_bkops_en = bkops_en;
|
||||
}
|
||||
out:
|
||||
|
@ -986,6 +1060,8 @@ void mmc_check_bkops(struct mmc_card *card)
|
|||
return;
|
||||
}
|
||||
|
||||
mmc_update_bkops_level(&card->bkops.stats,
|
||||
card->ext_csd.raw_bkops_status);
|
||||
if (card->ext_csd.raw_bkops_status < EXT_CSD_BKOPS_LEVEL_2)
|
||||
return;
|
||||
|
||||
|
@ -1021,6 +1097,7 @@ void mmc_start_manual_bkops(struct mmc_card *card)
|
|||
mmc_hostname(card->host), err);
|
||||
} else {
|
||||
mmc_card_set_doing_bkops(card);
|
||||
mmc_update_bkops_start(&card->bkops.stats);
|
||||
card->bkops.needs_manual = false;
|
||||
}
|
||||
|
||||
|
@ -1573,6 +1650,7 @@ int mmc_stop_bkops(struct mmc_card *card)
|
|||
*/
|
||||
if (!err || (err == -EINVAL)) {
|
||||
mmc_card_clr_doing_bkops(card);
|
||||
mmc_update_bkops_hpi(&card->bkops.stats);
|
||||
mmc_retune_release(card->host);
|
||||
err = 0;
|
||||
}
|
||||
|
|
|
@ -637,6 +637,89 @@ static const struct file_operations mmc_dbg_wr_pack_stats_fops = {
|
|||
.write = mmc_wr_pack_stats_write,
|
||||
};
|
||||
|
||||
static int mmc_bkops_stats_read(struct seq_file *file, void *data)
|
||||
{
|
||||
struct mmc_card *card = file->private;
|
||||
struct mmc_bkops_stats *stats;
|
||||
int i;
|
||||
|
||||
if (!card)
|
||||
return -EINVAL;
|
||||
|
||||
stats = &card->bkops.stats;
|
||||
|
||||
if (!stats->enabled) {
|
||||
pr_info("%s: bkops statistics are disabled\n",
|
||||
mmc_hostname(card->host));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
spin_lock(&stats->lock);
|
||||
|
||||
seq_printf(file, "%s: bkops statistics:\n",
|
||||
mmc_hostname(card->host));
|
||||
seq_printf(file, "%s: BKOPS: sent START_BKOPS to device: %u\n",
|
||||
mmc_hostname(card->host), stats->manual_start);
|
||||
seq_printf(file, "%s: BKOPS: stopped due to HPI: %u\n",
|
||||
mmc_hostname(card->host), stats->hpi);
|
||||
seq_printf(file, "%s: BKOPS: sent AUTO_EN set to 1: %u\n",
|
||||
mmc_hostname(card->host), stats->auto_start);
|
||||
seq_printf(file, "%s: BKOPS: sent AUTO_EN set to 0: %u\n",
|
||||
mmc_hostname(card->host), stats->auto_stop);
|
||||
|
||||
for (i = 0 ; i < MMC_BKOPS_NUM_SEVERITY_LEVELS ; ++i)
|
||||
seq_printf(file, "%s: BKOPS: due to level %d: %u\n",
|
||||
mmc_hostname(card->host), i, stats->level[i]);
|
||||
|
||||
spin_unlock(&stats->lock);
|
||||
|
||||
exit:
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t mmc_bkops_stats_write(struct file *filp,
|
||||
const char __user *ubuf, size_t cnt,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct mmc_card *card = filp->f_mapping->host->i_private;
|
||||
int value;
|
||||
struct mmc_bkops_stats *stats;
|
||||
int err;
|
||||
|
||||
if (!card)
|
||||
return cnt;
|
||||
|
||||
stats = &card->bkops.stats;
|
||||
|
||||
err = kstrtoint_from_user(ubuf, cnt, 0, &value);
|
||||
if (err) {
|
||||
pr_err("%s: %s: error parsing input from user (%d)\n",
|
||||
mmc_hostname(card->host), __func__, err);
|
||||
return err;
|
||||
}
|
||||
if (value) {
|
||||
mmc_blk_init_bkops_statistics(card);
|
||||
} else {
|
||||
spin_lock(&stats->lock);
|
||||
stats->enabled = false;
|
||||
spin_unlock(&stats->lock);
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static int mmc_bkops_stats_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, mmc_bkops_stats_read, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations mmc_dbg_bkops_stats_fops = {
|
||||
.open = mmc_bkops_stats_open,
|
||||
.read = seq_read,
|
||||
.write = mmc_bkops_stats_write,
|
||||
};
|
||||
|
||||
void mmc_add_card_debugfs(struct mmc_card *card)
|
||||
{
|
||||
struct mmc_host *host = card->host;
|
||||
|
@ -675,6 +758,13 @@ void mmc_add_card_debugfs(struct mmc_card *card)
|
|||
&mmc_dbg_wr_pack_stats_fops))
|
||||
goto err;
|
||||
|
||||
if (mmc_card_mmc(card) && (card->ext_csd.rev >= 5) &&
|
||||
(mmc_card_support_auto_bkops(card) ||
|
||||
mmc_card_configured_manual_bkops(card)))
|
||||
if (!debugfs_create_file("bkops_stats", S_IRUSR, root, card,
|
||||
&mmc_dbg_bkops_stats_fops))
|
||||
goto err;
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
|
|
|
@ -275,12 +275,48 @@ struct mmc_part {
|
|||
#define MMC_BLK_DATA_AREA_RPMB (1<<3)
|
||||
};
|
||||
|
||||
enum {
|
||||
MMC_BKOPS_NO_OP,
|
||||
MMC_BKOPS_NOT_CRITICAL,
|
||||
MMC_BKOPS_PERF_IMPACT,
|
||||
MMC_BKOPS_CRITICAL,
|
||||
MMC_BKOPS_NUM_SEVERITY_LEVELS,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mmc_bkops_stats - BKOPS statistics
|
||||
* @lock: spinlock used for synchronizing the debugfs and the runtime accesses
|
||||
* to this structure. No need to call with spin_lock_irq api
|
||||
* @manual_start: number of times START_BKOPS was sent to the device
|
||||
* @hpi: number of times HPI was sent to the device
|
||||
* @auto_start: number of times AUTO_EN was set to 1
|
||||
* @auto_stop: number of times AUTO_EN was set to 0
|
||||
* @level: number of times the device reported the need for each level of
|
||||
* bkops handling
|
||||
* @enabled: control over whether statistics should be gathered
|
||||
*
|
||||
* This structure is used to collect statistics regarding the bkops
|
||||
* configuration and use-patterns. It is collected during runtime and can be
|
||||
* shown to the user via a debugfs entry.
|
||||
*/
|
||||
struct mmc_bkops_stats {
|
||||
spinlock_t lock;
|
||||
unsigned int manual_start;
|
||||
unsigned int hpi;
|
||||
unsigned int auto_start;
|
||||
unsigned int auto_stop;
|
||||
unsigned int level[MMC_BKOPS_NUM_SEVERITY_LEVELS];
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mmc_bkops_info - BKOPS data
|
||||
* @stats: statistic information regarding bkops
|
||||
* @need_manual: indication whether have to send START_BKOPS
|
||||
* to the device
|
||||
*/
|
||||
struct mmc_bkops_info {
|
||||
struct mmc_bkops_stats stats;
|
||||
bool needs_manual;
|
||||
};
|
||||
|
||||
|
|
|
@ -208,6 +208,8 @@ extern int mmc_cache_barrier(struct mmc_card *);
|
|||
|
||||
extern int mmc_detect_card_removed(struct mmc_host *host);
|
||||
|
||||
extern void mmc_blk_init_bkops_statistics(struct mmc_card *card);
|
||||
|
||||
/**
|
||||
* mmc_claim_host - exclusively claim a host
|
||||
* @host: mmc host to claim
|
||||
|
|
Loading…
Add table
Reference in a new issue