[PATCH linux v5 17/18] drivers/fsi: Add SCOM FSI client device driver

Christopher Bostic christopher.lee.bostic at gmail.com
Fri Oct 21 02:21:19 AEDT 2016


On Wed, Oct 19, 2016 at 10:27 PM, Jeremy Kerr <jk at ozlabs.org> wrote:
> Hi Chris,
>
>> diff > +static int scom_probe(struct device *);
>> +
>> +struct scom_op {
>> +     uint64_t        data;
>> +     uint32_t        addr;
>> +};
>
> You're making this a userspace interface, so this should go into the
> uapi headers (and then will form part of the unchangeable Linux ABI).
> However, more on the ABI below...
>
>> +struct scom_device {
>> +     struct fsi_device *fsi_dev;
>> +     struct cdev *cdev;
>> +};
>> +
>> +struct scom_device scom_dev;
>> +
>> +struct fsi_device_id scom_ids[] = {
>> +     {
>> +             .engine_type = FSI_ENGID_SCOM,
>> +             .version = FSI_VERSION_ANY,
>> +     },
>> +     { 0 }
>> +};
>> +
>> +struct fsi_driver scom_drv = {
>> +     .id_table = scom_ids,
>> +     .drv = {
>> +             .name = "scom",
>> +             .bus = &fsi_bus_type,
>> +             .probe = scom_probe,
>> +     }
>> +};
>
> Make these static, and put after the code, just before the
> module_fsi_driver. Then you won't need the forward definition of
> scom_probe.
>

Hi Jeremy,

OK will change.

>> > +static ssize_t scom_read(struct file *filep, char __user *buf, size_t len,
>> +                     loff_t *offset)
>> +{
>> +     int rc = 0;
>> +     struct scom_op op;
>> +     struct scom_device *scom = &scom_dev;
>> +     struct device *dev = &scom->fsi_dev->dev;
>> +
>> +     /* todo: Retrieve device to operate on from filep->private_data */
>
> Yep, otherwise you only get one scom interface, and crazy results if you
> get probed twice. I'd suggest not leaving this until later.
>

Will add.

>> +
>> +     if (len != sizeof(struct scom_op))
>> +             return -EINVAL;
>> +
>> +     rc = copy_from_user(&op, buf, len);
>> +     if (rc) {
>> +             dev_dbg(dev, "copy from user failed:%d\n", rc);
>> +             return -EINVAL;
>> +     }
>> +
>> +     rc = get_scom(&op.data, op.addr);
>
> I'm not a huge fan of that ABI to userspace. You already have the
> address in the offset argument, so you can do this without needing new
> uapi headers, using something like:
>
> static ssize_t scom_read(struct file *filep, char __user *buf, size_t len,
>                         loff_t *offset)
> {
>         uint64_t val;
>
>         /* todo: can we do 1/2/4/8 byte operations too? */
>         if (len != sizeof(uint64_t))
>                 return -EINVAL;
>
>         rc = get_scom(&val, offset);
>         if (rc)
>                 return rc;
>
>         rc = copy_to_user(&val, buf, len);
>
>         return rc ? rc : len;
> }
>

OK, will change that.

>
> Also, have you thought about endianness?
>
>

The plan is for endianness is to be dealt with in the fsi-core
so the other engines don't need to worry about it.  Yes there
is likely to be some additions there.  Will need to evaluate.

>> +static int scom_probe(struct device *dev)
>> +{
>> +     struct fsi_device *fsi_dev = to_fsi_dev(dev);
>> +     struct scom_device *scom = &scom_dev;
>> +     int rc;
>> +
>> +     scom->fsi_dev = fsi_dev;
>> +     scom->cdev = cdev_alloc();
>> +     if (!scom->cdev)
>> +             return -ENOMEM;
>> +
>> +     scom->cdev->owner = THIS_MODULE;
>> +
>> +     rc = register_chrdev(0, "scom", &scom_fops);
>> +     if (rc < 0) {
>> +             dev_dbg(dev, "scom major allocation failed:%d\n", rc);
>> +             return rc;
>> +     }
>> +     dev_dbg(dev, "scom major allocated:%d\n", rc);
>
> You need to register the actual device too, right? We'll want scom0,
> scom1, etc.

Don't understand your meaning here.  Also scom0 and scom1 refer to
what exactly?  For a first pass of core code I'd like to be able to deal
with a single engine if possible and expand later.

Thanks,
Chris


>
> Cheers,
>
>
> Jeremy


More information about the openbmc mailing list