linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: marc.zyngier@arm.com (Marc Zyngier)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 09/13] irqchip: GICv3: ITS: MSI support
Date: Mon, 08 Dec 2014 09:32:24 +0000	[thread overview]
Message-ID: <54857028.2010707@arm.com> (raw)
In-Reply-To: <54851ACF.2090204@huawei.com>

On 08/12/14 03:28, Yun Wu (Abel) wrote:
> Hi Marc,
> On 2014/11/24 22:35, Marc Zyngier wrote:
> 
>> Now, the bit of code that allow us to use the ITS as a MSI controller.
>> Both MSI and MSI-X are supported.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  drivers/irqchip/irq-gic-v3-its.c   | 176 +++++++++++++++++++++++++++++++++++++
>>  include/linux/irqchip/arm-gic-v3.h |   6 ++
>>  2 files changed, 182 insertions(+)
>>
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
>> index d687fd4..532c6df 100644
>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -587,12 +587,47 @@ static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
>>  	return IRQ_SET_MASK_OK_DONE;
>>  }
>>  
>> +static void its_irq_compose_msi_msg(struct irq_data *d, struct msi_msg *msg)
>> +{
>> +	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
>> +	struct its_node *its;
>> +	u64 addr;
>> +
>> +	its = its_dev->its;
>> +	addr = its->phys_base + GITS_TRANSLATER;
>> +
>> +	msg->address_lo		= addr & ((1UL << 32) - 1);
>> +	msg->address_hi		= addr >> 32;
>> +	msg->data		= its_get_event_id(d);
>> +}
>> +
>>  static struct irq_chip its_irq_chip = {
>>  	.name			= "ITS",
>>  	.irq_mask		= its_mask_irq,
>>  	.irq_unmask		= its_unmask_irq,
>>  	.irq_eoi		= its_eoi_irq,
>>  	.irq_set_affinity	= its_set_affinity,
>> +	.irq_compose_msi_msg	= its_irq_compose_msi_msg,
>> +};
>> +
>> +static void its_mask_msi_irq(struct irq_data *d)
>> +{
>> +	pci_msi_mask_irq(d);
>> +	irq_chip_mask_parent(d);
>> +}
>> +
>> +static void its_unmask_msi_irq(struct irq_data *d)
>> +{
>> +	pci_msi_unmask_irq(d);
>> +	irq_chip_unmask_parent(d);
>> +}
>> +
>> +static struct irq_chip its_msi_irq_chip = {
>> +	.name			= "ITS-MSI",
>> +	.irq_unmask		= its_unmask_msi_irq,
>> +	.irq_mask		= its_mask_msi_irq,
>> +	.irq_eoi		= irq_chip_eoi_parent,
>> +	.irq_write_msi_msg	= pci_msi_domain_write_msg,
>>  };
>>  
>>  /*
>> @@ -1055,3 +1090,144 @@ static void its_free_device(struct its_device *its_dev)
>>  	kfree(its_dev->itt);
>>  	kfree(its_dev);
>>  }
>> +
>> +static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq)
>> +{
>> +	int idx;
>> +
>> +	idx = find_first_zero_bit(dev->lpi_map, dev->nr_lpis);
>> +	if (idx == dev->nr_lpis)
>> +		return -ENOSPC;
>> +
>> +	*hwirq = dev->lpi_base + idx;
>> +	set_bit(idx, dev->lpi_map);
>> +
>> +	/* Map the GIC irq ID to the device */
>> +	its_send_mapvi(dev, *hwirq, idx);
> 
> It would be better if we do hardware-level initialization in domain.{activate,deactivate}.

That'd certainly be possible. I'll have a look.

