linux-tegra.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dmitry Osipenko <digetx@gmail.com>
To: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>,
	Thierry Reding <thierry.reding@gmail.com>,
	Jonathan Hunter <jonathanh@nvidia.com>
Cc: linux-kernel@vger.kernel.org, linux-tegra@vger.kernel.org
Subject: Re: [PATCH v1] memory: tegra20: Add debug statistics
Date: Thu, 18 Mar 2021 19:18:58 +0300	[thread overview]
Message-ID: <26ef74e0-67ff-77c4-1682-8f8261b71463@gmail.com> (raw)
In-Reply-To: <acdbd1e3-8f38-1ee6-0980-3699df9e4375@canonical.com>

18.03.2021 18:23, Krzysztof Kozlowski пишет:
...
>> +	mc->debugfs.root = debugfs_create_dir("mc", NULL);
>> +	if (!mc->debugfs.root)
>> +		dev_err(&pdev->dev, "failed to create debugfs directory\n");
> 
> It's error pointer, not null, but anyway there is no need for handling
> debugfs error. See Greg KH's commits like "remove pointless check for
> debugfs_create_dir()".

Indeed!

>> +
>> +	if (mc->soc->init) {
>> +		err = mc->soc->init(mc);
>> +		if (err < 0)
>> +			dev_err(&pdev->dev,
>> +				"failed to register initialize SoC driver: %d\n",
> 
> "failed to initialize SoC driver:...."

Good catch!

>> +				err);
>> +	}
>> +
>>  	err = tegra_mc_reset_setup(mc);
>>  	if (err < 0)
>>  		dev_err(&pdev->dev, "failed to register reset controller: %d\n",
>> diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c
>> index 29ecf02805a0..513c07104296 100644
>> --- a/drivers/memory/tegra/tegra20.c
>> +++ b/drivers/memory/tegra/tegra20.c
>> @@ -3,6 +3,8 @@
>>   * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
>>   */
>>  
>> +#include <linux/bitfield.h>
>> +#include <linux/delay.h>
>>  #include <linux/of_device.h>
>>  #include <linux/slab.h>
>>  #include <linux/string.h>
>> @@ -11,6 +13,77 @@
>>  
>>  #include "mc.h"
>>  
>> +#define MC_STAT_CONTROL				0x90
>> +#define MC_STAT_EMC_CLOCK_LIMIT			0xa0
>> +#define MC_STAT_EMC_CLOCKS			0xa4
>> +#define MC_STAT_EMC_CONTROL_0			0xa8
>> +#define MC_STAT_EMC_CONTROL_1			0xac
>> +#define MC_STAT_EMC_COUNT_0			0xb8
>> +#define MC_STAT_EMC_COUNT_1			0xbc
>> +
>> +#define MC_STAT_CONTROL_CLIENT_ID		GENMASK(13,  8)
>> +#define MC_STAT_CONTROL_EVENT			GENMASK(23, 16)
>> +#define MC_STAT_CONTROL_PRI_EVENT		GENMASK(25, 24)
>> +#define MC_STAT_CONTROL_FILTER_CLIENT_ENABLE	GENMASK(26, 26)
>> +#define MC_STAT_CONTROL_FILTER_PRI		GENMASK(29, 28)
>> +
>> +#define MC_STAT_CONTROL_PRI_EVENT_HP		0
>> +#define MC_STAT_CONTROL_PRI_EVENT_TM		1
>> +#define MC_STAT_CONTROL_PRI_EVENT_BW		2
>> +
>> +#define MC_STAT_CONTROL_FILTER_PRI_DISABLE	0
>> +#define MC_STAT_CONTROL_FILTER_PRI_NO		1
>> +#define MC_STAT_CONTROL_FILTER_PRI_YES		2
>> +
>> +#define MC_STAT_CONTROL_EVENT_QUALIFIED		0
>> +#define MC_STAT_CONTROL_EVENT_ANY_READ		1
>> +#define MC_STAT_CONTROL_EVENT_ANY_WRITE		2
>> +#define MC_STAT_CONTROL_EVENT_RD_WR_CHANGE	3
>> +#define MC_STAT_CONTROL_EVENT_SUCCESSIVE	4
>> +#define MC_STAT_CONTROL_EVENT_ARB_BANK_AA	5
>> +#define MC_STAT_CONTROL_EVENT_ARB_BANK_BB	6
>> +#define MC_STAT_CONTROL_EVENT_PAGE_MISS		7
>> +#define MC_STAT_CONTROL_EVENT_AUTO_PRECHARGE	8
>> +
>> +#define EMC_GATHER_RST				(0 << 8)
>> +#define EMC_GATHER_CLEAR			(1 << 8)
>> +#define EMC_GATHER_DISABLE			(2 << 8)
>> +#define EMC_GATHER_ENABLE			(3 << 8)
>> +
>> +#define MC_STAT_SAMPLE_TIME_USEC		16000
>> +
>> +/* we store collected statistics as a fixed point values */
>> +#define MC_FX_FRAC_SCALE			100
>> +
>> +struct tegra20_mc_stat_gather {
>> +	unsigned int pri_filter;
>> +	unsigned int pri_event;
>> +	unsigned int result;
>> +	unsigned int client;
>> +	unsigned int event;
>> +	bool client_enb;
>> +};
>> +
>> +struct tegra20_mc_stat {
>> +	struct tegra20_mc_stat_gather gather0;
>> +	struct tegra20_mc_stat_gather gather1;
>> +	unsigned int sample_time_usec;
>> +	struct tegra_mc *mc;
>> +};
>> +
>> +struct tegra20_mc_client_stat {
>> +	unsigned int events;
>> +	unsigned int arb_high_prio;
>> +	unsigned int arb_timeout;
>> +	unsigned int arb_bandwidth;
>> +	unsigned int rd_wr_change;
>> +	unsigned int successive;
>> +	unsigned int page_miss;
>> +	unsigned int auto_precharge;
>> +	unsigned int arb_bank_aa;
>> +	unsigned int arb_bank_bb;
>> +};
>> +
>>  static const struct tegra_mc_client tegra20_mc_clients[] = {
>>  	{
>>  		.id = 0x00,
>> @@ -356,6 +429,274 @@ static const struct tegra_mc_icc_ops tegra20_mc_icc_ops = {
>>  	.set = tegra20_mc_icc_set,
>>  };
>>  
>> +static u32 tegra20_mc_stat_gather_control(struct tegra20_mc_stat_gather *g)
> 
> "g" looks like pointer to const here

I'll add couple more consts to the code for consistency.

>> +{
>> +	u32 control;
>> +
>> +	control  = FIELD_PREP(MC_STAT_CONTROL_EVENT, g->event);
>> +	control |= FIELD_PREP(MC_STAT_CONTROL_CLIENT_ID, g->client);
>> +	control |= FIELD_PREP(MC_STAT_CONTROL_PRI_EVENT, g->pri_event);
>> +	control |= FIELD_PREP(MC_STAT_CONTROL_FILTER_PRI, g->pri_filter);
>> +	control |= FIELD_PREP(MC_STAT_CONTROL_FILTER_CLIENT_ENABLE, g->client_enb);
>> +
>> +	return control;
>> +}
...
>> +static void tegra20_mc_collect_stats(struct tegra_mc *mc,
>> +				     struct tegra20_mc_client_stat *stats)
>> +{
>> +	const struct tegra_mc_client *client0, *client1;
>> +	unsigned int i, clienta, clientb;
> 
> Define the clienta and clientb inside the loop, to reduce the scope.
> Unless it is used between the loop iterations?

okay

>> +
>> +	/* collect memory controller utilization percent for each client */
>> +	for (i = 0; i < mc->soc->num_clients; i += 2) {
>> +		client0 = &mc->soc->clients[i];
>> +		client1 = &mc->soc->clients[i + 1];
>> +
>> +		if (i + 1 == mc->soc->num_clients)
>> +			client1 = NULL;
>> +
>> +		tegra20_mc_stat_events(mc, client0, client1,
>> +				       MC_STAT_CONTROL_FILTER_PRI_DISABLE,
>> +				       MC_STAT_CONTROL_PRI_EVENT_HP,
>> +				       MC_STAT_CONTROL_EVENT_QUALIFIED,
>> +				       &stats[i + 0].events,
>> +				       &stats[i + 1].events);
>> +	}
>> +
>> +	/* collect more info from active clients */
>> +	for (i = 0; i < mc->soc->num_clients; i++) {
>> +		clientb = mc->soc->num_clients;
>> +
>> +		for (client0 = NULL; i < mc->soc->num_clients; i++) {
>> +			if (stats[i].events) {
>> +				client0 = &mc->soc->clients[i];
>> +				clienta = i++;
>> +				break;
>> +			}
>> +		}
> 
> Could all clients have 0 events ending with "clienta" being undefined?
> "client0" would be non-NULL because of loop before.

As per 6.8.5.3 of C99 standard, the declaration of a for-loop "is
reached in the order of execution before the first evaluation of the
controlling expression".

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

>> +
>> +		for (client1 = NULL; i < mc->soc->num_clients; i++) {
>> +			if (stats[i].events) {
>> +				client1 = &mc->soc->clients[i];
>> +				clientb = i;
>> +				break;
>> +			}
>> +		}
>> +
>> +		if (!client0 && !client1)
>> +			break;

this means that both client0 and client1 are set t0 NULL here if all
clients have 0 events.

  reply	other threads:[~2021-03-18 16:19 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-18 11:55 [PATCH v1] memory: tegra20: Add debug statistics Dmitry Osipenko
2021-03-18 15:23 ` Krzysztof Kozlowski
2021-03-18 16:18   ` Dmitry Osipenko [this message]
2021-03-18 16:20     ` Krzysztof Kozlowski
2021-03-18 16:38       ` Dmitry Osipenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=26ef74e0-67ff-77c4-1682-8f8261b71463@gmail.com \
    --to=digetx@gmail.com \
    --cc=jonathanh@nvidia.com \
    --cc=krzysztof.kozlowski@canonical.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tegra@vger.kernel.org \
    --cc=thierry.reding@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).