Re: [PATCH v12 15/15] soc: amd: Add support for AMD Pensando SoC Controller

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

 



Hi Andy,

Thanks for the review.

On Thu, Mar 23, 2023 at 13:06 Andy Shevchenko <andy.shevchenko@xxxxxxxxx> wrote:
> On Thu, Mar 23, 2023 at 2:11 AM Brad Larson <blarson@xxxxxxx> wrote:
>>
>> The Pensando SoC controller is a SPI connected companion device
>> that is present in all Pensando SoC board designs.  The essential
>> board management registers are accessed on chip select 0 with
>> board mgmt IO support accessed using additional chip selects.
>
> ...
>
>> +config AMD_PENSANDO_CTRL
>> +       tristate "AMD Pensando SoC Controller"
>> +       depends on SPI_MASTER=y
>> +       depends on (ARCH_PENSANDO && OF) || COMPILE_TEST
>> +       default y if ARCH_PENSANDO
>
>       default ARCH_PENSANDO

Changed to default ARCH_PENSANDO

>> +       select REGMAP_SPI
>> +       select MFD_SYSCON
>
> ...
>
>> +/*
>> + * AMD Pensando SoC Controller
>> + *
>> + * Userspace interface and reset driver support for SPI connected Pensando SoC
>> + * controller device.  This device is present in all Pensando SoC designs and
>> + * contains board control/status regsiters and management IO support.
>
> registers ?

Fixed the typo

> ...
>
>> +#include <linux/cdev.h>
>> +#include <linux/delay.h>
>> +#include <linux/device.h>
>> +#include <linux/err.h>
>> +#include <linux/fs.h>
>> +#include <linux/init.h>
>> +#include <linux/module.h>
>> +#include <linux/mutex.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>
> Seems semi-random. Are you sure you use this and not missing mod_devicetable.h?

Added mod_devicetable.h.
Removed delay.h, fs.h and of_device.h

>> +#include <linux/reset-controller.h>
>> +#include <linux/spi/spi.h>
>
>...
>
>> +struct penctrl_device {
>> +       struct spi_device *spi_dev;
>> +       struct reset_controller_dev rcdev;
>
> Perhaps swapping these two might provide a better code generation.

Its a 96 byte struct with pointer followed by the reset controller.
The spi_device variable is accessed frequently and rcdev during
boot and ideally never again so if rcdev is mostly missing from
cache that is fine.  Likely the address of spi_dev is also in 
cache given it is periodically accessed.

> ...
>
>> +       struct spi_transfer t[2] = { 0 };
>
> 0 is not needed.

Dropped the 0.

> ...
>
>> +       if (_IOC_DIR(cmd) & _IOC_READ)
>> +               ret = !access_ok((void __user *)arg, _IOC_SIZE(cmd));
>> +       else if (_IOC_DIR(cmd) & _IOC_WRITE)
>> +               ret = !access_ok((void __user *)arg, _IOC_SIZE(cmd));
>
>
> Maybe you should create a temporary variable as
>
>    void __user *in = ... arg;

Yes, created temp variable.

>
>> +       if (ret)
>> +               return -EFAULT;
>
> ...
>
>> +       /* Verify and prepare spi message */
>
> SPI

Changed to SPI

>> +       size = _IOC_SIZE(cmd);
>> +       if ((size % sizeof(struct penctrl_spi_xfer)) != 0) {
>
> ' != 0' is redundant.

Fixed

>
>> +               ret = -EINVAL;
>> +               goto done;
>> +       }
>> +       num_msgs = size / sizeof(struct penctrl_spi_xfer);
>
>> +       if (num_msgs == 0) {
>> +               ret = -EINVAL;
>> +               goto done;
>> +       }
>
> Can be unified with a previous check as
>
> if (size == 0 || size % ...)

Yes, made this change.

