X86 platform drivers
 help / color / mirror / Atom feed
From: "Limonciello, Mario" <mario.limonciello@amd.com>
To: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>,
	Sanket Goswami <Sanket.Goswami@amd.com>,
	hdegoede@redhat.com, markgross@kernel.org
Cc: platform-driver-x86@vger.kernel.org
Subject: Re: [PATCH] platform/x86: amd-pmc: Add support for AMD Spill to DRAM STB feature
Date: Wed, 2 Feb 2022 08:24:21 -0600	[thread overview]
Message-ID: <7b3da1a7-cdd0-9ed4-8e0b-91c191ad9166@amd.com> (raw)
In-Reply-To: <b01dd497-2b1d-4d0e-5de6-67081986f066@amd.com>

On 2/2/2022 00:03, Shyam Sundar S K wrote:
> 
> 
> On 2/2/2022 10:14 AM, Limonciello, Mario wrote:
>> On 1/27/2022 04:09, Sanket Goswami wrote:
>>> Spill to DRAM functionality is a feature that allows STB (Smart Trace
>>> Buffer) to spill data from SRAM into DRAM on some future AMD ASICs. The
>>> size allocated for STB is more than the earlier SoC's which helps to
>>> collect more tracing and telemetry data.
>>>
>>> Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
>>> Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
>>> ---
>>>    drivers/platform/x86/amd-pmc.c | 132 +++++++++++++++++++++++++++++----
>>>    1 file changed, 118 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/drivers/platform/x86/amd-pmc.c
>>> b/drivers/platform/x86/amd-pmc.c
>>> index 4c72ba68b315..3040f50627c6 100644
>>> --- a/drivers/platform/x86/amd-pmc.c
>>> +++ b/drivers/platform/x86/amd-pmc.c
>>> @@ -41,6 +41,16 @@
>>>    #define AMD_PMC_STB_PMI_0        0x03E30600
>>>    #define AMD_PMC_STB_PREDEF        0xC6000001
>>>    +/* STB S2D(Spill to DRAM) has different message port offset */
>>> +#define STB_SPILL_TO_DRAM        0xBE
>>> +#define AMD_S2D_REGISTER_MESSAGE    0xA20
>>> +#define AMD_S2D_REGISTER_RESPONSE    0xA80
>>> +#define AMD_S2D_REGISTER_ARGUMENT    0xA88
>>> +
>>> +/* STB Spill to DRAM Parameters */
>>> +#define S2D_TELEMETRY_BYTES_MAX        0x100000
>>> +#define S2D_TELEMETRY_DRAMBYTES_MAX    0x1000000
>>
>> Why have two separate definitions for the same value?  Is there a case
>> that these will ever be different?
> 
> Values are different right? _BYTES_MAX is 1M and _DRAM_MAX is 16M

Sorry, my mistake when I looked - yes.

