Re: [PATCH v2] platform/x86: amd-pmc: Add support for AMD Spill to DRAM STB feature

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

On 2/4/22 13:25, 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@xxxxxxx>
> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@xxxxxxx>
> Signed-off-by: Sanket Goswami <Sanket.Goswami@xxxxxxx>
> ---
> Changes in v2:
> - Create separate routine amd_pmc_s2d_init() and move the S2D initialization logic there.
> - Handle the msg_port flag accordingly so that OS_HINT goes to PMC message port.

Thank you for your patch, I've applied this patch to my review-hans 
branch:
https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans

Note it will show up in my review-hans branch once I've pushed my
local branch there, which might take a while.

Once I've run some tests on this branch the patches there will be
added to the platform-drivers-x86/for-next branch and eventually
will be included in the pdx86 pull-request to Linus for the next
merge-window.

Regards,

Hans



> 
>  drivers/platform/x86/amd-pmc.c | 144 +++++++++++++++++++++++++++++----
>  1 file changed, 130 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c
> index 4c72ba68b315..69fdbb0d9f45 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
> +
>  /* 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,12 @@ enum amd_pmc_def {
>  	MSG_OS_HINT_RN,
>  };
>  
> +enum s2d_arg {
> +	S2D_TELEMETRY_SIZE = 0x01,
> +	S2D_PHYS_ADDR_LOW,
> +	S2D_PHYS_ADDR_HIGH,
> +};
> +
>  struct amd_pmc_bit_map {
>  	const char *name;
>  	u32 bit_mask;
> @@ -119,7 +135,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 +254,44 @@ 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;
> +
> +	buf = kzalloc(S2D_TELEMETRY_BYTES_MAX, GFP_KERNEL);
> +	if (!buf)
> +		return -ENOMEM;
> +
> +	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 +406,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 +453,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 +502,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 +524,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:
> @@ -601,6 +683,34 @@ static const struct pci_device_id pmc_pci_ids[] = {
>  	{ }
>  };
>  
> +static int amd_pmc_s2d_init(struct amd_pmc_dev *dev)
> +{
> +	u32 size, phys_addr_low, phys_addr_hi;
> +	u64 stb_phys_addr;
> +
> +	/* Spill to DRAM feature uses separate SMU message port */
> +	dev->msg_port = 1;
> +
> +	amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, STB_SPILL_TO_DRAM, 1);
> +	if (size != S2D_TELEMETRY_BYTES_MAX)
> +		return -EIO;
> +
> +	/* 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);
> +
> +	stb_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low);
> +
> +	/* Clear msg_port for other SMU operation */
> +	dev->msg_port = 0;
> +
> +	dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, S2D_TELEMETRY_DRAMBYTES_MAX);
> +	if (!dev->stb_virt_addr)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +
>  static int amd_pmc_write_stb(struct amd_pmc_dev *dev, u32 data)
>  {
>  	int err;
> @@ -719,6 +829,12 @@ static int amd_pmc_probe(struct platform_device *pdev)
>  	if (err)
>  		dev_err(dev->dev, "SMU debugging info not supported on this platform\n");
>  
> +	if (enable_stb && dev->cpu_id == AMD_CPU_ID_YC) {
> +		err = amd_pmc_s2d_init(dev);
> +		if (err)
> +			return err;
> +	}
> +
>  	amd_pmc_get_smu_version(dev);
>  	platform_set_drvdata(pdev, dev);
>  	amd_pmc_dbgfs_register(dev);
> 




[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux