Re: [PATCH v2] platform/x86: amd-pmc: Add AMD platform support for S2Idle

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

 



On Thu, Oct 29, 2020 at 10:57 AM Shyam Sundar S K
<Shyam-sundar.S-k@xxxxxxx> wrote:
>
> AMD Power Management Controller driver aka. amd-pmc driver is the

aka. -> a.k.a. or AKA

> controller which is meant for final S2Idle transaction that goes to the

for the final

> PMFW running on the AMD SMU (System Management Unit) responsible for
> tuning of the VDD.
>
> Once all the monitored list or the idle constraints are met, this driver
> would go and set the OS_HINT (meaning all the devices have reached to
> their lowest state possible) via the SMU mailboxes.
>
> This driver would also provide some debug capabilities via debugfs.

...

> +F:     drivers/platform/x86/amd-pmc.c
> +F:     drivers/platform/x86/amd-pmc.h

Can be one entry.

...

> +       help
> +         The driver provides support for AMD Power Management Controller
> +         primarily responsible for S2Idle transactions that are driven from
> +         a platform firmware running on SMU. This driver also provides debug

a debug

> +         mechanism to investigate the S2Idle transactions and failures.

How will the module be called?

...

> +static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
> +{
> +       struct dentry *dir;

What is the point of having the temporary variable?

> +       dir = debugfs_create_dir("amd_pmc", NULL);
> +       dev->dbgfs_dir = dir;
> +       debugfs_create_file("smu_fw_info", 0644, dir, dev, &smu_fw_info_fops);
> +}

...

> +static int amd_pmc_poll_smu_response(struct amd_pmc_dev *dev)
> +{
> +       int rc = 0, index;

Redundant assignment.

> +       for (index = 0; index < RESPONSE_REGISTER_LOOP_MAX; index++) {
> +               rc = amd_pmc_reg_read(dev, AMD_PMC_REGISTER_RESPONSE);

> +               if (rc != 0)
> +                       break;

if (rc)
  return rc;

> +
> +               usleep_range(PMC_MSG_DELAY_MIN, PMC_MSG_DELAY_MAX);
> +       }
> +
> +       return rc;
> +}

Seems like home grown readx_poll_timeout().

...

> +       int rc = 0;

Redundant assignment.

...

> +       /* Wait until the response register is non-zero */

This comment is confusing.

I guess you rather need to return an error code from the called function...

> +       rc = amd_pmc_poll_smu_response(dev);
> +       if (!rc) {
> +               dev_err(dev->dev, "failed to talk to SMU\n");

> +               return -EIO;

...and propagate it here.

> +       }

...

> +       if (arg) {
> +               /* Wait until the response register is non-zero */
> +               rc = amd_pmc_poll_smu_response(dev);

> +               if (!rc) {

As above. This is an unusual pattern in the kernel.

> +                       dev_err(dev->dev, "failed to talk to SMU\n");
> +                       return -EIO;
> +               }

> +               /* If message register is OK, then SMU has finished processing
> +                * the message, and then read back from AMD_PMC_REGISTER_ARGUMENT
> +                */

Comment style!

> +               rc = amd_pmc_reg_read(dev, AMD_PMC_REGISTER_ARGUMENT);

And where is rc going?

> +       }
> +
> +       return 0;

...

> +#ifdef CONFIG_PM_SLEEP

__maybe_unused is slightly better.

...

> +static int amd_pmc_suspend(struct device *dev)
> +{
> +       struct amd_pmc_dev *pdev = dev_get_drvdata(dev);

> +       int rc = 0;

What is the point?

> +       rc = amd_pmc_send_cmd(pdev, 1, 0);
> +       if (rc)
> +               dev_err(pdev->dev, "suspend failed\n");
> +
> +       amd_pmc_dump_registers(pdev);
> +
> +       return 0;
> +}
> +
> +static int amd_pmc_resume(struct device *dev)
> +{
> +       struct amd_pmc_dev *pdev = dev_get_drvdata(dev);

> +       int rc = 0;

Ditto.

> +       rc = amd_pmc_send_cmd(pdev, 0, 0);
> +       if (rc)
> +               dev_err(pdev->dev, "resume failed\n");
> +
> +       amd_pmc_dump_registers(pdev);
> +
> +       return 0;
> +}
> +#endif

...

> +       rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
> +       if (!rdev || (!(rdev->vendor == PCI_VENDOR_ID_AMD) &&
> +                     (rdev->device == AMD_CPU_ID_PCO ||
> +                       rdev->device == AMD_CPU_ID_RN))) {
> +               return -ENODEV;
> +       }

Can you rather create an additional PCI ID table and simple use pci_match_id()?

> +       err = pci_write_config_dword(rdev, AMD_PMC_SMU_INDEX_ADDRESS, AMD_PMC_BASE_ADDR_LO);
> +       if (err) {
> +               dev_err(dev->dev, "error writing to 0x%x\n", AMD_PMC_SMU_INDEX_ADDRESS);
> +               return err;
> +       }

Returning positive error codes?!

...

> +       dev->smu_base = ioremap(base_addr, AMD_PMC_MAPPING_SIZE);

devm_ioremap()?

> +       if (!dev->smu_base)
> +               return -ENOMEM;
> +
> +       dev->regbase = ioremap(base_addr + AMD_PMC_BASE_ADDR_OFFSET, AMD_PMC_MAPPING_SIZE);

Ditto.

> +       if (!dev->regbase) {
> +               iounmap(dev->smu_base);
> +               return -ENOMEM;
> +       }

...

> +               .acpi_match_table = ACPI_PTR(amd_pmc_acpi_ids),

It depends on ACPI. What is the point of ACPI_PTR?

...

> +

Redundant blank line

> +module_platform_driver(amd_pmc_driver);

...

> +++ b/drivers/platform/x86/amd-pmc.h

Who is going to use this file?

...

> +#define AMD_PMC_BASE_ADDR_HI_MASK      0xFFF00000L
> +#define AMD_PMC_BASE_ADDR_LO_MASK      0x0000FFFFL

You included bits.h and not using it, why?

...

> +#define PMC_MSG_DELAY_MIN              100
> +#define PMC_MSG_DELAY_MAX              200

Units?

...

> +enum amd_pmc_def {
> +       msg_test = 0x01,
> +       msg_os_hint_pco,
> +       msg_os_hint_rn,
> +};

Hmm... Perhaps capital letters?

-- 
With Best Regards,
Andy Shevchenko



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

  Powered by Linux