> 
>>
>>> +
>>>    /* Base address of SMU for mapping physical address to virtual
>>> address */
>>>    #define AMD_PMC_SMU_INDEX_ADDRESS    0xB8
>>>    #define AMD_PMC_SMU_INDEX_DATA        0xBC
>>> @@ -95,6 +105,13 @@ enum amd_pmc_def {
>>>        MSG_OS_HINT_RN,
>>>    };
>>>    +enum s2d_arg {
>>> +    S2D_TELEMETRY_SIZE = 0x01,
>>> +    S2D_PHYS_ADDR_LOW,
>>> +    S2D_PHYS_ADDR_HIGH,
>>> +    S2D_NUM_SAMPLES,
>>> +};
>>> +
>>>    struct amd_pmc_bit_map {
>>>        const char *name;
>>>        u32 bit_mask;
>>> @@ -119,7 +136,9 @@ static const struct amd_pmc_bit_map soc15_ip_blk[]
>>> = {
>>>    struct amd_pmc_dev {
>>>        void __iomem *regbase;
>>>        void __iomem *smu_virt_addr;
>>> +    void __iomem *stb_virt_addr;
>>>        void __iomem *fch_virt_addr;
>>> +    bool msg_port;
>>>        u32 base_addr;
>>>        u32 cpu_id;
>>>        u32 active_ips;
>>> @@ -236,6 +255,65 @@ static const struct file_operations
>>> amd_pmc_stb_debugfs_fops = {
>>>        .release = amd_pmc_stb_debugfs_release,
>>>    };
>>>    +static int amd_pmc_stb_debugfs_open_v2(struct inode *inode, struct
>>> file *filp)
>>> +{
>>> +    struct amd_pmc_dev *dev = filp->f_inode->i_private;
>>> +    u32 *buf, phys_addr_low, phys_addr_hi, size, samples;
>>> +    u64 stb_phys_addr;
>>> +
>>> +    /* Spill to DRAM feature uses separate SMU message port */
>>> +    dev->msg_port = 1;
>>
>> This message port is only used for STD right?  Existing messages for
>> version, OS_HINT and the like should go through the old port.
> 
> msg_port is a flag to decide whether to use the regular PMC port or the
> new STB port defined for Spill-to-DRAM feature.
> 
> Both are complementary. Spill-to-DRAM will only be enabled in Yellow
> Carp and future ASICs and lower than that the new message port will not
> be enabled.
> 
> The decision of whether to use v2 or v1 versions of debugfs is being
> taken in the debugfs creation with a cpuid check and hence I believe the
> versions/OS_HINT will not collide.
> 
> Also, this change has to tested several iterations on older and newer
> platforms before it was posted here. So, based that this we should
> ignore any such concerns around the OS_HINT.
>  >>
>> You don't seem to ever unset this, so I think if the STB was opened
>> before S0i3 was invoked I would think it would cause the OS_HINT message
>> to be sent to the wrong port wouldn't it?
> 
> I tried to cover this in the above details. No, it would not cause HINT
> to be sent to wrong message port.

I don't think you followed my thought process here.

If `amd_pmc_stb_debugfs_open_v2` is called then dev->msg_port is set to 1.

So that means that any future call to `amd_pmc_send_cmd` (such as is 
done for OS_HINT) will use the STD registers.  So doesn't that mean 
OS_HINT is sent to STD registers?

If STD registers support all the existing commands as the PMC registers 
this is fine, otherwise I think there needs to be more logic to check 
whether the command is PMC or STD related.

> 
>>
>> It might be safer to modify amd_pmc_send_cmd to have an extra argument
>> of which port to use in each invocation.  Then only in debugfs_v2
>> operations you can use this port.
>>
>>> +
>>> +    amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size,
>>> STB_SPILL_TO_DRAM, 1);
>>> +    if (size != S2D_TELEMETRY_BYTES_MAX)
>>> +        return -EIO;
>>
>> What if the firmware was configured to use less than 16MB?  Shouldn't
>> you be able to respect that?
> 
> That is why there is a seperate call to fetch the S2D(Spill-to-DRAM)
> size which the FW has configured it for notifying it to the driver.

But you only allow size to be S2D_TELEMETRY_BYTES_MAX, shouldn't you be 
flexible to a range of what the firmware returns rather than the single 
value?

> 
> Btw, though 16M is the max DRAM carved out space for 16M, but currently
> only 1M is allocated to get the full STB dumps from DRAM space and this
> by design. We have the same change on the windows side too.
> 
>>
>> I would think you instead want to have a boundary check on the "max" to
>> support.
> 
> Above explanation should hopefully address this.
> 
>>
>>> +
>>> +    /* Get STB DRAM address */
>>> +    amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low,
>>> STB_SPILL_TO_DRAM, 1);
>>> +    amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi,
>>> STB_SPILL_TO_DRAM, 1);
>>> +
>>> +    /* Get the number of samples present in the STB buffer */
>>> +    amd_pmc_send_cmd(dev, S2D_NUM_SAMPLES, &samples,
>>> STB_SPILL_TO_DRAM, 1);
>>> +    stb_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low);
>>> +
>>> +    dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr,
>>> S2D_TELEMETRY_DRAMBYTES_MAX);
>>> +    if (!dev->stb_virt_addr)
>>> +        return -ENOMEM;
>>> +
>>> +    buf = kzalloc(S2D_TELEMETRY_BYTES_MAX, GFP_KERNEL);
>>> +    if (!buf)
>>> +        return -ENOMEM;
>>
>> Shouldn't you clear the iomapping for dev->stb_virt_addr on this failure?
> 
> I believe, that is why we use managed devm_*() APIs which is supposed to
>   take care of reducing the reference counts ?

