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

Re: [Xen-devel] [PATCH v7 08/28] xen/arm: ITS: Add APIs to add and assign device



On Mon, Sep 21, 2015 at 7:17 PM, Julien Grall <julien.grall@xxxxxxxxxx> wrote:
> Hi Vijay,
>
> On 18/09/15 14:08, vijay.kilari@xxxxxxxxx wrote:
>> From: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx>
>>
>> Add APIs to add devices to RB-tree, assign and remove
>> devices to domain.
>>
[...]
>> +
>> +static void its_free_device(struct its_device *dev)
>> +{
>> +    xfree(dev->itt);
>> +    its_lpi_free(dev);
>>      xfree(dev->event_map.lpi_map);
>
> Why did you move this call from its_lpi_free to here?

its_lpi_free() is called along with its_free_device. So moved into
this code instead of calling it separately. This helps to avoid
chances of missing it out.

>
>> +    xfree(dev->event_map.col_map);
>
> This line should have been added in its_lpi_free in patch #5.
>
>> +    xfree(dev);
>> +}
>> +
>> +static struct its_device *its_alloc_device(u32 devid, u32 nr_ites,
>> +                                           struct dt_device_node *dt_its)
>
> Can you explain why you weren't able to re-use its_create_device from Linux?
>
> AFAICT there is nothing different and you miss key code such as rounding
> to a power of 2 the number of event IDs.
>

  It is almost re-used with following changes
1) Rounding of nr_ites, which is missing. However nr_ites is passed
from platform
    file.
2) Freeing of memory on failure. Here I re-used its_free_device() which does
    the same

>> +{
>> +    struct its_device *dev;
>> +    unsigned long *lpi_map;
>> +    int lpi_base, sz;
>> +    u16 *col_map = NULL;
>> +
>> +    dev = xzalloc(struct its_device);
>> +    if ( dev == NULL )
>> +        return NULL;
>> +
>> +    dev->its = its_get_phys_node(dt_its);
>
> You can re-order the code to get the ITS before allocate the memory. And
> then you can drop one goto.
>
>> +    if (dev->its == NULL)
>> +    {
>> +        printk(XENLOG_G_ERR
>
> As already asked on v6, why XENLOG_G_ERR? Any call to this function will
> be done via privileged guest.
>
>> +               "ITS: Failed to find ITS node for devid 0x%"PRIx32"\n", 
>> devid);
>> +        goto err;
>> +    }
>> +
>> +    sz = nr_ites * dev->its->ite_size;
>> +    sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
>> +    dev->itt = xzalloc_bytes(sz);
>> +    if ( !dev->itt )
>> +        goto err;
>> +
>> +    lpi_map = its_lpi_alloc_chunks(nr_ites, &lpi_base);
>> +    if ( !lpi_map )
>> +        goto lpi_err;
>> +
>> +    col_map = xzalloc_bytes(sizeof(*col_map) * nr_ites);
>> +    if ( !col_map )
>> +        goto col_err;
>> +    dev->event_map.lpi_map = lpi_map;
>> +    dev->event_map.lpi_base = lpi_base;
>> +    dev->event_map.col_map = col_map;
>> +    dev->event_map.nr_lpis = nr_ites;
>> +    dev->device_id = devid;
>> +
>> +    return dev;
>> +
>> +col_err:
>> +    its_free_device(dev);
>> +    return NULL;
>> +lpi_err:
>> +    xfree(dev->itt);
>> +err:
>> +    xfree(dev);
>> +
>> +    return NULL;
>> +}
>> +
>> +/* Device assignment */
>> +int its_add_device(u32 devid, u32 nr_ites, struct dt_device_node *dt_its)
>> +{
>> +    struct its_device *dev;
>> +    u32 i, plpi = 0;
>> +    struct its_collection *col;
>> +    struct irq_desc *desc;
>> +    struct msi_desc *msi = NULL;
>> +    int res = 0;
>> +
>> +    spin_lock(&rb_its_dev_lock);
>> +    dev = its_find_device(devid);
>> +    if ( dev )
>> +    {
>> +        printk(XENLOG_G_ERR "ITS: Device already exists 0x%"PRIx32"\n",
>
> Same question as before for XENLOG_G_ERR.

I should have used XENLOG_ERR?

>
>> +               dev->device_id);
>> +        res = -EEXIST;
>> +        goto err_unlock;
>> +    }
>> +
>> +    dev = its_alloc_device(devid, nr_ites, dt_its);
>> +    if ( !dev )
>> +    {
>> +        res = -ENOMEM;
>> +        goto err_unlock;
>> +    }
>> +
>> +    if ( its_insert_device(dev) )
>
> The only way that this call can fail is because the device already
> exists in the RB-tree. Although, this can never happen because you have
> the lock taken and check beforehand if someone has inserted a device
> with this devID.
>
> So I would turn this if into an BUG_ON(its_insert_device(dev)) and save
> 6 lines.

With below code it prints message, free's up memory and return error.
The caller can handle as required.

>
>> +    {
>> +        its_free_device(dev);
>> +        printk(XENLOG_G_ERR "ITS: Failed to insert device 0x%"PRIx32"\n", 
>> devid);
>> +        res = -EINVAL;
>> +        goto err_unlock;
>> +    }
>> +    /* Assign device to dom0 by default */
>
[...]
>
>> +
>> +    /*
>> +     * TODO: For pass-through following has to be implemented
>> +     * 1) Allow device to be assigned to other domains (Dom0 -> DomU).
>> +     * 2) Allow device to be re-assigned to Dom0 (DomU -> Dom0).
>> +     * Implement separate function to handle this or rework this function.
>> +     * For now do not allow assigning devices other than Dom0.
>> +     *
>> +     * By default all devices are assigned to Dom0.
>
> See my question above about the "why?".

AIUI, by default all devices are assigned to Dom0.
By updating dev->domain in add device to Dom0, we are making
sure that at the time of add device the device is with Dom0.

In assign_device the below check ensures that devices are with Dom0
before assigning to other Doms.

If we don't want to update dev->domain in add_device then
I think, we can explicitly initialize dev->domain = NULL and
check here (assign_device) that dev->domain should always either NULL or
should be hardware_domain.

>
>> +     * Device should be with Dom0 before assigning to other domain.
>> +     */
>> +    if ( !is_hardware_domain(d) || !is_hardware_domain(pdev->domain) )
>> +    {
>> +        printk(XENLOG_ERR
>> +               "ITS: PCI-Passthrough not supported!! to assign from d%d to 
>> d%d",
>> +               pdev->domain->domain_id, d->domain_id);
>> +        return -ENXIO;
>> +    }
>> +
>> +    pdev->domain = d;
>> +    pdev->virt_device_id = vdevid;
>> +
>> +    DPRINTK("ITS: Assign pdevid 0x%"PRIx32" lpis %"PRIu32" for dom 
>> %"PRIu16"\n",
>> +            pdevid, pdev->event_map.nr_lpis, d->domain_id);
>> +
>> +    for ( i = 0; i < pdev->event_map.nr_lpis; i++ )
>> +    {
>> +        plpi = its_get_plpi(pdev, i);
>> +        /* TODO: Route lpi */
>> +    }
>> +
>> +    return 0;
>>  }
>
> Regards,
>
> --
> Julien Grall

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.