>> +
>> +	return 0;
>> +}
>> +
>> +static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
>> +			   int nvec, msi_alloc_info_t *info)
>> +{
>> +	struct pci_dev *pdev;
>> +	struct its_node *its;
>> +	u32 dev_id;
>> +	struct its_device *its_dev;
>> +
>> +	if (!dev_is_pci(dev))
>> +		return -EINVAL;
>> +
>> +	pdev = to_pci_dev(dev);
>> +	dev_id = PCI_DEVID(pdev->bus->number, pdev->devfn);
>> +	its = domain->parent->host_data;
>> +
>> +	its_dev = its_find_device(its, dev_id);
>> +	if (WARN_ON(its_dev))
>> +		return -EINVAL;
>> +
>> +	its_dev = its_create_device(its, dev_id, nvec);
>> +	if (!its_dev)
>> +		return -ENOMEM;
>> +
>> +	dev_dbg(&pdev->dev, "ITT %d entries, %d bits\n", nvec, ilog2(nvec));
>> +
>> +	info->scratchpad[0].ptr = its_dev;
>> +	info->scratchpad[1].ptr = dev;
>> +	return 0;
>> +}
>> +
>> +static struct msi_domain_ops its_pci_msi_ops = {
>> +	.msi_prepare	= its_msi_prepare,
>> +};
>> +
>> +static struct msi_domain_info its_pci_msi_domain_info = {
>> +	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
>> +		   MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX),
>> +	.ops	= &its_pci_msi_ops,
>> +	.chip	= &its_msi_irq_chip,
>> +};
>> +
>> +static int its_irq_gic_domain_alloc(struct irq_domain *domain,
>> +				    unsigned int virq,
>> +				    irq_hw_number_t hwirq)
>> +{
>> +	struct of_phandle_args args;
>> +
>> +	args.np = domain->parent->of_node;
>> +	args.args_count = 3;
>> +	args.args[0] = GIC_IRQ_TYPE_LPI;
>> +	args.args[1] = hwirq;
>> +	args.args[2] = IRQ_TYPE_EDGE_RISING;
>> +
>> +	return irq_domain_alloc_irqs_parent(domain, virq, 1, &args);
>> +}
>> +
>> +static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
>> +				unsigned int nr_irqs, void *args)
>> +{
>> +	msi_alloc_info_t *info = args;
>> +	struct its_device *its_dev = info->scratchpad[0].ptr;
>> +	irq_hw_number_t hwirq;
>> +	int err;
>> +	int i;
>> +
>> +	for (i = 0; i < nr_irqs; i++) {
>> +		err = its_alloc_device_irq(its_dev, &hwirq);
>> +		if (err)
>> +			return err;
>> +
>> +		err = its_irq_gic_domain_alloc(domain, virq + i, hwirq);
>> +		if (err)
>> +			return err;
>> +
>> +		irq_domain_set_hwirq_and_chip(domain, virq + i,
>> +					      hwirq, &its_irq_chip, its_dev);
>> +		dev_dbg(info->scratchpad[1].ptr, "ID:%d pID:%d vID:%d\n",
>> +			(int)(hwirq - its_dev->lpi_base), (int)hwirq, virq + i);
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
>> +				unsigned int nr_irqs)
>> +{
>> +	struct irq_data *d = irq_domain_get_irq_data(domain, virq);
>> +	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
>> +	int i;
>> +
>> +	for (i = 0; i < nr_irqs; i++) {
>> +		struct irq_data *data = irq_domain_get_irq_data(domain,
>> +								virq + i);
>> +		int event = its_get_event_id(data);
>> +
>> +		/* Stop the delivery of interrupts */
>> +		its_send_discard(its_dev, event);
>> +
>> +		/* Mark interrupt index as unused */
>> +		clear_bit(event, its_dev->lpi_map);
>> +
>> +		/* Nuke the entry in the domain */
>> +		irq_domain_reset_irq_data(d);
> 
> I think you mean "data" here, instead of "d"?

Indeed, nice catch.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

  reply	other threads:[~2014-12-08  9:32 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-24 14:35 [PATCH v3 00/13] arm64: PCI/MSI: GICv3 ITS support (stacked domain edition) Marc Zyngier
2014-11-24 14:35 ` [PATCH v3 01/13] arm64: PCI/MSI: Use asm-generic/msi.h Marc Zyngier
2014-11-24 14:35 ` [PATCH v3 02/13] irqchip: GICv3: Convert to domain hierarchy Marc Zyngier
2014-11-24 14:35 ` [PATCH v3 03/13] irqchip: GICv3: rework redistributor structure Marc Zyngier
2014-11-24 14:35 ` [PATCH v3 04/13] irqchip: GICv3: ITS command queue Marc Zyngier
2014-12-10  3:03   ` Yun Wu (Abel)
2014-12-10 11:20     ` Marc Zyngier
2014-11-24 14:35 ` [PATCH v3 05/13] irqchip: GICv3: ITS: irqchip implementation Marc Zyngier
2014-11-24 14:35 ` [PATCH v3 06/13] irqchip: GICv3: ITS: LPI allocator Marc Zyngier
2014-11-24 14:57   ` Jiang Liu
2014-11-24 15:32     ` Marc Zyngier
2014-11-24 14:35 ` [PATCH v3 07/13] irqchip: GICv3: ITS: tables allocators Marc Zyngier
2014-11-24 14:35 ` [PATCH v3 08/13] irqchip: GICv3: ITS: device allocation and configuration Marc Zyngier
2014-11-24 14:35 ` [PATCH v3 09/13] irqchip: GICv3: ITS: MSI support Marc Zyngier
2014-12-04 21:52   ` Stuart Yoder
2014-12-04 21:58     ` Thomas Gleixner
2014-12-05 10:10     ` Marc Zyngier
2014-12-08  3:28   ` Yun Wu (Abel)
2014-12-08  9:32     ` Marc Zyngier [this message]
2014-11-24 14:35 ` [PATCH v3 10/13] irqchip: GICv3: ITS: DT probing and initialization Marc Zyngier
2014-11-25 21:08   ` Stuart Yoder
2014-11-26 10:14     ` Marc Zyngier
2014-11-24 14:35 ` [PATCH v3 11/13] irqchip: GICv3: ITS: plug ITS init into main GICv3 code Marc Zyngier
2014-11-24 14:35 ` [PATCH v3 12/13] irqchip: GICv3: ITS: enable compilation of the ITS driver Marc Zyngier
2014-11-24 14:35 ` [PATCH v3 13/13] irqchip: GICv3: Binding updates for ITS Marc Zyngier
2014-11-26  8:06 ` [PATCH v3 00/13] arm64: PCI/MSI: GICv3 ITS support (stacked domain edition) Jason Cooper

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=54857028.2010707@arm.com \
    --to=marc.zyngier@arm.com \
    --cc=linux-arm-kernel@lists.infradead.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).