From: Julien Grall <julien.grall@citrix.com>
To: vijay.kilari@gmail.com, Ian.Campbell@citrix.com,
stefano.stabellini@eu.citrix.com, stefano.stabellini@citrix.com,
tim@xen.org, xen-devel@lists.xen.org
Cc: Prasun.Kapoor@caviumnetworks.com,
Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>,
manish.jaggi@caviumnetworks.com
Subject: Re: [PATCH v7 08/28] xen/arm: ITS: Add APIs to add and assign device
Date: Mon, 21 Sep 2015 14:47:39 +0100 [thread overview]
Message-ID: <56000A7B.5070503@citrix.com> (raw)
In-Reply-To: <1442581755-2668-9-git-send-email-vijay.kilari@gmail.com>
Hi Vijay,
On 18/09/15 14:08, vijay.kilari@gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
>
> Add APIs to add devices to RB-tree, assign and remove
> devices to domain.
>
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>
> ---
> v7: - Added check for domain in its_assign_device() to avoid
> assigning device to DomU
> - Added comments whereever requested
> - Called its_remove_device to remove from rb-tree
> when failed to add device
> - Changed dprintk to printk
> - Store domain pointer instead of domain id in its_device struct
> - Free msi_desc and reset irq_desc when lpis are discarded
> - Add function its_free_msi_descs() to free msi_desc
> v6: - Moved this patch #19 to patch #8
> - Used col_map to store collection id
> - Use helper functions to update msi_desc members
> v5: - Removed its_detach_device API
> - Pass nr_ites as parameter to its_add_device
> v4: - Introduced helper to populate its_device struct
> - Fixed freeing of its_device memory
> - its_device struct holds domain id
> ---
> xen/arch/arm/gic-v3-its.c | 261 +++++++++++++++++++++++++++++++++++++++++
> xen/include/asm-arm/gic-its.h | 6 +
> 2 files changed, 267 insertions(+)
>
> diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
> index 4b7d9ed..bc3b73c 100644
> --- a/xen/arch/arm/gic-v3-its.c
> +++ b/xen/arch/arm/gic-v3-its.c
> @@ -145,6 +145,19 @@ static struct its_collection *dev_event_to_col(struct its_device *dev,
> return its->collections + dev->event_map.col_map[event];
> }
>
> +static struct its_node *its_get_phys_node(struct dt_device_node *dt)
> +{
> + struct its_node *its;
> +
> + list_for_each_entry(its, &its_nodes, entry)
> + {
> + if ( its->dt_node == dt )
> + return its;
> + }
> +
> + return NULL;
> +}
> +
> /* RB-tree helpers for its_device */
> static struct its_device *its_find_device(u32 devid)
> {
> @@ -537,8 +550,256 @@ static void its_lpi_free(struct its_device *dev)
> }
>
> spin_unlock(&lpi_lock);
> +}
> +
> +static void its_discard_lpis(struct its_device *dev, u32 ids)
> +{
> + int i;
u32 i;
> +
> + for ( i = 0; i < ids; i++ )
> + its_send_discard(dev, i);
> +}
> +
> +static void its_free_msi_descs(struct its_device *dev, int count)
its_free_msi_descs can be merge with its_discard_lpis. It would avoid
looping twice which can be expensive with device having a lot of MSI and
make clear the dependency.
For instance its_free_msi_descs should never be called before
its_discard_lpis.
> +{
> + int i, irq;
Why do you need them signed? Same for the parameter "count".
> + struct irq_desc *desc;
> +
> + for ( i = 0; i < count; i++ )
> + {
> + irq = dev->event_map.lpi_base + i;
You could have use its_get_plpi here.
> + desc = irq_to_desc(irq);
> +
> + spin_lock(&desc->lock);
> + irqdesc_set_lpi_event(desc, 0);
> + irqdesc_set_its_device(desc, NULL);
Why do you need these 2 calls?
> + xfree(irq_get_msi_desc(desc));
> + irq_set_msi_desc(desc, NULL);
After this, the IRQ desc is still left in an unknown state (give a look
to gic_remove_irq_from_guest).
Although, it may not need necessary for now. So I would be fine with a
TODO in the code.
> + spin_unlock(&desc->lock);
> + }
> +}
> +
> +static inline u32 its_get_plpi(struct its_device *dev, u32 event)
> +{
> + return dev->event_map.lpi_base + event;
> +}
> +
> +static int its_alloc_device_irq(struct its_device *dev, u32 *hwirq)
> +{
> + int idx;
> +
> + idx = find_first_zero_bit(dev->event_map.lpi_map, dev->event_map.nr_lpis);
> + if ( idx == dev->event_map.nr_lpis )
> + return -ENOSPC;
> +
> + *hwirq = its_get_plpi(dev, idx);
> + set_bit(idx, dev->event_map.lpi_map);
>
> + return 0;
> +}
> +
> +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?
> + 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.
> +{
> + 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.
> + 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.
> + {
> + 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 */
This wasn't present on the previous version. Why do you need that? DOM0
is just a guest and you make the code in the assignation function (see
its_assign_device) for nothing.
IHMO, the code to add a device and assign to a guest should be
completely separate.
> + dev->domain = hardware_domain;
> + spin_unlock(&rb_its_dev_lock);
> +
> + DPRINTK("ITS:Add Device 0x%"PRIx32" lpis %"PRIu32" base 0x%"PRIx32"\n",
> + dev->device_id, dev->event_map.nr_lpis, dev->event_map.lpi_base);
> +
> + /* Map device to ITS ITT */
> + its_send_mapd(dev, 1);
> +
> + for ( i = 0; i < dev->event_map.nr_lpis; i++ )
> + {
> + msi = xzalloc(struct msi_desc);
> + if ( its_alloc_device_irq(dev, &plpi) || !msi )
> + {
> + /* Discard LPIs and free device on failure to allocate pLPI */
> + its_discard_lpis(dev, i);
> + its_free_msi_descs(dev, i);
> + its_send_mapd(dev, 0);
> +
> + spin_lock(&rb_its_dev_lock);
> + its_remove_device(dev);
> + spin_unlock(&rb_its_dev_lock);
> +
> + its_free_device(dev);
> +
> + printk(XENLOG_G_ERR "ITS: Cannot add device 0x%"PRIx32"\n", devid);
Same question as before for XENLOG_G_ERR.
> + res = -ENOSPC;
> + goto err;
> + }
> +
> + /*
> + * Each Collection is mapped to one physical CPU and
> + * each pLPI allocated to this device is mapped one collection
> + * in a roundrobin fashion. Hence all pLPIs are distributed
s/roundrobin/round robin/
> + * across all processors in the system.
> + */
> + col = &dev->its->collections[(i % nr_cpu_ids)];
Your round robin is done per device. So if we have 10 devices with a
single event ID, all the LPIs will be routed to CPU0.
I guess this is fine for now, but it worth mentioning it in the comment.
> + desc = irq_to_desc(plpi);
> +
> + spin_lock(&desc->lock);
> + dev->event_map.col_map[i] = col->col_id;
> + irq_set_msi_desc(desc, msi);
> + irqdesc_set_lpi_event(desc, i);
> + irqdesc_set_its_device(desc, dev);
While I gave my reviewed-by on the patch with add those helpers (see
#7), I'm continuing to think that they are not useful and make the usage
more difficult due the ordering requirement.
Something like below would have been better:
msi->eventID = i;
msi->dev = dev;
irq_set_msi_desc(msi);
This will also turn 5 functions call (2 for each irqdesc_* + 1 for
irq_set_msi_*) into a single one.
This code is still ok, but it would make a different in the LPI handling
code later.
> + spin_unlock(&desc->lock);
> +
> + /* For each pLPI send MAPVI command */
> + its_send_mapvi(dev, plpi, i);
> + }
> +
> + return 0;
> +
> +err_unlock:
> + spin_unlock(&rb_its_dev_lock);
> +err:
> + return res;
> +}
> +
> +int its_assign_device(struct domain *d, u32 vdevid, u32 pdevid)
> +{
> + struct its_device *pdev;
> + u32 plpi, i;
> +
> + DPRINTK("ITS: Assign request for dev 0x%"PRIx32" to domain %"PRIu16"\n",
> + vdevid, d->domain_id);
> +
> + spin_lock(&rb_its_dev_lock);
> + pdev = its_find_device(pdevid);
> + if ( !pdev )
> + {
> + spin_unlock(&rb_its_dev_lock);
> + return -ENODEV;
> + }
> + spin_unlock(&rb_its_dev_lock);
You can rework this code to avoid 2 spin_unlock:
spin_lock(&rb...)
pdev = its_find_device(pdevid);
spin_unlock(&rb...)
if ( !pdev )
return -ENODEV;
> +
> + /*
> + * 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?".
> + * 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
next prev parent reply other threads:[~2015-09-21 13:47 UTC|newest]
Thread overview: 81+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-18 13:08 [PATCH v7 00/28] Add ITS support vijay.kilari
2015-09-18 13:08 ` [PATCH v7 01/28] xen/arm: Add bitmap_find_next_zero_area helper function vijay.kilari
2015-09-18 13:08 ` [PATCH v7 02/28] xen: Add log2 functionality vijay.kilari
2015-09-18 13:08 ` [PATCH v7 03/28] xen/arm: Set nr_cpu_ids to available number of cpus vijay.kilari
2015-09-18 13:08 ` [PATCH v7 04/28] xen/arm: Rename NR_IRQs and vgic_num_irqs helper function vijay.kilari
2015-09-21 10:40 ` Julien Grall
2015-09-18 13:08 ` [PATCH v7 05/28] xen/arm: ITS: Port ITS driver to Xen vijay.kilari
2015-09-21 11:23 ` Julien Grall
2015-09-22 9:55 ` Vijay Kilari
2015-09-22 10:01 ` Julien Grall
2015-09-22 10:34 ` Vijay Kilari
2015-09-22 12:34 ` Julien Grall
2015-09-21 13:08 ` Julien Grall
2015-09-18 13:08 ` [PATCH v7 06/28] xen/arm: ITS: Add helper functions to manage its_devices vijay.kilari
2015-09-18 14:15 ` Julien Grall
2015-09-21 11:26 ` Julien Grall
2015-09-18 13:08 ` [PATCH v7 07/28] xen/arm: ITS: Introduce msi_desc for LPIs vijay.kilari
2015-09-18 13:08 ` [PATCH v7 08/28] xen/arm: ITS: Add APIs to add and assign device vijay.kilari
2015-09-21 13:47 ` Julien Grall [this message]
2015-09-22 7:33 ` Vijay Kilari
2015-09-22 13:19 ` Julien Grall
2015-09-18 13:08 ` [PATCH v7 09/28] xen/arm: ITS: Introduce gic_is_lpi helper function vijay.kilari
2015-09-21 14:20 ` Julien Grall
2015-09-22 9:10 ` Vijay Kilari
2015-09-22 13:24 ` Julien Grall
2015-09-18 13:08 ` [PATCH v7 10/28] xen/arm: ITS: Implement hw_irq_controller for LPIs vijay.kilari
2015-09-21 14:35 ` Julien Grall
2015-09-18 13:08 ` [PATCH v7 11/28] xen/arm: ITS: Enable compilation of physical ITS driver vijay.kilari
2015-09-18 13:08 ` [PATCH v7 12/28] xen/arm: ITS: Plumbing hw_irq_controller for LPIs vijay.kilari
2015-09-21 14:44 ` Julien Grall
2015-09-18 13:09 ` [PATCH v7 13/28] xen/arm: Move vgic rank locking inside get_irq_priority vijay.kilari
2015-09-21 14:49 ` Julien Grall
2015-09-18 13:09 ` [PATCH v7 14/28] xen/arm: ITS: Initialize physical ITS and export lpi support vijay.kilari
2015-09-21 15:20 ` Julien Grall
2015-09-22 9:17 ` Vijay Kilari
2015-09-22 9:45 ` Julien Grall
2015-09-22 10:05 ` Ian Campbell
2015-09-22 10:29 ` Julien Grall
2015-09-22 10:44 ` Ian Campbell
2015-09-22 12:31 ` Julien Grall
2015-09-18 13:09 ` [PATCH v7 15/28] xen/arm: ITS: Add virtual ITS driver vijay.kilari
2015-09-21 15:34 ` Julien Grall
2015-09-18 13:09 ` [PATCH v7 16/28] xen/arm: ITS: Add virtual ITS commands support vijay.kilari
2015-09-22 13:47 ` Julien Grall
2015-09-18 13:09 ` [PATCH v7 17/28] xen/arm: ITS: Add GITS registers emulation vijay.kilari
2015-09-22 14:30 ` Julien Grall
2015-09-24 5:07 ` Vijay Kilari
2015-09-24 11:05 ` Julien Grall
2015-09-24 11:29 ` Ian Campbell
2015-09-24 11:43 ` Julien Grall
2015-09-18 13:09 ` [PATCH v7 18/28] xen/arm: ITS: Export ITS info to Virtual ITS vijay.kilari
2015-09-23 8:31 ` Julien Grall
2015-09-24 5:26 ` Vijay Kilari
2015-09-24 8:27 ` Ian Campbell
2015-09-24 11:31 ` Julien Grall
2015-09-24 11:41 ` Ian Campbell
2015-09-18 13:09 ` [PATCH v7 19/28] xen/arm: ITS: Store LPIs allocated per domain vijay.kilari
2015-09-23 8:37 ` Julien Grall
2015-09-18 13:09 ` [PATCH v7 20/28] xen/arm: ITS: Add virtual ITS availability check helper vijay.kilari
2015-09-23 8:52 ` Julien Grall
2015-09-24 6:44 ` Vijay Kilari
2015-09-24 11:47 ` Julien Grall
2015-09-18 13:09 ` [PATCH v7 21/28] xen/arm: ITS: Add GICR register emulation vijay.kilari
2015-09-23 10:22 ` Julien Grall
2015-09-26 16:08 ` Vijay Kilari
2015-09-28 9:53 ` Ian Campbell
2015-09-28 10:37 ` Vijay Kilari
2015-09-28 11:03 ` Julien Grall
2015-09-29 9:35 ` Vijay Kilari
2015-09-18 13:09 ` [PATCH v7 22/28] xen/arm: ITS: Allocate irq descriptors for LPIs vijay.kilari
2015-09-23 10:28 ` Julien Grall
2015-09-18 13:09 ` [PATCH v7 23/28] xen/arm: ITS: Allocate pending_lpi " vijay.kilari
2015-09-24 12:38 ` Julien Grall
2015-09-18 13:09 ` [PATCH v7 24/28] xen/arm: ITS: Route LPIs vijay.kilari
2015-09-18 13:09 ` [PATCH v7 25/28] xen/arm: ITS: Add domain specific ITS initialization vijay.kilari
2015-09-18 13:09 ` [PATCH v7 26/28] xen/arm: ITS: Map ITS translation space vijay.kilari
2015-09-18 13:09 ` [PATCH v7 27/28] xen/arm: ITS: Generate ITS node for Dom0 vijay.kilari
2015-09-18 13:09 ` [PATCH v7 28/28] xen/arm: ITS: Add pci devices in ThunderX vijay.kilari
2015-09-22 15:09 ` Julien Grall
2015-09-18 13:51 ` [PATCH v7 00/28] Add ITS support Julien Grall
2015-09-21 6:52 ` Vijay Kilari
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=56000A7B.5070503@citrix.com \
--to=julien.grall@citrix.com \
--cc=Ian.Campbell@citrix.com \
--cc=Prasun.Kapoor@caviumnetworks.com \
--cc=Vijaya.Kumar@caviumnetworks.com \
--cc=manish.jaggi@caviumnetworks.com \
--cc=stefano.stabellini@citrix.com \
--cc=stefano.stabellini@eu.citrix.com \
--cc=tim@xen.org \
--cc=vijay.kilari@gmail.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.