I think those only take account when unloading the driver or unbinding 
the device though, don't they?  So if devm_ioremap worked but kzalloc 
failed then you call `amd_pmc_stb_debugfs_open_v2` again without unbind 
or unload driver devm_ioremap will be called again too.

> 
> Thanks,
> Shyam
> 
>>
>>> +
>>> +    memcpy_fromio(buf, dev->stb_virt_addr, S2D_TELEMETRY_BYTES_MAX);
>>> +
>>> +    filp->private_data = buf;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static ssize_t amd_pmc_stb_debugfs_read_v2(struct file *filp, char
>>> __user *buf, size_t size,
>>> +                       loff_t *pos)
>>> +{
>>> +    if (!filp->private_data)
>>> +        return -EINVAL;
>>> +
>>> +    return simple_read_from_buffer(buf, size, pos, filp->private_data,
>>> +                    S2D_TELEMETRY_BYTES_MAX);
>>> +}
>>> +
>>> +static int amd_pmc_stb_debugfs_release_v2(struct inode *inode, struct
>>> file *filp)
>>> +{
>>> +    kfree(filp->private_data);
>>> +    return 0;
>>> +}
>>> +
>>> +static const struct file_operations amd_pmc_stb_debugfs_fops_v2 = {
>>> +    .owner = THIS_MODULE,
>>> +    .open = amd_pmc_stb_debugfs_open_v2,
>>> +    .read = amd_pmc_stb_debugfs_read_v2,
>>> +    .release = amd_pmc_stb_debugfs_release_v2,
>>> +};
>>> +
>>>    static int amd_pmc_idlemask_read(struct amd_pmc_dev *pdev, struct
>>> device *dev,
>>>                     struct seq_file *s)
>>>    {
>>> @@ -350,9 +428,14 @@ static void amd_pmc_dbgfs_register(struct
>>> amd_pmc_dev *dev)
>>>        debugfs_create_file("amd_pmc_idlemask", 0644, dev->dbgfs_dir, dev,
>>>                    &amd_pmc_idlemask_fops);
>>>        /* Enable STB only when the module_param is set */
>>> -    if (enable_stb)
>>> -        debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev,
>>> -                    &amd_pmc_stb_debugfs_fops);
>>> +    if (enable_stb) {
>>> +        if (dev->cpu_id == AMD_CPU_ID_YC)
>>> +            debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev,
>>> +                        &amd_pmc_stb_debugfs_fops_v2);
>>> +        else
>>> +            debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev,
>>> +                        &amd_pmc_stb_debugfs_fops);
>>> +    }
>>>    }
>>>    #else
>>>    static inline void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
>>> @@ -392,26 +475,47 @@ static int amd_pmc_setup_smu_logging(struct
>>> amd_pmc_dev *dev)
>>>      static void amd_pmc_dump_registers(struct amd_pmc_dev *dev)
>>>    {
>>> -    u32 value;
>>> +    u32 value, message, argument, response;
>>> +
>>> +    if (dev->msg_port) {
>>> +        message = AMD_S2D_REGISTER_MESSAGE;
>>> +        argument = AMD_S2D_REGISTER_ARGUMENT;
>>> +        response = AMD_S2D_REGISTER_RESPONSE;
>>> +    } else {
>>> +        message = AMD_PMC_REGISTER_MESSAGE;
>>> +        argument = AMD_PMC_REGISTER_ARGUMENT;
>>> +        response = AMD_PMC_REGISTER_RESPONSE;
>>> +    }
>>>    -    value = amd_pmc_reg_read(dev, AMD_PMC_REGISTER_RESPONSE);
>>> +    value = amd_pmc_reg_read(dev, response);
>>>        dev_dbg(dev->dev, "AMD_PMC_REGISTER_RESPONSE:%x\n", value);
>>>    -    value = amd_pmc_reg_read(dev, AMD_PMC_REGISTER_ARGUMENT);
>>> +    value = amd_pmc_reg_read(dev, argument);
>>>        dev_dbg(dev->dev, "AMD_PMC_REGISTER_ARGUMENT:%x\n", value);
>>>    -    value = amd_pmc_reg_read(dev, AMD_PMC_REGISTER_MESSAGE);
>>> +    value = amd_pmc_reg_read(dev, message);
>>>        dev_dbg(dev->dev, "AMD_PMC_REGISTER_MESSAGE:%x\n", value);
>>>    }
>>>      static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32
>>> *data, u8 msg, bool ret)
>>>    {
>>>        int rc;
>>> -    u32 val;
>>> +    u32 val, message, argument, response;
>>>          mutex_lock(&dev->lock);
>>> +
>>> +    if (dev->msg_port) {
>>> +        message = AMD_S2D_REGISTER_MESSAGE;
>>> +        argument = AMD_S2D_REGISTER_ARGUMENT;
>>> +        response = AMD_S2D_REGISTER_RESPONSE;
>>> +    } else {
>>> +        message = AMD_PMC_REGISTER_MESSAGE;
>>> +        argument = AMD_PMC_REGISTER_ARGUMENT;
>>> +        response = AMD_PMC_REGISTER_RESPONSE;
>>> +    }
>>> +
>>>        /* Wait until we get a valid response */
>>> -    rc = readx_poll_timeout(ioread32, dev->regbase +
>>> AMD_PMC_REGISTER_RESPONSE,
>>> +    rc = readx_poll_timeout(ioread32, dev->regbase + response,
>>>                    val, val != 0, PMC_MSG_DELAY_MIN_US,
>>>                    PMC_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX);
>>>        if (rc) {
>>> @@ -420,16 +524,16 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev
>>> *dev, u32 arg, u32 *data, u8 msg,
>>>        }
>>>          /* Write zero to response register */
>>> -    amd_pmc_reg_write(dev, AMD_PMC_REGISTER_RESPONSE, 0);
>>> +    amd_pmc_reg_write(dev, response, 0);
>>>          /* Write argument into response register */
>>> -    amd_pmc_reg_write(dev, AMD_PMC_REGISTER_ARGUMENT, arg);
>>> +    amd_pmc_reg_write(dev, argument, arg);
>>>          /* Write message ID to message ID register */
>>> -    amd_pmc_reg_write(dev, AMD_PMC_REGISTER_MESSAGE, msg);
>>> +    amd_pmc_reg_write(dev, message, msg);
>>>          /* Wait until we get a valid response */
>>> -    rc = readx_poll_timeout(ioread32, dev->regbase +
>>> AMD_PMC_REGISTER_RESPONSE,
>>> +    rc = readx_poll_timeout(ioread32, dev->regbase + response,
>>>                    val, val != 0, PMC_MSG_DELAY_MIN_US,
>>>                    PMC_MSG_DELAY_MIN_US * RESPONSE_REGISTER_LOOP_MAX);
>>>        if (rc) {
>>> @@ -442,7 +546,7 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev
>>> *dev, u32 arg, u32 *data, u8 msg,
>>>            if (ret) {
>>>                /* PMFW may take longer time to return back the data */
>>>                usleep_range(DELAY_MIN_US, 10 * DELAY_MAX_US);
>>> -            *data = amd_pmc_reg_read(dev, AMD_PMC_REGISTER_ARGUMENT);
>>> +            *data = amd_pmc_reg_read(dev, argument);
>>>            }
>>>            break;
>>>        case AMD_PMC_RESULT_CMD_REJECT_BUSY:
>>


  reply	other threads:[~2022-02-02 14:24 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-27 10:09 [PATCH] platform/x86: amd-pmc: Add support for AMD Spill to DRAM STB feature Sanket Goswami
2022-02-02  4:44 ` Limonciello, Mario
2022-02-02  6:03   ` Shyam Sundar S K
2022-02-02 14:24     ` Limonciello, Mario [this message]
2022-02-02 19:07       ` Shyam Sundar S K
2022-02-02 19:23         ` Limonciello, Mario

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=7b3da1a7-cdd0-9ed4-8e0b-91c191ad9166@amd.com \
    --to=mario.limonciello@amd.com \
    --cc=Sanket.Goswami@amd.com \
    --cc=Shyam-sundar.S-k@amd.com \
    --cc=hdegoede@redhat.com \
    --cc=markgross@kernel.org \
    --cc=platform-driver-x86@vger.kernel.org \
    /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