>> +       msg = memdup_user((struct penctrl_spi_xfer __user *)arg, size);
>> +       if (!msg) {
>> +               ret = PTR_ERR(msg);
>> +               goto done;
>> +       }
>
>...
>
>> +       if (copy_from_user((void *)(uintptr_t)tx_buf,
>> +                          (void __user *)msg->tx_buf, msg->len)) {
>
> Why are all these castings here?

Yes, overkill, changed to:

        if (copy_from_user(tx_buf, (void __user *)msg->tx_buf, msg->len)) {

> ...
>
>> +       if (copy_to_user((void __user *)msg->rx_buf,
>> +                        (void *)(uintptr_t)rx_buf, msg->len))
>> +               ret = -EFAULT;
>
> Ditto.

Changed to:

        if (copy_to_user((void __user *)msg->rx_buf, rx_buf, msg->len))

> ...
>
>> +       struct spi_transfer t[2] = { 0 };
>
> 0 is redundant.

Dropped the 0.

> ...
>
>> +       struct spi_transfer t[1] = { 0 };
>
> Ditto.

Dropped the 0.

> Why is this an array?

Fixed, it's a single message and shouldn't be an array.

> ...
>
>> +       ret = spi_sync(spi_dev, &m);
>> +       return ret;
>
> return spi_sync(...);

Fixed.

> ...
>
>> +       np = spi_dev->dev.parent->of_node;
>> +       ret = of_property_read_u32(np, "num-cs", &num_cs);
>
> Why not simply device_property_read_u32()?

It can be and removed two lines with below result. Also changed the
variable spi_dev to spi which is the more common usage.

        ret = device_property_read_u32(spi->dev.parent, "num-cs", &num_cs);
        if (ret)
                return dev_err_probe(&spi->dev, ret,
                                     "number of chip-selects not defined\n");

> ...
>
>> +       cdev = cdev_alloc();
>> +       if (!cdev) {
>> +               dev_err(&spi_dev->dev, "allocation of cdev failed");
>> +               ret = -ENOMEM;
>
> ret = dev_err_probe(...);

Fixed.

>> +               goto cdev_failed;
>> +       }
>
> ...
>
>> +       ret = cdev_add(cdev, penctrl_devt, num_cs);
>> +       if (ret) {
>
>> +               dev_err(&spi_dev->dev, "register of cdev failed");
>
> dev_err_probe() ?

Fixed.

>> +               goto cdev_delete;
>> +       }
>
> ...
>
>> +       penctrl = kzalloc(sizeof(*penctrl), GFP_KERNEL);
>> +       if (!penctrl) {
>
>> +               ret = -ENOMEM;
>> +               dev_err(&spi_dev->dev, "allocate driver data failed");
>
> ret = dev_err_probe();
> But we do not print memory allocation failure messages.

Fixed this way

        penctrl = kzalloc(sizeof(*penctrl), GFP_KERNEL);
        if (!penctrl) {
                ret = -ENOMEM;
                goto free_cdev;
        }

> ...
>
>> +               if (IS_ERR(dev)) {
>> +                       ret = IS_ERR(dev);
>> +                       dev_err(&spi_dev->dev, "error creating device\n");
>
> ret = dev_err_probe();

Fixed.

> ...
>
> +       spi_set_drvdata(spi_dev, penctrl);
>
> Is it in use?

Not used and now dropped.

> ...
>
>> +       penctrl->rcdev.of_node = spi_dev->dev.of_node;
>
> device_set_node();

Added: device_set_node(&spi->dev, dev_fwnode(dev));

> ...
>
>> +       ret = reset_controller_register(&penctrl->rcdev);
>> +       if (ret)
>> +               return dev_err_probe(&spi_dev->dev, ret,
>> +                                    "failed to register reset controller\n");
>> +       return ret;
>
> return 0;

Yes, changed.

> ...
>
>> +       device_destroy(penctrl_class, penctrl_devt);
>
> Are you sure this is the correct API?

Yes, however a probe error could call up to 5 APIs to clean up which resulted
in this update:

destroy_device:
        for (cs = 0; cs < num_cs; cs++)
                device_destroy(penctrl_class, MKDEV(MAJOR(penctrl_devt), cs));
        kfree(penctrl);
free_cdev:
        cdev_del(cdev);
destroy_class:
        class_destroy(penctrl_class);
unregister_chrdev:
        unregister_chrdev(MAJOR(penctrl_devt), "penctrl");

        return ret;

> ...
>
>> +#include <linux/types.h>
>> +#include <linux/ioctl.h>
>
> Sorted?

Swapped these

Regards,
Brad



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux