Re: [PATCH v2 1/5] iommu/virtio: Add definitions for VIRTIO_IOMMU_F_BYPASS_CONFIG

2021-11-26 Thread Eric Auger
Hi Jean,

On 11/23/21 4:52 PM, Jean-Philippe Brucker wrote:
> Add definitions for the VIRTIO_IOMMU_F_BYPASS_CONFIG, which supersedes
> VIRTIO_IOMMU_F_BYPASS.
>
> Reviewed-by: Kevin Tian 
> Signed-off-by: Jean-Philippe Brucker 
> ---
>  include/uapi/linux/virtio_iommu.h | 8 +++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/include/uapi/linux/virtio_iommu.h 
> b/include/uapi/linux/virtio_iommu.h
> index 237e36a280cb..cafd8cf7febf 100644
> --- a/include/uapi/linux/virtio_iommu.h
> +++ b/include/uapi/linux/virtio_iommu.h
> @@ -16,6 +16,7 @@
>  #define VIRTIO_IOMMU_F_BYPASS3
>  #define VIRTIO_IOMMU_F_PROBE 4
>  #define VIRTIO_IOMMU_F_MMIO  5
> +#define VIRTIO_IOMMU_F_BYPASS_CONFIG 6
>  
>  struct virtio_iommu_range_64 {
>   __le64  start;
> @@ -36,6 +37,8 @@ struct virtio_iommu_config {
>   struct virtio_iommu_range_32domain_range;
>   /* Probe buffer size */
>   __le32  probe_size;
> + __u8bypass;
> + __u8reserved[7];
in [PATCH v3] virtio-iommu: Rework the bypass feature I see

+  u8 bypass;
+  u8 reserved[3];

What was exactly voted?

Thanks

Eric

>  };
>  
>  /* Request types */
> @@ -66,11 +69,14 @@ struct virtio_iommu_req_tail {
>   __u8reserved[3];
>  };
>  
> +#define VIRTIO_IOMMU_ATTACH_F_BYPASS (1 << 0)
> +
>  struct virtio_iommu_req_attach {
>   struct virtio_iommu_req_headhead;
>   __le32  domain;
>   __le32  endpoint;
> - __u8reserved[8];
> + __le32  flags;
> + __u8reserved[4];
>   struct virtio_iommu_req_tailtail;
>  };
>  

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 2/2] iommu/mediatek: always check runtime PM status in tlb flush range callback

2021-11-26 Thread Yong Wu
On Mon, 2021-11-22 at 12:44 +0200, Dafna Hirschfeld wrote:
> From: Sebastian Reichel 
> 
> In case of v4l2_reqbufs() it is possible, that a TLB flush is done
> without runtime PM being enabled. In that case the "Partial TLB flush
> timed out, falling back to full flush" warning is printed.
> 
> Commit c0b57581b73b ("iommu/mediatek: Add power-domain operation")
> introduced has_pm as optimization to avoid checking runtime PM
> when there is no power domain attached. But without the PM domain
> there is still the device driver's runtime PM suspend handler, which
> disables the clock. Thus flushing should also be avoided when there
> is no PM domain involved.
> 
> Signed-off-by: Sebastian Reichel 
> Reviewed-by: Dafna Hirschfeld 

Reviewed-by: Yong Wu 

> ---
>  drivers/iommu/mtk_iommu.c | 10 +++---
>  1 file changed, 3 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 28dc4b95b6d9..b0535fcfd1d7 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -227,16 +227,13 @@ static void
> mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
>  size_t granule,
>  struct mtk_iommu_data *data)
>  {
> - bool has_pm = !!data->dev->pm_domain;
>   unsigned long flags;
>   int ret;
>   u32 tmp;
>  
>   for_each_m4u(data) {
> - if (has_pm) {
> - if (pm_runtime_get_if_in_use(data->dev) <= 0)
> - continue;
> - }
> + if (pm_runtime_get_if_in_use(data->dev) <= 0)
> + continue;
>  
>   spin_lock_irqsave(>tlb_lock, flags);
>   writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
> @@ -261,8 +258,7 @@ static void
> mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
>   writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
>   spin_unlock_irqrestore(>tlb_lock, flags);
>  
> - if (has_pm)
> - pm_runtime_put(data->dev);
> + pm_runtime_put(data->dev);
>   }
>  }
>  
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 1/2] iommu/mediatek: Always tlb_flush_all when each PM resume

2021-11-26 Thread Yong Wu
Hi Dafna,

Sorry for reply late.

On Mon, 2021-11-22 at 12:43 +0200, Dafna Hirschfeld wrote:
> From: Yong Wu 
> 
> Prepare for 2 HWs that sharing pgtable in different power-domains.
> 
> When there are 2 M4U HWs, it may has problem in the flush_range in
> which
> we get the pm_status via the m4u dev, BUT that function don't reflect
> the
> real power-domain status of the HW since there may be other HW also
> use
> that power-domain.
> 
> The function dma_alloc_attrs help allocate the iommu buffer which
> need the corresponding power domain since tlb flush is needed when
> preparing iova. BUT this function only is for allocating buffer,
> we have no good reason to request the user always call pm_runtime_get
> before calling dma_alloc_xxx. Therefore, we add a tlb_flush_all
> in the pm_runtime_resume to make sure the tlb always is clean.
> 
> Another solution is always call pm_runtime_get in the
> tlb_flush_range.
> This will trigger pm runtime resume/backup so often when the iommu
> power is not active at some time(means user don't call pm_runtime_get
> before calling dma_alloc_xxx), This may cause the performance drop.
> thus we don't use this.
> 
> In other case, the iommu's power should always be active via device
> link with smi.
> 
> The previous SoC don't have PM except mt8192. the mt8192 IOMMU is
> display's
> power-domain which nearly always is enabled. thus no need fix tags
> here.
> Prepare for mt8195.

In this patchset, this message should be not proper. I think you could
add the comment why this patch is needed in mt8173.

> 
> Signed-off-by: Yong Wu 
> [imporvie inline doc]
> Signed-off-by: Dafna Hirschfeld 
> ---
>  drivers/iommu/mtk_iommu.c | 7 +++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
> index 25b834104790..28dc4b95b6d9 100644
> --- a/drivers/iommu/mtk_iommu.c
> +++ b/drivers/iommu/mtk_iommu.c
> @@ -964,6 +964,13 @@ static int __maybe_unused
> mtk_iommu_runtime_resume(struct device *dev)
>   return ret;
>   }
>  
> + /*
> +  * Users may allocate dma buffer before they call
> pm_runtime_get,
> +  * in which case it will lack the necessary tlb flush.
> +  * Thus, make sure to update the tlb after each PM resume.
> +  */
> + mtk_iommu_tlb_flush_all(data);

This should not work. since current the *_tlb_flush_all call
pm_runtime_get_if_in_use which will always return 0 when it called from
this runtime_cb in my test. thus, It won't do the tlb_flush_all
actually.

I guess this also depend on these two patches of mt8195 v3.
[PATCH v3 09/33] iommu/mediatek: Remove for_each_m4u in tlb_sync_all
[PATCH v3 10/33] iommu/mediatek: Add tlb_lock in tlb_flush_all

like in [10/33], I added a mtk_iommu_tlb_do_flush_all which don't have
the pm operation.

This looks has a dependence. Let me know if I can help this.

> +
>   /*
>* Uppon first resume, only enable the clk and return, since
> the values of the
>* registers are not yet set.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v2 0/2] iommu/vt-d: Fixes for v5.16-rc3

2021-11-26 Thread Lu Baolu

On 11/27/21 5:57 AM, Joerg Roedel wrote:

On Fri, Nov 26, 2021 at 09:55:54PM +0800, Lu Baolu wrote:

Update this series with a fix for an issue reported by Intel 0-day
robot. Sorry for the inconvenience.


Replaced those with the previous fixes, thanks. Please just send a fix
on-top next time. This was already in the published fixes branch, which
I had to rebase now.


Sure.

Best regards,
baolu

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 37/37] dmaengine: qcom_hidma: Cleanup MSI handling

2021-11-26 Thread Thomas Gleixner
There is no reason to walk the MSI descriptors to retrieve the interrupt
number for a device. Use msi_get_virq() instead.

Signed-off-by: Thomas Gleixner 
Cc: Sinan Kaya 
Cc: dmaeng...@vger.kernel.org
---
 drivers/dma/qcom/hidma.c |   42 ++
 1 file changed, 18 insertions(+), 24 deletions(-)

--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -678,11 +678,13 @@ static void hidma_free_msis(struct hidma
 {
 #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
struct device *dev = dmadev->ddev.dev;
-   struct msi_desc *desc;
+   int i, virq;
 
-   /* free allocated MSI interrupts above */
-   for_each_msi_entry(desc, dev)
-   devm_free_irq(dev, desc->irq, >lldev);
+   for (i = 0; i < HIDMA_MSI_INTS; i++) {
+   virq = msi_get_virq(dev, i);
+   if (virq)
+   devm_free_irq(dev, virq, >lldev);
+   }
 
platform_msi_domain_free_irqs(dev);
 #endif
@@ -692,45 +694,37 @@ static int hidma_request_msi(struct hidm
 struct platform_device *pdev)
 {
 #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
-   int rc;
-   struct msi_desc *desc;
-   struct msi_desc *failed_desc = NULL;
+   int rc, i, virq;
 
rc = platform_msi_domain_alloc_irqs(>dev, HIDMA_MSI_INTS,
hidma_write_msi_msg);
if (rc)
return rc;
 
-   for_each_msi_entry(desc, >dev) {
-   if (!desc->msi_index)
-   dmadev->msi_virqbase = desc->irq;
-
-   rc = devm_request_irq(>dev, desc->irq,
+   for (i = 0; i < HIDMA_MSI_INTS; i++) {
+   virq = msi_get_virq(>dev, i);
+   rc = devm_request_irq(>dev, virq,
   hidma_chirq_handler_msi,
   0, "qcom-hidma-msi",
   >lldev);
-   if (rc) {
-   failed_desc = desc;
+   if (rc)
break;
-   }
+   if (!i)
+   dmadev->msi_virqbase = virq;
}
 
if (rc) {
/* free allocated MSI interrupts above */
-   for_each_msi_entry(desc, >dev) {
-   if (desc == failed_desc)
-   break;
-   devm_free_irq(>dev, desc->irq,
- >lldev);
+   for (--i; i >= 0; i--) {
+   virq = msi_get_virq(>dev, i);
+   devm_free_irq(>dev, virq, >lldev);
}
+   dev_warn(>dev,
+"failed to request MSI irq, falling back to wired 
IRQ\n");
} else {
/* Add callback to free MSIs on teardown */
hidma_ll_setup_irq(dmadev->lldev, true);
-
}
-   if (rc)
-   dev_warn(>dev,
-"failed to request MSI irq, falling back to wired 
IRQ\n");
return rc;
 #else
return -EINVAL;

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 36/37] soc: ti: ti_sci_inta_msi: Get rid of ti_sci_inta_msi_get_virq()

2021-11-26 Thread Thomas Gleixner
Just use the core function msi_get_virq().

Signed-off-by: Thomas Gleixner 
---
 drivers/dma/ti/k3-udma-private.c   |6 ++
 drivers/dma/ti/k3-udma.c   |   10 --
 drivers/soc/ti/k3-ringacc.c|2 +-
 drivers/soc/ti/ti_sci_inta_msi.c   |   12 
 include/linux/soc/ti/ti_sci_inta_msi.h |1 -
 5 files changed, 7 insertions(+), 24 deletions(-)

--- a/drivers/dma/ti/k3-udma-private.c
+++ b/drivers/dma/ti/k3-udma-private.c
@@ -168,8 +168,7 @@ int xudma_pktdma_tflow_get_irq(struct ud
 {
const struct udma_oes_offsets *oes = >soc_data->oes;
 
-   return ti_sci_inta_msi_get_virq(ud->dev, udma_tflow_id +
-   oes->pktdma_tchan_flow);
+   return msi_get_virq(ud->dev, udma_tflow_id + oes->pktdma_tchan_flow);
 }
 EXPORT_SYMBOL(xudma_pktdma_tflow_get_irq);
 
@@ -177,7 +176,6 @@ int xudma_pktdma_rflow_get_irq(struct ud
 {
const struct udma_oes_offsets *oes = >soc_data->oes;
 
-   return ti_sci_inta_msi_get_virq(ud->dev, udma_rflow_id +
-   oes->pktdma_rchan_flow);
+   return msi_get_virq(ud->dev, udma_rflow_id + oes->pktdma_rchan_flow);
 }
 EXPORT_SYMBOL(xudma_pktdma_rflow_get_irq);
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -2313,8 +2313,7 @@ static int udma_alloc_chan_resources(str
 
/* Event from UDMA (TR events) only needed for slave TR mode channels */
if (is_slave_direction(uc->config.dir) && !uc->config.pkt_mode) {
-   uc->irq_num_udma = ti_sci_inta_msi_get_virq(ud->dev,
-   irq_udma_idx);
+   uc->irq_num_udma = msi_get_virq(ud->dev, irq_udma_idx);
if (uc->irq_num_udma <= 0) {
dev_err(ud->dev, "Failed to get udma irq (index: %u)\n",
irq_udma_idx);
@@ -2486,7 +2485,7 @@ static int bcdma_alloc_chan_resources(st
uc->psil_paired = true;
}
 
-   uc->irq_num_ring = ti_sci_inta_msi_get_virq(ud->dev, irq_ring_idx);
+   uc->irq_num_ring = msi_get_virq(ud->dev, irq_ring_idx);
if (uc->irq_num_ring <= 0) {
dev_err(ud->dev, "Failed to get ring irq (index: %u)\n",
irq_ring_idx);
@@ -2503,8 +2502,7 @@ static int bcdma_alloc_chan_resources(st
 
/* Event from BCDMA (TR events) only needed for slave channels */
if (is_slave_direction(uc->config.dir)) {
-   uc->irq_num_udma = ti_sci_inta_msi_get_virq(ud->dev,
-   irq_udma_idx);
+   uc->irq_num_udma = msi_get_virq(ud->dev, irq_udma_idx);
if (uc->irq_num_udma <= 0) {
dev_err(ud->dev, "Failed to get bcdma irq (index: 
%u)\n",
irq_udma_idx);
@@ -2672,7 +2670,7 @@ static int pktdma_alloc_chan_resources(s
 
uc->psil_paired = true;
 
-   uc->irq_num_ring = ti_sci_inta_msi_get_virq(ud->dev, irq_ring_idx);
+   uc->irq_num_ring = msi_get_virq(ud->dev, irq_ring_idx);
if (uc->irq_num_ring <= 0) {
dev_err(ud->dev, "Failed to get ring irq (index: %u)\n",
irq_ring_idx);
--- a/drivers/soc/ti/k3-ringacc.c
+++ b/drivers/soc/ti/k3-ringacc.c
@@ -647,7 +647,7 @@ int k3_ringacc_get_ring_irq_num(struct k
if (!ring)
return -EINVAL;
 
-   irq_num = ti_sci_inta_msi_get_virq(ring->parent->dev, ring->ring_id);
+   irq_num = msi_get_virq(ring->parent->dev, ring->ring_id);
if (irq_num <= 0)
irq_num = -EINVAL;
return irq_num;
--- a/drivers/soc/ti/ti_sci_inta_msi.c
+++ b/drivers/soc/ti/ti_sci_inta_msi.c
@@ -148,15 +148,3 @@ void ti_sci_inta_msi_domain_free_irqs(st
ti_sci_inta_msi_free_descs(dev);
 }
 EXPORT_SYMBOL_GPL(ti_sci_inta_msi_domain_free_irqs);
-
-unsigned int ti_sci_inta_msi_get_virq(struct device *dev, u32 dev_index)
-{
-   struct msi_desc *desc;
-
-   for_each_msi_entry(desc, dev)
-   if (desc->msi_index == dev_index)
-   return desc->irq;
-
-   return -ENODEV;
-}
-EXPORT_SYMBOL_GPL(ti_sci_inta_msi_get_virq);
--- a/include/linux/soc/ti/ti_sci_inta_msi.h
+++ b/include/linux/soc/ti/ti_sci_inta_msi.h
@@ -18,6 +18,5 @@ struct irq_domain
   struct irq_domain *parent);
 int ti_sci_inta_msi_domain_alloc_irqs(struct device *dev,
  struct ti_sci_resource *res);
-unsigned int ti_sci_inta_msi_get_virq(struct device *dev, u32 index);
 void ti_sci_inta_msi_domain_free_irqs(struct device *dev);
 #endif /* __INCLUDE_LINUX_IRQCHIP_TI_SCI_INTA_H */

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 35/37] bus: fsl-mc: fsl-mc-allocator: Rework MSI handling

2021-11-26 Thread Thomas Gleixner
Storing a pointer to the MSI descriptor just to track the Linux interrupt
number is daft. Just store the interrupt number and be done with it.

Signed-off-by: Thomas Gleixner 
Cc: Stuart Yoder 
---
 drivers/bus/fsl-mc/dprc-driver.c|8 
 drivers/bus/fsl-mc/fsl-mc-allocator.c   |9 ++---
 drivers/bus/fsl-mc/fsl-mc-msi.c |6 +++---
 drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c|4 ++--
 drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c|4 +---
 drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c |5 ++---
 drivers/soc/fsl/dpio/dpio-driver.c  |8 
 drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c  |4 ++--
 include/linux/fsl/mc.h  |4 ++--
 9 files changed, 22 insertions(+), 30 deletions(-)

--- a/drivers/bus/fsl-mc/dprc-driver.c
+++ b/drivers/bus/fsl-mc/dprc-driver.c
@@ -400,7 +400,7 @@ static irqreturn_t dprc_irq0_handler_thr
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_dev);
struct fsl_mc_io *mc_io = mc_dev->mc_io;
-   struct msi_desc *msi_desc = mc_dev->irqs[0]->msi_desc;
+   int irq = mc_dev->irqs[0]->virq;
 
dev_dbg(dev, "DPRC IRQ %d triggered on CPU %u\n",
irq_num, smp_processor_id());
@@ -409,7 +409,7 @@ static irqreturn_t dprc_irq0_handler_thr
return IRQ_HANDLED;
 
mutex_lock(_bus->scan_mutex);
-   if (!msi_desc || msi_desc->irq != (u32)irq_num)
+   if (irq != (u32)irq_num)
goto out;
 
status = 0;
@@ -521,7 +521,7 @@ static int register_dprc_irq_handler(str
 * function that programs the MSI physically in the device
 */
error = devm_request_threaded_irq(_dev->dev,
- irq->msi_desc->irq,
+ irq->virq,
  dprc_irq0_handler,
  dprc_irq0_handler_thread,
  IRQF_NO_SUSPEND | IRQF_ONESHOT,
@@ -771,7 +771,7 @@ static void dprc_teardown_irq(struct fsl
 
(void)disable_dprc_irq(mc_dev);
 
-   devm_free_irq(_dev->dev, irq->msi_desc->irq, _dev->dev);
+   devm_free_irq(_dev->dev, irq->virq, _dev->dev);
 
fsl_mc_free_irqs(mc_dev);
 }
--- a/drivers/bus/fsl-mc/fsl-mc-allocator.c
+++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
@@ -350,7 +350,6 @@ int fsl_mc_populate_irq_pool(struct fsl_
 unsigned int irq_count)
 {
unsigned int i;
-   struct msi_desc *msi_desc;
struct fsl_mc_device_irq *irq_resources;
struct fsl_mc_device_irq *mc_dev_irq;
int error;
@@ -388,16 +387,12 @@ int fsl_mc_populate_irq_pool(struct fsl_
mc_dev_irq->resource.type = res_pool->type;
mc_dev_irq->resource.data = mc_dev_irq;
mc_dev_irq->resource.parent_pool = res_pool;
+   mc_dev_irq->virq = msi_get_virq(_bus_dev->dev, i);
+   mc_dev_irq->resource.id = mc_dev_irq->virq;
INIT_LIST_HEAD(_dev_irq->resource.node);
list_add_tail(_dev_irq->resource.node, _pool->free_list);
}
 
-   for_each_msi_entry(msi_desc, _bus_dev->dev) {
-   mc_dev_irq = _resources[msi_desc->msi_index];
-   mc_dev_irq->msi_desc = msi_desc;
-   mc_dev_irq->resource.id = msi_desc->irq;
-   }
-
res_pool->max_count = irq_count;
res_pool->free_count = irq_count;
mc_bus->irq_resources = irq_resources;
--- a/drivers/bus/fsl-mc/fsl-mc-msi.c
+++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
@@ -58,11 +58,11 @@ static void fsl_mc_msi_update_dom_ops(st
 }
 
 static void __fsl_mc_msi_write_msg(struct fsl_mc_device *mc_bus_dev,
-  struct fsl_mc_device_irq *mc_dev_irq)
+  struct fsl_mc_device_irq *mc_dev_irq,
+  struct msi_desc *msi_desc)
 {
int error;
struct fsl_mc_device *owner_mc_dev = mc_dev_irq->mc_dev;
-   struct msi_desc *msi_desc = mc_dev_irq->msi_desc;
struct dprc_irq_cfg irq_cfg;
 
/*
@@ -129,7 +129,7 @@ static void fsl_mc_msi_write_msg(struct
/*
 * Program the MSI (paddr, value) pair in the device:
 */
-   __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq);
+   __fsl_mc_msi_write_msg(mc_bus_dev, mc_dev_irq, msi_desc);
 }
 
 static void fsl_mc_msi_update_chip_ops(struct msi_domain_info *info)
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -4246,7 +4246,7 @@ static int dpaa2_eth_setup_irqs(struct f
}
 
irq = ls_dev->irqs[0];
-   err = devm_request_threaded_irq(_dev->dev, irq->msi_desc->irq,
+   err = devm_request_threaded_irq(_dev->dev, irq->virq,

[patch 34/37] mailbox: bcm-flexrm-mailbox: Rework MSI interrupt handling

2021-11-26 Thread Thomas Gleixner
No point in retrieving the MSI descriptors. Just query the Linux interrupt
number.

Signed-off-by: Thomas Gleixner 
---
 drivers/mailbox/bcm-flexrm-mailbox.c |7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

--- a/drivers/mailbox/bcm-flexrm-mailbox.c
+++ b/drivers/mailbox/bcm-flexrm-mailbox.c
@@ -1497,7 +1497,6 @@ static int flexrm_mbox_probe(struct plat
int index, ret = 0;
void __iomem *regs;
void __iomem *regs_end;
-   struct msi_desc *desc;
struct resource *iomem;
struct flexrm_ring *ring;
struct flexrm_mbox *mbox;
@@ -1608,10 +1607,8 @@ static int flexrm_mbox_probe(struct plat
goto fail_destroy_cmpl_pool;
 
/* Save alloced IRQ numbers for each ring */
-   for_each_msi_entry(desc, dev) {
-   ring = >rings[desc->msi_index];
-   ring->irq = desc->irq;
-   }
+   for (index = 0; index < mbox->num_rings; index++)
+   mbox->rings[index].irq = msi_get_virq(dev, index);
 
/* Check availability of debugfs */
if (!debugfs_initialized())

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 33/37] iommu/arm-smmu-v3: Use msi_get_virq()

2021-11-26 Thread Thomas Gleixner
Let the core code fiddle with the MSI descriptor retrieval.

Signed-off-by: Thomas Gleixner 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |   19 +++
 1 file changed, 3 insertions(+), 16 deletions(-)

--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3154,7 +3154,6 @@ static void arm_smmu_write_msi_msg(struc
 
 static void arm_smmu_setup_msis(struct arm_smmu_device *smmu)
 {
-   struct msi_desc *desc;
int ret, nvec = ARM_SMMU_MAX_MSIS;
struct device *dev = smmu->dev;
 
@@ -3182,21 +3181,9 @@ static void arm_smmu_setup_msis(struct a
return;
}
 
-   for_each_msi_entry(desc, dev) {
-   switch (desc->msi_index) {
-   case EVTQ_MSI_INDEX:
-   smmu->evtq.q.irq = desc->irq;
-   break;
-   case GERROR_MSI_INDEX:
-   smmu->gerr_irq = desc->irq;
-   break;
-   case PRIQ_MSI_INDEX:
-   smmu->priq.q.irq = desc->irq;
-   break;
-   default:/* Unknown */
-   continue;
-   }
-   }
+   smmu->evtq.q.irq = msi_get_virq(dev, EVTQ_MSI_INDEX);
+   smmu->gerr_irq = msi_get_virq(dev, GERROR_MSI_INDEX);
+   smmu->priq.q.irq = msi_get_virq(dev, PRIQ_MSI_INDEX);
 
/* Add callback to free MSIs on teardown */
devm_add_action(dev, arm_smmu_free_msis, dev);

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 31/37] dmaengine: mv_xor_v2: Get rid of msi_desc abuse

2021-11-26 Thread Thomas Gleixner
Storing a pointer to the MSI descriptor just to keep track of the Linux
interrupt number is daft. Use msi_get_virq() instead.

Signed-off-by: Thomas Gleixner 
Cc: dmaeng...@vger.kernel.org
Cc: Vinod Koul 
---
 drivers/dma/mv_xor_v2.c |   16 +---
 1 file changed, 5 insertions(+), 11 deletions(-)

--- a/drivers/dma/mv_xor_v2.c
+++ b/drivers/dma/mv_xor_v2.c
@@ -149,7 +149,7 @@ struct mv_xor_v2_descriptor {
  * @desc_size: HW descriptor size
  * @npendings: number of pending descriptors (for which tx_submit has
  * @hw_queue_idx: HW queue index
- * @msi_desc: local interrupt descriptor information
+ * @irq: The Linux interrupt number
  * been called, but not yet issue_pending)
  */
 struct mv_xor_v2_device {
@@ -168,7 +168,7 @@ struct mv_xor_v2_device {
int desc_size;
unsigned int npendings;
unsigned int hw_queue_idx;
-   struct msi_desc *msi_desc;
+   unsigned int irq;
 };
 
 /**
@@ -718,7 +718,6 @@ static int mv_xor_v2_probe(struct platfo
int i, ret = 0;
struct dma_device *dma_dev;
struct mv_xor_v2_sw_desc *sw_desc;
-   struct msi_desc *msi_desc;
 
BUILD_BUG_ON(sizeof(struct mv_xor_v2_descriptor) !=
 MV_XOR_V2_EXT_DESC_SIZE);
@@ -770,14 +769,9 @@ static int mv_xor_v2_probe(struct platfo
if (ret)
goto disable_clk;
 
-   msi_desc = first_msi_entry(>dev);
-   if (!msi_desc) {
-   ret = -ENODEV;
-   goto free_msi_irqs;
-   }
-   xor_dev->msi_desc = msi_desc;
+   xor_dev->irq = msi_get_virq(>dev, 0);
 
-   ret = devm_request_irq(>dev, msi_desc->irq,
+   ret = devm_request_irq(>dev, xor_dev->irq,
   mv_xor_v2_interrupt_handler, 0,
   dev_name(>dev), xor_dev);
if (ret)
@@ -892,7 +886,7 @@ static int mv_xor_v2_remove(struct platf
  xor_dev->desc_size * MV_XOR_V2_DESC_NUM,
  xor_dev->hw_desq_virt, xor_dev->hw_desq);
 
-   devm_free_irq(>dev, xor_dev->msi_desc->irq, xor_dev);
+   devm_free_irq(>dev, xor_dev->irq, xor_dev);
 
platform_msi_domain_free_irqs(>dev);
 

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 32/37] perf/smmuv3: Use msi_get_virq()

2021-11-26 Thread Thomas Gleixner
Let the core code fiddle with the MSI descriptor retrieval.

Signed-off-by: Thomas Gleixner 
Cc: Mark Rutland 
Cc: Will Deacon 
Cc: linux-arm-ker...@lists.infradead.org
---
 drivers/perf/arm_smmuv3_pmu.c |5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -684,7 +684,6 @@ static void smmu_pmu_write_msi_msg(struc
 
 static void smmu_pmu_setup_msi(struct smmu_pmu *pmu)
 {
-   struct msi_desc *desc;
struct device *dev = pmu->dev;
int ret;
 
@@ -701,9 +700,7 @@ static void smmu_pmu_setup_msi(struct sm
return;
}
 
-   desc = first_msi_entry(dev);
-   if (desc)
-   pmu->irq = desc->irq;
+   pmu->irq = msi_get_virq(dev, 0);
 
/* Add callback to free MSIs on teardown */
devm_add_action(dev, smmu_pmu_free_msis, dev);

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 30/37] PCI/MSI: Simplify pci_irq_get_affinity()

2021-11-26 Thread Thomas Gleixner
Replace open coded MSI descriptor chasing and use the proper accessor
functions instead.

Signed-off-by: Thomas Gleixner 
---
 drivers/pci/msi/msi.c |   26 ++
 1 file changed, 10 insertions(+), 16 deletions(-)

--- a/drivers/pci/msi/msi.c
+++ b/drivers/pci/msi/msi.c
@@ -1040,26 +1040,20 @@ EXPORT_SYMBOL(pci_irq_vector);
  */
 const struct cpumask *pci_irq_get_affinity(struct pci_dev *dev, int nr)
 {
-   if (dev->msix_enabled) {
-   struct msi_desc *entry;
+   int irq = pci_irq_vector(dev, nr);
+   struct msi_desc *desc;
 
-   for_each_pci_msi_entry(entry, dev) {
-   if (entry->msi_index == nr)
-   return >affinity->mask;
-   }
-   WARN_ON_ONCE(1);
+   if (WARN_ON_ONCE(irq <= 0))
return NULL;
-   } else if (dev->msi_enabled) {
-   struct msi_desc *entry = first_pci_msi_entry(dev);
 
-   if (WARN_ON_ONCE(!entry || !entry->affinity ||
-nr >= entry->nvec_used))
-   return NULL;
-
-   return >affinity[nr].mask;
-   } else {
+   desc = irq_get_msi_desc(irq);
+   /* Non-MSI does not have the information handy */
+   if (!desc)
return cpu_possible_mask;
-   }
+
+   if (WARN_ON_ONCE(!desc->affinity))
+   return NULL;
+   return >affinity[nr].mask;
 }
 EXPORT_SYMBOL(pci_irq_get_affinity);
 

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 29/37] PCI/MSI: Use __msi_get_virq() in pci_get_vector()

2021-11-26 Thread Thomas Gleixner
Use __msi_get_vector() and handle the return values to be compatible.

No functional change intended.

Signed-off-by: Thomas Gleixner 
---
 drivers/pci/msi/msi.c |   25 +
 1 file changed, 5 insertions(+), 20 deletions(-)

--- a/drivers/pci/msi/msi.c
+++ b/drivers/pci/msi/msi.c
@@ -1023,28 +1023,13 @@ EXPORT_SYMBOL(pci_free_irq_vectors);
  */
 int pci_irq_vector(struct pci_dev *dev, unsigned int nr)
 {
-   if (dev->msix_enabled) {
-   struct msi_desc *entry;
+   int irq = __msi_get_virq(>dev, nr);
 
-   for_each_pci_msi_entry(entry, dev) {
-   if (entry->msi_index == nr)
-   return entry->irq;
-   }
-   WARN_ON_ONCE(1);
-   return -EINVAL;
+   switch (irq) {
+   case -ENODEV: return !nr ? dev->irq : -EINVAL;
+   case -ENOENT: return -EINVAL;
}
-
-   if (dev->msi_enabled) {
-   struct msi_desc *entry = first_pci_msi_entry(dev);
-
-   if (WARN_ON_ONCE(nr >= entry->nvec_used))
-   return -EINVAL;
-   } else {
-   if (WARN_ON_ONCE(nr > 0))
-   return -EINVAL;
-   }
-
-   return dev->irq + nr;
+   return irq;
 }
 EXPORT_SYMBOL(pci_irq_vector);
 

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 28/37] genirq/msi: Provide interface to retrieve Linux interrupt number

2021-11-26 Thread Thomas Gleixner
This allows drivers to retrieve the Linux interrupt number instead of
fiddling with MSI descriptors.

msi_get_virq() returns the Linux interrupt number or 0, __msi_get_virq()
has more detailed return codes so pci_irq_vector() can use it as well.

Signed-off-by: Thomas Gleixner 
---
 include/linux/msi.h |   16 
 kernel/irq/msi.c|   38 ++
 2 files changed, 54 insertions(+)

--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -169,6 +169,22 @@ static inline bool msi_device_has_proper
 }
 #endif
 
+int __msi_get_virq(struct device *dev, unsigned int index);
+
+/**
+ * msi_get_virq - Return Linux interrupt number of a MSI interrupt
+ * @dev:   Device to operate on
+ * @index: MSI interrupt index to look for (0-based)
+ *
+ * Return: The Linux interrupt number on success (> 0), 0 if not found
+ */
+static inline unsigned int msi_get_virq(struct device *dev, unsigned int index)
+{
+   int ret = __msi_get_virq(dev, index);
+
+   return ret < 0 ? 0 : ret;
+}
+
 /* Helpers to hide struct msi_desc implementation details */
 #define msi_desc_to_dev(desc)  ((desc)->dev)
 #define dev_to_msi_list(dev)   (&(dev)->msi_list)
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -120,6 +120,44 @@ int msi_setup_device_data(struct device
return 0;
 }
 
+/**
+ * __msi_get_virq - Return Linux interrupt number of a MSI interrupt
+ * @dev:   Device to operate on
+ * @index: MSI interrupt index to look for (0-based)
+ *
+ * Return: The Linux interrupt number on success (> 0)
+ *-ENODEV when the device is not using MSI
+ *-ENOENT if no such entry exists
+ */
+int __msi_get_virq(struct device *dev, unsigned int index)
+{
+   struct msi_desc *desc;
+   bool pcimsi;
+
+   if (!dev->msi.data)
+   return -ENODEV;
+
+   pcimsi = msi_device_has_property(dev, MSI_PROP_PCI_MSI);
+
+   for_each_msi_entry(desc, dev) {
+   /* PCI-MSI has only one descriptor for multiple interrupts. */
+   if (pcimsi) {
+   if (desc->irq && index < desc->nvec_used)
+   return desc->irq + index;
+   break;
+   }
+
+   /*
+* PCI-MSIX and platform MSI use a descriptor per
+* interrupt.
+*/
+   if (desc->msi_index == index)
+   return desc->irq;
+   }
+   return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(__msi_get_virq);
+
 #ifdef CONFIG_SYSFS
 static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,
 char *buf)

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 27/37] powerpc/pseries/msi: Let core code check for contiguous entries

2021-11-26 Thread Thomas Gleixner
Set the domain info flag and remove the check.

Signed-off-by: Thomas Gleixner 
---
 arch/powerpc/platforms/pseries/msi.c |   32 +---
 1 file changed, 9 insertions(+), 23 deletions(-)

--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -321,27 +321,6 @@ static int msi_quota_for_device(struct p
return request;
 }
 
-static int check_msix_entries(struct pci_dev *pdev)
-{
-   struct msi_desc *entry;
-   int expected;
-
-   /* There's no way for us to express to firmware that we want
-* a discontiguous, or non-zero based, range of MSI-X entries.
-* So we must reject such requests. */
-
-   expected = 0;
-   for_each_pci_msi_entry(entry, pdev) {
-   if (entry->msi_index != expected) {
-   pr_debug("rtas_msi: bad MSI-X entries.\n");
-   return -EINVAL;
-   }
-   expected++;
-   }
-
-   return 0;
-}
-
 static void rtas_hack_32bit_msi_gen2(struct pci_dev *pdev)
 {
u32 addr_hi, addr_lo;
@@ -380,7 +359,7 @@ static int rtas_prepare_msi_irqs(struct
if (quota && quota < nvec)
return quota;
 
-   if (type == PCI_CAP_ID_MSIX && check_msix_entries(pdev))
+   if (type == PCI_CAP_ID_MSIX)
return -EINVAL;
 
/*
@@ -530,9 +509,16 @@ static struct irq_chip pseries_pci_msi_i
.irq_write_msi_msg  = pseries_msi_write_msg,
 };
 
+
+/*
+ * Set MSI_FLAG_MSIX_CONTIGUOUS as there is no way to express to
+ * firmware to request a discontiguous or non-zero based range of
+ * MSI-X entries. Core code will reject such setup attempts.
+ */
 static struct msi_domain_info pseries_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),
+ MSI_FLAG_MULTI_PCI_MSI  | MSI_FLAG_PCI_MSIX |
+ MSI_FLAG_MSIX_CONTIGUOUS),
.ops   = _pci_msi_domain_ops,
.chip  = _pci_msi_irq_chip,
 };

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 26/37] PCI/MSI: Provide MSI_FLAG_MSIX_CONTIGUOUS

2021-11-26 Thread Thomas Gleixner
Provide a domain info flag which makes the core code check for a contiguous
MSI-X index on allocation. That's simpler than checking it at some other
domain callback in architecture code.

Signed-off-by: Thomas Gleixner 
---
 drivers/pci/msi/irqdomain.c |   16 ++--
 include/linux/msi.h |2 ++
 2 files changed, 16 insertions(+), 2 deletions(-)

--- a/drivers/pci/msi/irqdomain.c
+++ b/drivers/pci/msi/irqdomain.c
@@ -89,9 +89,21 @@ static int pci_msi_domain_check_cap(stru
if (pci_msi_desc_is_multi_msi(desc) &&
!(info->flags & MSI_FLAG_MULTI_PCI_MSI))
return 1;
-   else if (desc->pci.msi_attrib.is_msix && !(info->flags & 
MSI_FLAG_PCI_MSIX))
-   return -ENOTSUPP;
 
+   if (desc->pci.msi_attrib.is_msix) {
+   if (!(info->flags & MSI_FLAG_PCI_MSIX))
+   return -ENOTSUPP;
+
+   if (info->flags & MSI_FLAG_MSIX_CONTIGUOUS) {
+   unsigned int idx = 0;
+
+   /* Check for gaps in the entry indices */
+   for_each_msi_entry(desc, dev) {
+   if (desc->msi_index != idx++)
+   return -ENOTSUPP;
+   }
+   }
+   }
return 0;
 }
 
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -378,6 +378,8 @@ enum {
MSI_FLAG_LEVEL_CAPABLE  = (1 << 6),
/* Populate sysfs on alloc() and destroy it on free() */
MSI_FLAG_DEV_SYSFS  = (1 << 7),
+   /* MSI-X entries must be contiguous */
+   MSI_FLAG_MSIX_CONTIGUOUS= (1 << 8),
 };
 
 int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 25/37] powerpc/pseries/msi: Use MSI device properties

2021-11-26 Thread Thomas Gleixner
instead of fiddling with MSI descriptors.

Signed-off-by: Thomas Gleixner 
---
 arch/powerpc/platforms/pseries/msi.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -447,9 +447,9 @@ static int rtas_prepare_msi_irqs(struct
 static int pseries_msi_ops_prepare(struct irq_domain *domain, struct device 
*dev,
   int nvec, msi_alloc_info_t *arg)
 {
+   bool is_msix = msi_device_has_property(dev, MSI_PROP_PCI_MSIX);
+   int type = is_msix ? PCI_CAP_ID_MSIX : PCI_CAP_ID_MSI;
struct pci_dev *pdev = to_pci_dev(dev);
-   struct msi_desc *desc = first_pci_msi_entry(pdev);
-   int type = desc->pci.msi_attrib.is_msix ? PCI_CAP_ID_MSIX : 
PCI_CAP_ID_MSI;
 
return rtas_prepare_msi_irqs(pdev, nvec, type, arg);
 }

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 24/37] powerpc/cell/axon_msi: Use MSI device properties

2021-11-26 Thread Thomas Gleixner
instead of fiddling with MSI descriptors.

Signed-off-by: Thomas Gleixner 
---
 arch/powerpc/platforms/cell/axon_msi.c |6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -199,7 +199,7 @@ static struct axon_msic *find_msi_transl
 static int setup_msi_msg_address(struct pci_dev *dev, struct msi_msg *msg)
 {
struct device_node *dn;
-   struct msi_desc *entry;
+   bool is_64bit;
int len;
const u32 *prop;
 
@@ -209,10 +209,10 @@ static int setup_msi_msg_address(struct
return -ENODEV;
}
 
-   entry = first_pci_msi_entry(dev);
+   is_64bit = msi_device_has_property(MSI_PROP_64BIT);
 
for (; dn; dn = of_get_next_parent(dn)) {
-   if (entry->pci.msi_attrib.is_64) {
+   if (is_64bit) {
prop = of_get_property(dn, "msi-address-64", );
if (prop)
break;

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 23/37] genirq/msi: Use device MSI properties

2021-11-26 Thread Thomas Gleixner
instead of fiddling with MSI descriptors.

Signed-off-by: Thomas Gleixner 
Cc: x...@kernel.org
---
 kernel/irq/msi.c |   17 ++---
 1 file changed, 2 insertions(+), 15 deletions(-)

--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -114,21 +114,8 @@ int msi_setup_device_data(struct device
 static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,
 char *buf)
 {
-   struct msi_desc *entry;
-   bool is_msix = false;
-   unsigned long irq;
-   int retval;
-
-   retval = kstrtoul(attr->attr.name, 10, );
-   if (retval)
-   return retval;
-
-   entry = irq_get_msi_desc(irq);
-   if (!entry)
-   return -ENODEV;
-
-   if (dev_is_pci(dev))
-   is_msix = entry->pci.msi_attrib.is_msix;
+   /* MSI vs. MSIX is per device not per interrupt */
+   bool is_msix = msi_device_has_property(dev, MSI_PROP_PCI_MSIX);
 
return sysfs_emit(buf, "%s\n", is_msix ? "msix" : "msi");
 }

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 22/37] x86/apic/msi: Use device MSI properties

2021-11-26 Thread Thomas Gleixner
instead of fiddling with MSI descriptors.

Signed-off-by: Thomas Gleixner 
---
 arch/x86/kernel/apic/msi.c |5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

--- a/arch/x86/kernel/apic/msi.c
+++ b/arch/x86/kernel/apic/msi.c
@@ -160,11 +160,8 @@ static struct irq_chip pci_msi_controlle
 int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec,
msi_alloc_info_t *arg)
 {
-   struct pci_dev *pdev = to_pci_dev(dev);
-   struct msi_desc *desc = first_pci_msi_entry(pdev);
-
init_irq_alloc_info(arg, NULL);
-   if (desc->pci.msi_attrib.is_msix) {
+   if (msi_device_has_property(dev, MSI_PROP_PCI_MSIX)) {
arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSIX;
} else {
arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSI;

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 21/37] x86/pci/XEN: Use device MSI properties

2021-11-26 Thread Thomas Gleixner
instead of fiddling with MSI descriptors.

Signed-off-by: Thomas Gleixner 
---
 arch/x86/pci/xen.c |6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -399,9 +399,7 @@ static void xen_teardown_msi_irqs(struct
 
 static void xen_pv_teardown_msi_irqs(struct pci_dev *dev)
 {
-   struct msi_desc *msidesc = first_pci_msi_entry(dev);
-
-   if (msidesc->pci.msi_attrib.is_msix)
+   if (msi_device_has_property(>dev, MSI_PROP_PCI_MSIX))
xen_pci_frontend_disable_msix(dev);
else
xen_pci_frontend_disable_msi(dev);
@@ -417,7 +415,7 @@ static int xen_msi_domain_alloc_irqs(str
if (WARN_ON_ONCE(!dev_is_pci(dev)))
return -EINVAL;
 
-   if (first_msi_entry(dev)->pci.msi_attrib.is_msix)
+   if (msi_device_has_property(dev, MSI_PROP_PCI_MSIX))
type = PCI_CAP_ID_MSIX;
else
type = PCI_CAP_ID_MSI;

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 20/37] PCI/MSI: Store properties in device::msi::data

2021-11-26 Thread Thomas Gleixner
Store the properties which are interesting for various places so the MSI
descriptor fiddling can be removed.

Signed-off-by: Thomas Gleixner 
---
 drivers/pci/msi/msi.c |6 ++
 1 file changed, 6 insertions(+)

--- a/drivers/pci/msi/msi.c
+++ b/drivers/pci/msi/msi.c
@@ -244,6 +244,8 @@ static void free_msi_irqs(struct pci_dev
iounmap(dev->msix_base);
dev->msix_base = NULL;
}
+
+   dev->dev.msi.data->properties = 0;
 }
 
 static void pci_intx_for_msi(struct pci_dev *dev, int enable)
@@ -372,6 +374,9 @@ msi_setup_entry(struct pci_dev *dev, int
if (entry->pci.msi_attrib.can_mask)
pci_read_config_dword(dev, entry->pci.mask_pos, 
>pci.msi_mask);
 
+   dev->dev.msi.data->properties = MSI_PROP_PCI_MSI;
+   if (entry->pci.msi_attrib.is_64)
+   dev->dev.msi.data->properties |= MSI_PROP_64BIT;
 out:
kfree(masks);
return entry;
@@ -514,6 +519,7 @@ static int msix_setup_entries(struct pci
if (masks)
curmsk++;
}
+   dev->dev.msi.data->properties = MSI_PROP_PCI_MSIX | MSI_PROP_64BIT;
ret = 0;
 out:
kfree(masks);

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 19/37] genirq/msi: Add msi_device_data::properties

2021-11-26 Thread Thomas Gleixner
Add a properties field which allows core code to store information for easy
retrieval in order to replace MSI descriptor fiddling.

Signed-off-by: Thomas Gleixner 
---
 include/linux/msi.h |   17 +
 kernel/irq/msi.c|   12 
 2 files changed, 29 insertions(+)

--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -4,6 +4,7 @@
 
 #include 
 #include 
+#include 
 #include 
 
 /* Dummy shadow structures if an architecture does not define them */
@@ -141,17 +142,33 @@ struct msi_desc {
 /**
  * msi_device_data - MSI per device data
  * @lock:  Spinlock to protect register access
+ * @properties:MSI properties which are interesting to drivers
  * @attrs: Pointer to the sysfs attribute group
  * @platform_data: Platform-MSI specific data
  */
 struct msi_device_data {
raw_spinlock_t  lock;
+   unsigned long   properties;
const struct attribute_group**attrs;
struct platform_msi_priv_data   *platform_data;
 };
 
 int msi_setup_device_data(struct device *dev);
 
+/* MSI device properties */
+#define MSI_PROP_PCI_MSI   BIT(0)
+#define MSI_PROP_PCI_MSIX  BIT(1)
+#define MSI_PROP_64BIT BIT(2)
+
+#ifdef CONFIG_GENERIC_MSI_IRQ
+bool msi_device_has_property(struct device *dev, unsigned long prop);
+#else
+static inline bool msi_device_has_property(struct device *dev, unsigned long 
prop)
+{
+   return false;
+}
+#endif
+
 /* Helpers to hide struct msi_desc implementation details */
 #define msi_desc_to_dev(desc)  ((desc)->dev)
 #define dev_to_msi_list(dev)   (&(dev)->msi_list)
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -60,6 +60,18 @@ void free_msi_entry(struct msi_desc *ent
kfree(entry);
 }
 
+/**
+ * msi_device_has_property - Check whether a device has a specific MSI property
+ * @dev:   Pointer to the device which is queried
+ * @prop:  Property to check for
+ */
+bool msi_device_has_property(struct device *dev, unsigned long prop)
+{
+   if (!dev->msi.data)
+   return false;
+   return !!(dev->msi.data->properties & prop);
+}
+
 void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
*msg = entry->msg;

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 18/37] PCI/MSI: Use msi_desc::msi_index

2021-11-26 Thread Thomas Gleixner
The usage of msi_desc::pci::entry_nr is confusing at best. It's the index
into the MSI[X] descriptor table.

Use msi_desc::msi_index which is shared between all MSI incarnations
instead of having a PCI specific storage for no value.

Signed-off-by: Thomas Gleixner 
---
 arch/powerpc/platforms/pseries/msi.c |4 ++--
 arch/x86/pci/xen.c   |2 +-
 drivers/pci/msi/irqdomain.c  |2 +-
 drivers/pci/msi/msi.c|   20 
 drivers/pci/xen-pcifront.c   |2 +-
 include/linux/msi.h  |2 --
 6 files changed, 13 insertions(+), 19 deletions(-)

--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -332,7 +332,7 @@ static int check_msix_entries(struct pci
 
expected = 0;
for_each_pci_msi_entry(entry, pdev) {
-   if (entry->pci.msi_attrib.entry_nr != expected) {
+   if (entry->msi_index != expected) {
pr_debug("rtas_msi: bad MSI-X entries.\n");
return -EINVAL;
}
@@ -580,7 +580,7 @@ static int pseries_irq_domain_alloc(stru
int hwirq;
int i, ret;
 
-   hwirq = rtas_query_irq_number(pci_get_pdn(pdev), 
desc->pci.msi_attrib.entry_nr);
+   hwirq = rtas_query_irq_number(pci_get_pdn(pdev), desc->msi_index);
if (hwirq < 0) {
dev_err(>dev, "Failed to query HW IRQ: %d\n", hwirq);
return hwirq;
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -306,7 +306,7 @@ static int xen_initdom_setup_msi_irqs(st
return -EINVAL;
 
map_irq.table_base = pci_resource_start(dev, bir);
-   map_irq.entry_nr = msidesc->pci.msi_attrib.entry_nr;
+   map_irq.entry_nr = msidesc->msi_index;
}
 
ret = -EINVAL;
--- a/drivers/pci/msi/irqdomain.c
+++ b/drivers/pci/msi/irqdomain.c
@@ -57,7 +57,7 @@ static irq_hw_number_t pci_msi_domain_ca
 {
struct pci_dev *dev = msi_desc_to_pci_dev(desc);
 
-   return (irq_hw_number_t)desc->pci.msi_attrib.entry_nr |
+   return (irq_hw_number_t)desc->msi_index |
pci_dev_id(dev) << 11 |
(pci_domain_nr(dev->bus) & 0x) << 27;
 }
--- a/drivers/pci/msi/msi.c
+++ b/drivers/pci/msi/msi.c
@@ -44,7 +44,7 @@ static inline void pci_msi_unmask(struct
 
 static inline void __iomem *pci_msix_desc_addr(struct msi_desc *desc)
 {
-   return desc->pci.mask_base + desc->pci.msi_attrib.entry_nr * 
PCI_MSIX_ENTRY_SIZE;
+   return desc->pci.mask_base + desc->msi_index * PCI_MSIX_ENTRY_SIZE;
 }
 
 /*
@@ -354,13 +354,10 @@ msi_setup_entry(struct pci_dev *dev, int
if (dev->dev_flags & PCI_DEV_FLAGS_HAS_MSI_MASKING)
control |= PCI_MSI_FLAGS_MASKBIT;
 
-   entry->pci.msi_attrib.is_msix   = 0;
-   entry->pci.msi_attrib.is_64 = !!(control & 
PCI_MSI_FLAGS_64BIT);
-   entry->pci.msi_attrib.is_virtual= 0;
-   entry->pci.msi_attrib.entry_nr  = 0;
+   entry->pci.msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT);
entry->pci.msi_attrib.can_mask  = !pci_msi_ignore_mask &&
  !!(control & PCI_MSI_FLAGS_MASKBIT);
-   entry->pci.msi_attrib.default_irq   = dev->irq; /* Save IOAPIC 
IRQ */
+   entry->pci.msi_attrib.default_irq = dev->irq;
entry->pci.msi_attrib.multi_cap = (control & PCI_MSI_FLAGS_QMASK) >> 1;
entry->pci.msi_attrib.multiple  = ilog2(__roundup_pow_of_two(nvec));
 
@@ -494,12 +491,11 @@ static int msix_setup_entries(struct pci
entry->pci.msi_attrib.is_64 = 1;
 
if (entries)
-   entry->pci.msi_attrib.entry_nr = entries[i].entry;
+   entry->msi_index = entries[i].entry;
else
-   entry->pci.msi_attrib.entry_nr = i;
+   entry->msi_index = i;
 
-   entry->pci.msi_attrib.is_virtual =
-   entry->pci.msi_attrib.entry_nr >= vec_count;
+   entry->pci.msi_attrib.is_virtual = entry->msi_index >= 
vec_count;
 
entry->pci.msi_attrib.can_mask  = !pci_msi_ignore_mask &&
  
!entry->pci.msi_attrib.is_virtual;
@@ -1025,7 +1021,7 @@ int pci_irq_vector(struct pci_dev *dev,
struct msi_desc *entry;
 
for_each_pci_msi_entry(entry, dev) {
-   if (entry->pci.msi_attrib.entry_nr == nr)
+   if (entry->msi_index == nr)
return entry->irq;
}
WARN_ON_ONCE(1);
@@ -1057,7 +1053,7 @@ const struct cpumask *pci_irq_get_affini
struct msi_desc *entry;
 
for_each_pci_msi_entry(entry, dev) {
-   if (entry->pci.msi_attrib.entry_nr == nr)
+

[patch 17/37] soc: ti: ti_sci_inta_msi: Use msi_desc::msi_index

2021-11-26 Thread Thomas Gleixner
Use the common msi_index member and get rid of the pointless wrapper struct.

Signed-off-by: Thomas Gleixner 
---
 drivers/irqchip/irq-ti-sci-inta.c |2 +-
 drivers/soc/ti/ti_sci_inta_msi.c  |6 +++---
 include/linux/msi.h   |   16 ++--
 3 files changed, 6 insertions(+), 18 deletions(-)

--- a/drivers/irqchip/irq-ti-sci-inta.c
+++ b/drivers/irqchip/irq-ti-sci-inta.c
@@ -595,7 +595,7 @@ static void ti_sci_inta_msi_set_desc(msi
struct platform_device *pdev = to_platform_device(desc->dev);
 
arg->desc = desc;
-   arg->hwirq = TO_HWIRQ(pdev->id, desc->inta.dev_index);
+   arg->hwirq = TO_HWIRQ(pdev->id, desc->msi_index);
 }
 
 static struct msi_domain_ops ti_sci_inta_msi_ops = {
--- a/drivers/soc/ti/ti_sci_inta_msi.c
+++ b/drivers/soc/ti/ti_sci_inta_msi.c
@@ -84,7 +84,7 @@ static int ti_sci_inta_msi_alloc_descs(s
return -ENOMEM;
}
 
-   msi_desc->inta.dev_index = res->desc[set].start + i;
+   msi_desc->msi_index = res->desc[set].start + i;
INIT_LIST_HEAD(_desc->list);
list_add_tail(_desc->list, dev_to_msi_list(dev));
count++;
@@ -96,7 +96,7 @@ static int ti_sci_inta_msi_alloc_descs(s
return -ENOMEM;
}
 
-   msi_desc->inta.dev_index = res->desc[set].start_sec + i;
+   msi_desc->msi_index = res->desc[set].start_sec + i;
INIT_LIST_HEAD(_desc->list);
list_add_tail(_desc->list, dev_to_msi_list(dev));
count++;
@@ -154,7 +154,7 @@ unsigned int ti_sci_inta_msi_get_virq(st
struct msi_desc *desc;
 
for_each_msi_entry(desc, dev)
-   if (desc->inta.dev_index == dev_index)
+   if (desc->msi_index == dev_index)
return desc->irq;
 
return -ENODEV;
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -106,14 +106,6 @@ struct pci_msi_desc {
 };
 
 /**
- * ti_sci_inta_msi_desc - TISCI based INTA specific msi descriptor data
- * @dev_index: TISCI device index
- */
-struct ti_sci_inta_msi_desc {
-   u16 dev_index;
-};
-
-/**
  * struct msi_desc - Descriptor structure for MSI based interrupts
  * @list:  List head for management
  * @irq:   The base interrupt number
@@ -127,8 +119,7 @@ struct ti_sci_inta_msi_desc {
  * @write_msi_msg_data:Data parameter for the callback.
  *
  * @msi_index: Index of the msi descriptor
- * @pci:   [PCI]   PCI speficic msi descriptor data
- * @inta:  [INTA]  TISCI based INTA specific msi descriptor data
+ * @pci:   PCI speficic msi descriptor data
  */
 struct msi_desc {
/* Shared device/bus type independent data */
@@ -146,10 +137,7 @@ struct msi_desc {
void *write_msi_msg_data;
 
u16 msi_index;
-   union {
-   struct pci_msi_desc pci;
-   struct ti_sci_inta_msi_desc inta;
-   };
+   struct pci_msi_desc pci;
 };
 
 /**

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 15/37] platform-msi: Use msi_desc::msi_index

2021-11-26 Thread Thomas Gleixner
Use the common msi_index member and get rid of the pointless wrapper struct.

Signed-off-by: Thomas Gleixner 
Cc: linux-arm-ker...@lists.infradead.org
Cc: iommu@lists.linux-foundation.org
Cc: dmaeng...@vger.kernel.org
---
 drivers/base/platform-msi.c |   10 +-
 drivers/dma/qcom/hidma.c|4 ++--
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |4 ++--
 drivers/mailbox/bcm-flexrm-mailbox.c|4 ++--
 include/linux/msi.h |   10 --
 5 files changed, 11 insertions(+), 21 deletions(-)

--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -40,7 +40,7 @@ static irq_hw_number_t platform_msi_calc
 {
u32 devid = desc->dev->msi.data->platform_data->devid;
 
-   return (devid << (32 - DEV_ID_SHIFT)) | desc->platform.msi_index;
+   return (devid << (32 - DEV_ID_SHIFT)) | desc->msi_index;
 }
 
 static void platform_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
@@ -112,8 +112,8 @@ static void platform_msi_free_descs(stru
struct msi_desc *desc, *tmp;
 
list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
-   if (desc->platform.msi_index >= base &&
-   desc->platform.msi_index < (base + nvec)) {
+   if (desc->msi_index >= base &&
+   desc->msi_index < (base + nvec)) {
list_del(>list);
free_msi_entry(desc);
}
@@ -129,7 +129,7 @@ static int platform_msi_alloc_descs_with
if (!list_empty(dev_to_msi_list(dev))) {
desc = list_last_entry(dev_to_msi_list(dev),
   struct msi_desc, list);
-   base = desc->platform.msi_index + 1;
+   base = desc->msi_index + 1;
}
 
for (i = 0; i < nvec; i++) {
@@ -137,7 +137,7 @@ static int platform_msi_alloc_descs_with
if (!desc)
break;
 
-   desc->platform.msi_index = base + i;
+   desc->msi_index = base + i;
desc->irq = virq ? virq + i : 0;
 
list_add_tail(>list, dev_to_msi_list(dev));
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -666,7 +666,7 @@ static void hidma_write_msi_msg(struct m
struct device *dev = msi_desc_to_dev(desc);
struct hidma_dev *dmadev = dev_get_drvdata(dev);
 
-   if (!desc->platform.msi_index) {
+   if (!desc->msi_index) {
writel(msg->address_lo, dmadev->dev_evca + 0x118);
writel(msg->address_hi, dmadev->dev_evca + 0x11C);
writel(msg->data, dmadev->dev_evca + 0x120);
@@ -702,7 +702,7 @@ static int hidma_request_msi(struct hidm
return rc;
 
for_each_msi_entry(desc, >dev) {
-   if (!desc->platform.msi_index)
+   if (!desc->msi_index)
dmadev->msi_virqbase = desc->irq;
 
rc = devm_request_irq(>dev, desc->irq,
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3142,7 +3142,7 @@ static void arm_smmu_write_msi_msg(struc
phys_addr_t doorbell;
struct device *dev = msi_desc_to_dev(desc);
struct arm_smmu_device *smmu = dev_get_drvdata(dev);
-   phys_addr_t *cfg = arm_smmu_msi_cfg[desc->platform.msi_index];
+   phys_addr_t *cfg = arm_smmu_msi_cfg[desc->msi_index];
 
doorbell = (((u64)msg->address_hi) << 32) | msg->address_lo;
doorbell &= MSI_CFG0_ADDR_MASK;
@@ -3183,7 +3183,7 @@ static void arm_smmu_setup_msis(struct a
}
 
for_each_msi_entry(desc, dev) {
-   switch (desc->platform.msi_index) {
+   switch (desc->msi_index) {
case EVTQ_MSI_INDEX:
smmu->evtq.q.irq = desc->irq;
break;
--- a/drivers/mailbox/bcm-flexrm-mailbox.c
+++ b/drivers/mailbox/bcm-flexrm-mailbox.c
@@ -1484,7 +1484,7 @@ static void flexrm_mbox_msi_write(struct
 {
struct device *dev = msi_desc_to_dev(desc);
struct flexrm_mbox *mbox = dev_get_drvdata(dev);
-   struct flexrm_ring *ring = >rings[desc->platform.msi_index];
+   struct flexrm_ring *ring = >rings[desc->msi_index];
 
/* Configure per-Ring MSI registers */
writel_relaxed(msg->address_lo, ring->regs + RING_MSI_ADDR_LS);
@@ -1609,7 +1609,7 @@ static int flexrm_mbox_probe(struct plat
 
/* Save alloced IRQ numbers for each ring */
for_each_msi_entry(desc, dev) {
-   ring = >rings[desc->platform.msi_index];
+   ring = >rings[desc->msi_index];
ring->irq = desc->irq;
}
 
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -106,14 +106,6 @@ struct pci_msi_desc {
 };
 
 /**
- * platform_msi_desc - Platform device specific msi descriptor data
- * @msi_index: The index of the MSI descriptor for multi MSI
- */

[patch 16/37] bus: fsl-mc-msi: Use msi_desc::msi_index

2021-11-26 Thread Thomas Gleixner
Use the common msi_index member and get rid of the pointless wrapper struct.

Signed-off-by: Thomas Gleixner 
---
 drivers/bus/fsl-mc/fsl-mc-allocator.c |2 +-
 drivers/bus/fsl-mc/fsl-mc-msi.c   |6 +++---
 include/linux/msi.h   |   10 --
 3 files changed, 4 insertions(+), 14 deletions(-)

--- a/drivers/bus/fsl-mc/fsl-mc-allocator.c
+++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
@@ -393,7 +393,7 @@ int fsl_mc_populate_irq_pool(struct fsl_
}
 
for_each_msi_entry(msi_desc, _bus_dev->dev) {
-   mc_dev_irq = _resources[msi_desc->fsl_mc.msi_index];
+   mc_dev_irq = _resources[msi_desc->msi_index];
mc_dev_irq->msi_desc = msi_desc;
mc_dev_irq->resource.id = msi_desc->irq;
}
--- a/drivers/bus/fsl-mc/fsl-mc-msi.c
+++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
@@ -29,7 +29,7 @@ static irq_hw_number_t fsl_mc_domain_cal
 * Make the base hwirq value for ICID*1 so it is readable
 * as a decimal value in /proc/interrupts.
 */
-   return (irq_hw_number_t)(desc->fsl_mc.msi_index + (dev->icid * 1));
+   return (irq_hw_number_t)(desc->msi_index + (dev->icid * 1));
 }
 
 static void fsl_mc_msi_set_desc(msi_alloc_info_t *arg,
@@ -122,7 +122,7 @@ static void fsl_mc_msi_write_msg(struct
struct fsl_mc_device *mc_bus_dev = to_fsl_mc_device(msi_desc->dev);
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
struct fsl_mc_device_irq *mc_dev_irq =
-   _bus->irq_resources[msi_desc->fsl_mc.msi_index];
+   _bus->irq_resources[msi_desc->msi_index];
 
msi_desc->msg = *msg;
 
@@ -235,7 +235,7 @@ static int fsl_mc_msi_alloc_descs(struct
goto cleanup_msi_descs;
}
 
-   msi_desc->fsl_mc.msi_index = i;
+   msi_desc->msi_index = i;
INIT_LIST_HEAD(_desc->list);
list_add_tail(_desc->list, dev_to_msi_list(dev));
}
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -106,14 +106,6 @@ struct pci_msi_desc {
 };
 
 /**
- * fsl_mc_msi_desc - FSL-MC device specific msi descriptor data
- * @msi_index: The index of the MSI descriptor
- */
-struct fsl_mc_msi_desc {
-   u16 msi_index;
-};
-
-/**
  * ti_sci_inta_msi_desc - TISCI based INTA specific msi descriptor data
  * @dev_index: TISCI device index
  */
@@ -136,7 +128,6 @@ struct ti_sci_inta_msi_desc {
  *
  * @msi_index: Index of the msi descriptor
  * @pci:   [PCI]   PCI speficic msi descriptor data
- * @fsl_mc:[fsl-mc]FSL MC device specific msi descriptor data
  * @inta:  [INTA]  TISCI based INTA specific msi descriptor data
  */
 struct msi_desc {
@@ -157,7 +148,6 @@ struct msi_desc {
u16 msi_index;
union {
struct pci_msi_desc pci;
-   struct fsl_mc_msi_desc  fsl_mc;
struct ti_sci_inta_msi_desc inta;
};
 };

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 14/37] genirq/msi: Consolidate MSI descriptor data

2021-11-26 Thread Thomas Gleixner
All non PCI/MSI usage variants have data structures in struct msi_desc with
only one member: xxx_index. PCI/MSI has a entry_nr member.

Add a common msi_index member to struct msi_desc so all implementations can
share it which allows further consolidation.

Signed-off-by: Thomas Gleixner 
---
 include/linux/msi.h |2 ++
 1 file changed, 2 insertions(+)

--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -142,6 +142,7 @@ struct ti_sci_inta_msi_desc {
  * address or data changes
  * @write_msi_msg_data:Data parameter for the callback.
  *
+ * @msi_index: Index of the msi descriptor
  * @pci:   [PCI]   PCI speficic msi descriptor data
  * @platform:  [platform]  Platform device specific msi descriptor data
  * @fsl_mc:[fsl-mc]FSL MC device specific msi descriptor data
@@ -162,6 +163,7 @@ struct msi_desc {
void (*write_msi_msg)(struct msi_desc *entry, void *data);
void *write_msi_msg_data;
 
+   u16 msi_index;
union {
struct pci_msi_desc pci;
struct platform_msi_descplatform;

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 13/37] platform-msi: Store platform private data pointer in msi_device_data

2021-11-26 Thread Thomas Gleixner
Storing the platform private data in a MSI descriptor is sloppy at
best. The data belongs to the device and not to the descriptor.
Add a pointer to struct msi_device_data and store the pointer there.

Signed-off-by: Thomas Gleixner 
---
 drivers/base/platform-msi.c |   79 +---
 include/linux/msi.h |5 +-
 2 files changed, 35 insertions(+), 49 deletions(-)

--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -38,9 +38,7 @@ static DEFINE_IDA(platform_msi_devid_ida
  */
 static irq_hw_number_t platform_msi_calc_hwirq(struct msi_desc *desc)
 {
-   u32 devid;
-
-   devid = desc->platform.msi_priv_data->devid;
+   u32 devid = desc->dev->msi.data->platform_data->devid;
 
return (devid << (32 - DEV_ID_SHIFT)) | desc->platform.msi_index;
 }
@@ -85,11 +83,8 @@ static void platform_msi_update_dom_ops(
 static void platform_msi_write_msg(struct irq_data *data, struct msi_msg *msg)
 {
struct msi_desc *desc = irq_data_get_msi_desc(data);
-   struct platform_msi_priv_data *priv_data;
-
-   priv_data = desc->platform.msi_priv_data;
 
-   priv_data->write_msg(desc, msg);
+   desc->dev->msi.data->platform_data->write_msg(desc, msg);
 }
 
 static void platform_msi_update_chip_ops(struct msi_domain_info *info)
@@ -126,9 +121,7 @@ static void platform_msi_free_descs(stru
 }
 
 static int platform_msi_alloc_descs_with_irq(struct device *dev, int virq,
-int nvec,
-struct platform_msi_priv_data 
*data)
-
+int nvec)
 {
struct msi_desc *desc;
int i, base = 0;
@@ -144,7 +137,6 @@ static int platform_msi_alloc_descs_with
if (!desc)
break;
 
-   desc->platform.msi_priv_data = data;
desc->platform.msi_index = base + i;
desc->irq = virq ? virq + i : 0;
 
@@ -161,11 +153,9 @@ static int platform_msi_alloc_descs_with
return 0;
 }
 
-static int platform_msi_alloc_descs(struct device *dev, int nvec,
-   struct platform_msi_priv_data *data)
-
+static int platform_msi_alloc_descs(struct device *dev, int nvec)
 {
-   return platform_msi_alloc_descs_with_irq(dev, 0, nvec, data);
+   return platform_msi_alloc_descs_with_irq(dev, 0, nvec);
 }
 
 /**
@@ -199,9 +189,8 @@ struct irq_domain *platform_msi_create_i
return domain;
 }
 
-static struct platform_msi_priv_data *
-platform_msi_alloc_priv_data(struct device *dev, unsigned int nvec,
-irq_write_msi_msg_t write_msi_msg)
+static int platform_msi_alloc_priv_data(struct device *dev, unsigned int nvec,
+   irq_write_msi_msg_t write_msi_msg)
 {
struct platform_msi_priv_data *datap;
int err;
@@ -213,41 +202,44 @@ platform_msi_alloc_priv_data(struct devi
 * capable devices).
 */
if (!dev->msi.domain || !write_msi_msg || !nvec || nvec > MAX_DEV_MSIS)
-   return ERR_PTR(-EINVAL);
+   return -EINVAL;
 
if (dev->msi.domain->bus_token != DOMAIN_BUS_PLATFORM_MSI) {
dev_err(dev, "Incompatible msi_domain, giving up\n");
-   return ERR_PTR(-EINVAL);
+   return -EINVAL;
}
 
err = msi_setup_device_data(dev);
if (err)
-   return ERR_PTR(err);
+   return err;
 
-   /* Already had a helping of MSI? Greed... */
-   if (!list_empty(dev_to_msi_list(dev)))
-   return ERR_PTR(-EBUSY);
+   /* Already initialized? */
+   if (dev->msi.data->platform_data)
+   return -EBUSY;
 
datap = kzalloc(sizeof(*datap), GFP_KERNEL);
if (!datap)
-   return ERR_PTR(-ENOMEM);
+   return -ENOMEM;
 
datap->devid = ida_simple_get(_msi_devid_ida,
  0, 1 << DEV_ID_SHIFT, GFP_KERNEL);
if (datap->devid < 0) {
err = datap->devid;
kfree(datap);
-   return ERR_PTR(err);
+   return err;
}
 
datap->write_msg = write_msi_msg;
datap->dev = dev;
-
-   return datap;
+   dev->msi.data->platform_data = datap;
+   return 0;
 }
 
-static void platform_msi_free_priv_data(struct platform_msi_priv_data *data)
+static void platform_msi_free_priv_data(struct device *dev)
 {
+   struct platform_msi_priv_data *data = dev->msi.data->platform_data;
+
+   dev->msi.data->platform_data = NULL;
ida_simple_remove(_msi_devid_ida, data->devid);
kfree(data);
 }
@@ -264,14 +256,13 @@ static void platform_msi_free_priv_data(
 int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
   irq_write_msi_msg_t write_msi_msg)
 {
-   struct platform_msi_priv_data *priv_data;
 

[patch 12/37] platform-msi: Rename functions and clarify comments

2021-11-26 Thread Thomas Gleixner
It's hard to distinguish what platform_msi_domain_alloc() and
platform_msi_domain_alloc_irqs() are about. Make the distinction more
explicit and add comments which explain the use cases properly.

Signed-off-by: Thomas Gleixner 
---
 drivers/base/platform-msi.c |   36 +---
 drivers/irqchip/irq-mbigen.c|4 ++--
 drivers/irqchip/irq-mvebu-icu.c |6 +++---
 include/linux/msi.h |8 
 4 files changed, 30 insertions(+), 24 deletions(-)

--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -313,17 +313,18 @@ EXPORT_SYMBOL_GPL(platform_msi_domain_fr
  *  a platform-msi domain
  * @domain:The platform-msi domain
  *
- * Returns the private data provided when calling
- * platform_msi_create_device_domain.
+ * Return: The private data provided when calling
+ * platform_msi_create_device_domain().
  */
 void *platform_msi_get_host_data(struct irq_domain *domain)
 {
struct platform_msi_priv_data *data = domain->host_data;
+
return data->host_data;
 }
 
 /**
- * __platform_msi_create_device_domain - Create a platform-msi domain
+ * __platform_msi_create_device_domain - Create a platform-msi device domain
  *
  * @dev:   The device generating the MSIs
  * @nvec:  The number of MSIs that need to be allocated
@@ -332,7 +333,11 @@ void *platform_msi_get_host_data(struct
  * @ops:   The hierarchy domain operations to use
  * @host_data: Private data associated to this domain
  *
- * Returns an irqdomain for @nvec interrupts
+ * Return: An irqdomain for @nvec interrupts on success, NULL in case of error.
+ *
+ * This is for interrupt domains which stack on a platform-msi domain
+ * created by platform_msi_create_irq_domain(). @dev->msi.domain points to
+ * that platform-msi domain which is the parent for the new domain.
  */
 struct irq_domain *
 __platform_msi_create_device_domain(struct device *dev,
@@ -372,18 +377,19 @@ struct irq_domain *
 }
 
 /**
- * platform_msi_domain_free - Free interrupts associated with a platform-msi
- *domain
+ * platform_msi_device_domain_free - Free interrupts associated with a 
platform-msi
+ *  device domain
  *
- * @domain:The platform-msi domain
+ * @domain:The platform-msi device domain
  * @virq:  The base irq from which to perform the free operation
  * @nvec:  How many interrupts to free from @virq
  */
-void platform_msi_domain_free(struct irq_domain *domain, unsigned int virq,
- unsigned int nvec)
+void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int 
virq,
+unsigned int nvec)
 {
struct platform_msi_priv_data *data = domain->host_data;
struct msi_desc *desc, *tmp;
+
for_each_msi_entry_safe(desc, tmp, data->dev) {
if (WARN_ON(!desc->irq || desc->nvec_used != 1))
return;
@@ -397,10 +403,10 @@ void platform_msi_domain_free(struct irq
 }
 
 /**
- * platform_msi_domain_alloc - Allocate interrupts associated with
- *a platform-msi domain
+ * platform_msi_device_domain_alloc - Allocate interrupts associated with
+ *   a platform-msi device domain
  *
- * @domain:The platform-msi domain
+ * @domain:The platform-msi device domain
  * @virq:  The base irq from which to perform the allocate operation
  * @nr_irqs:   How many interrupts to free from @virq
  *
@@ -408,8 +414,8 @@ void platform_msi_domain_free(struct irq
  * with irq_domain_mutex held (which can only be done as part of a
  * top-level interrupt allocation).
  */
-int platform_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
- unsigned int nr_irqs)
+int platform_msi_device_domain_alloc(struct irq_domain *domain, unsigned int 
virq,
+unsigned int nr_irqs)
 {
struct platform_msi_priv_data *data = domain->host_data;
int err;
@@ -421,7 +427,7 @@ int platform_msi_domain_alloc(struct irq
err = msi_domain_populate_irqs(domain->parent, data->dev,
   virq, nr_irqs, >arg);
if (err)
-   platform_msi_domain_free(domain, virq, nr_irqs);
+   platform_msi_device_domain_free(domain, virq, nr_irqs);
 
return err;
 }
--- a/drivers/irqchip/irq-mbigen.c
+++ b/drivers/irqchip/irq-mbigen.c
@@ -207,7 +207,7 @@ static int mbigen_irq_domain_alloc(struc
if (err)
return err;
 
-   err = platform_msi_domain_alloc(domain, virq, nr_irqs);
+   err = platform_msi_device_domain_alloc(domain, virq, nr_irqs);
if (err)
return err;
 
@@ -223,7 +223,7 @@ static int mbigen_irq_domain_alloc(struc
 static void mbigen_irq_domain_free(struct irq_domain *domain, unsigned int 

[patch 11/37] genirq/msi: Remove the original sysfs interfaces

2021-11-26 Thread Thomas Gleixner
No more users. Refactor the core code accordingly.

Signed-off-by: Thomas Gleixner 
---
 include/linux/msi.h |   12 ---
 kernel/irq/msi.c|   53 +++-
 2 files changed, 20 insertions(+), 45 deletions(-)

--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -246,21 +246,9 @@ void pci_msi_unmask_irq(struct irq_data
 #ifdef CONFIG_SYSFS
 int msi_device_populate_sysfs(struct device *dev);
 void msi_device_destroy_sysfs(struct device *dev);
-
-const struct attribute_group **msi_populate_sysfs(struct device *dev);
-void msi_destroy_sysfs(struct device *dev,
-  const struct attribute_group **msi_irq_groups);
 #else
 static inline int msi_device_populate_sysfs(struct device *dev) { return 0; }
 static inline void msi_device_destroy_sysfs(struct device *dev) { }
-
-static inline const struct attribute_group **msi_populate_sysfs(struct device 
*dev)
-{
-   return NULL;
-}
-static inline void msi_destroy_sysfs(struct device *dev, const struct 
attribute_group **msi_irq_groups)
-{
-}
 #endif
 
 /*
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -132,12 +132,8 @@ static ssize_t msi_mode_show(struct devi
 /**
  * msi_populate_sysfs - Populate msi_irqs sysfs entries for devices
  * @dev:   The device(PCI, platform etc) who will get sysfs entries
- *
- * Return attribute_group ** so that specific bus MSI can save it to
- * somewhere during initilizing msi irqs. If devices has no MSI irq,
- * return NULL; if it fails to populate sysfs, return ERR_PTR
  */
-const struct attribute_group **msi_populate_sysfs(struct device *dev)
+static const struct attribute_group **msi_populate_sysfs(struct device *dev)
 {
const struct attribute_group **msi_irq_groups;
struct attribute **msi_attrs, *msi_attr;
@@ -228,41 +224,32 @@ int msi_device_populate_sysfs(struct dev
 }
 
 /**
- * msi_destroy_sysfs - Destroy msi_irqs sysfs entries for devices
- * @dev:   The device(PCI, platform etc) who will remove sysfs 
entries
- * @msi_irq_groups:attribute_group for device msi_irqs entries
- */
-void msi_destroy_sysfs(struct device *dev, const struct attribute_group 
**msi_irq_groups)
-{
-   struct device_attribute *dev_attr;
-   struct attribute **msi_attrs;
-   int count = 0;
-
-   if (msi_irq_groups) {
-   sysfs_remove_groups(>kobj, msi_irq_groups);
-   msi_attrs = msi_irq_groups[0]->attrs;
-   while (msi_attrs[count]) {
-   dev_attr = container_of(msi_attrs[count],
-   struct device_attribute, attr);
-   kfree(dev_attr->attr.name);
-   kfree(dev_attr);
-   ++count;
-   }
-   kfree(msi_attrs);
-   kfree(msi_irq_groups[0]);
-   kfree(msi_irq_groups);
-   }
-}
-
-/**
  * msi_device_destroy_sysfs - Destroy msi_irqs sysfs entries for a device
  * @dev:   The device(PCI, platform etc) for which to remove
  * sysfs entries
  */
 void msi_device_destroy_sysfs(struct device *dev)
 {
-   msi_destroy_sysfs(dev, dev->msi.data->attrs);
+   const struct attribute_group **msi_irq_groups = dev->msi.data->attrs;
+   struct device_attribute *dev_attr;
+   struct attribute **msi_attrs;
+   int count = 0;
+
dev->msi.data->attrs = NULL;
+   if (!msi_irq_groups)
+   return;
+
+   sysfs_remove_groups(>kobj, msi_irq_groups);
+   msi_attrs = msi_irq_groups[0]->attrs;
+   while (msi_attrs[count]) {
+   dev_attr = container_of(msi_attrs[count], struct 
device_attribute, attr);
+   kfree(dev_attr->attr.name);
+   kfree(dev_attr);
+   ++count;
+   }
+   kfree(msi_attrs);
+   kfree(msi_irq_groups[0]);
+   kfree(msi_irq_groups);
 }
 #endif
 

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 10/37] platform-msi: Let the core code handle sysfs groups

2021-11-26 Thread Thomas Gleixner
Set the domain info flag and remove the local sysfs code.

Signed-off-by: Thomas Gleixner 
---
 drivers/base/platform-msi.c |   11 +--
 1 file changed, 1 insertion(+), 10 deletions(-)

--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -23,7 +23,6 @@
 struct platform_msi_priv_data {
struct device   *dev;
void*host_data;
-   const struct attribute_group**msi_irq_groups;
msi_alloc_info_targ;
irq_write_msi_msg_t write_msg;
int devid;
@@ -191,6 +190,7 @@ struct irq_domain *platform_msi_create_i
platform_msi_update_dom_ops(info);
if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
platform_msi_update_chip_ops(info);
+   info->flags |= MSI_FLAG_DEV_SYSFS;
 
domain = msi_create_irq_domain(fwnode, info, parent);
if (domain)
@@ -279,16 +279,8 @@ int platform_msi_domain_alloc_irqs(struc
if (err)
goto out_free_desc;
 
-   priv_data->msi_irq_groups = msi_populate_sysfs(dev);
-   if (IS_ERR(priv_data->msi_irq_groups)) {
-   err = PTR_ERR(priv_data->msi_irq_groups);
-   goto out_free_irqs;
-   }
-
return 0;
 
-out_free_irqs:
-   msi_domain_free_irqs(dev->msi.domain, dev);
 out_free_desc:
platform_msi_free_descs(dev, 0, nvec);
 out_free_priv_data:
@@ -308,7 +300,6 @@ void platform_msi_domain_free_irqs(struc
struct msi_desc *desc;
 
desc = first_msi_entry(dev);
-   msi_destroy_sysfs(dev, 
desc->platform.msi_priv_data->msi_irq_groups);
platform_msi_free_priv_data(desc->platform.msi_priv_data);
}
 

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 09/37] PCI/MSI: Let the irq code handle sysfs groups

2021-11-26 Thread Thomas Gleixner
Set the domain info flag which makes the core code handle sysfs groups and
put an explicit invocation into the legacy code.

Signed-off-by: Thomas Gleixner 
---
 drivers/pci/msi/irqdomain.c |2 +-
 drivers/pci/msi/legacy.c|6 +-
 drivers/pci/msi/msi.c   |   23 ---
 include/linux/pci.h |1 -
 4 files changed, 6 insertions(+), 26 deletions(-)

--- a/drivers/pci/msi/irqdomain.c
+++ b/drivers/pci/msi/irqdomain.c
@@ -159,7 +159,7 @@ struct irq_domain *pci_msi_create_irq_do
if (info->flags & MSI_FLAG_USE_DEF_CHIP_OPS)
pci_msi_domain_update_chip_ops(info);
 
-   info->flags |= MSI_FLAG_ACTIVATE_EARLY;
+   info->flags |= MSI_FLAG_ACTIVATE_EARLY | MSI_FLAG_DEV_SYSFS;
if (IS_ENABLED(CONFIG_GENERIC_IRQ_RESERVATION_MODE))
info->flags |= MSI_FLAG_MUST_REACTIVATE;
 
--- a/drivers/pci/msi/legacy.c
+++ b/drivers/pci/msi/legacy.c
@@ -71,10 +71,14 @@ int pci_msi_legacy_setup_msi_irqs(struct
 {
int ret = arch_setup_msi_irqs(dev, nvec, type);
 
-   return pci_msi_setup_check_result(dev, type, ret);
+   ret = pci_msi_setup_check_result(dev, type, ret);
+   if (!ret)
+   ret = msi_device_populate_sysfs(>dev);
+   return ret;
 }
 
 void pci_msi_legacy_teardown_msi_irqs(struct pci_dev *dev)
 {
+   msi_device_destroy_sysfs(>dev);
arch_teardown_msi_irqs(dev);
 }
--- a/drivers/pci/msi/msi.c
+++ b/drivers/pci/msi/msi.c
@@ -233,11 +233,6 @@ static void free_msi_irqs(struct pci_dev
for (i = 0; i < entry->nvec_used; i++)
BUG_ON(irq_has_action(entry->irq + i));
 
-   if (dev->msi_irq_groups) {
-   msi_destroy_sysfs(>dev, dev->msi_irq_groups);
-   dev->msi_irq_groups = NULL;
-   }
-
pci_msi_teardown_msi_irqs(dev);
 
list_for_each_entry_safe(entry, tmp, msi_list, list) {
@@ -415,7 +410,6 @@ static int msi_verify_entries(struct pci
 static int msi_capability_init(struct pci_dev *dev, int nvec,
   struct irq_affinity *affd)
 {
-   const struct attribute_group **groups;
struct msi_desc *entry;
int ret;
 
@@ -439,14 +433,6 @@ static int msi_capability_init(struct pc
if (ret)
goto err;
 
-   groups = msi_populate_sysfs(>dev);
-   if (IS_ERR(groups)) {
-   ret = PTR_ERR(groups);
-   goto err;
-   }
-
-   dev->msi_irq_groups = groups;
-
/* Set MSI enabled bits */
pci_intx_for_msi(dev, 0);
pci_msi_set_enable(dev, 1);
@@ -574,7 +560,6 @@ static void msix_mask_all(void __iomem *
 static int msix_capability_init(struct pci_dev *dev, struct msix_entry 
*entries,
int nvec, struct irq_affinity *affd)
 {
-   const struct attribute_group **groups;
void __iomem *base;
int ret, tsize;
u16 control;
@@ -616,14 +601,6 @@ static int msix_capability_init(struct p
 
msix_update_entries(dev, entries);
 
-   groups = msi_populate_sysfs(>dev);
-   if (IS_ERR(groups)) {
-   ret = PTR_ERR(groups);
-   goto out_free;
-   }
-
-   dev->msi_irq_groups = groups;
-
/* Set MSI-X enabled bits and unmask the function */
pci_intx_for_msi(dev, 0);
dev->msix_enabled = 1;
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -474,7 +474,6 @@ struct pci_dev {
 #endif
 #ifdef CONFIG_PCI_MSI
void __iomem*msix_base;
-   const struct attribute_group **msi_irq_groups;
 #endif
struct pci_vpd  vpd;
 #ifdef CONFIG_PCIE_DPC

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 08/37] genirq/msi: Provide msi_device_populate/destroy_sysfs()

2021-11-26 Thread Thomas Gleixner
Add new allocation functions which can be activated by domain info
flags. They store the groups pointer in struct msi_device_data.

Signed-off-by: Thomas Gleixner 
---
 include/linux/msi.h |   12 +++-
 kernel/irq/msi.c|   42 --
 2 files changed, 51 insertions(+), 3 deletions(-)

--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -174,9 +174,11 @@ struct msi_desc {
 /**
  * msi_device_data - MSI per device data
  * @lock:  Spinlock to protect register access
+ * @attrs: Pointer to the sysfs attribute group
  */
 struct msi_device_data {
-   raw_spinlock_t  lock;
+   raw_spinlock_t  lock;
+   const struct attribute_group**attrs;
 };
 
 int msi_setup_device_data(struct device *dev);
@@ -242,10 +244,16 @@ void pci_msi_mask_irq(struct irq_data *d
 void pci_msi_unmask_irq(struct irq_data *data);
 
 #ifdef CONFIG_SYSFS
+int msi_device_populate_sysfs(struct device *dev);
+void msi_device_destroy_sysfs(struct device *dev);
+
 const struct attribute_group **msi_populate_sysfs(struct device *dev);
 void msi_destroy_sysfs(struct device *dev,
   const struct attribute_group **msi_irq_groups);
 #else
+static inline int msi_device_populate_sysfs(struct device *dev) { return 0; }
+static inline void msi_device_destroy_sysfs(struct device *dev) { }
+
 static inline const struct attribute_group **msi_populate_sysfs(struct device 
*dev)
 {
return NULL;
@@ -393,6 +401,8 @@ enum {
MSI_FLAG_MUST_REACTIVATE= (1 << 5),
/* Is level-triggered capable, using two messages */
MSI_FLAG_LEVEL_CAPABLE  = (1 << 6),
+   /* Populate sysfs on alloc() and destroy it on free() */
+   MSI_FLAG_DEV_SYSFS  = (1 << 7),
 };
 
 int msi_domain_set_affinity(struct irq_data *data, const struct cpumask *mask,
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -214,6 +214,20 @@ const struct attribute_group **msi_popul
 }
 
 /**
+ * msi_device_populate_sysfs - Populate msi_irqs sysfs entries for a device
+ * @dev:   The device(PCI, platform etc) which will get sysfs entries
+ */
+int msi_device_populate_sysfs(struct device *dev)
+{
+   const struct attribute_group **group = msi_populate_sysfs(dev);
+
+   if (IS_ERR(group))
+   return PTR_ERR(group);
+   dev->msi.data->attrs = group;
+   return 0;
+}
+
+/**
  * msi_destroy_sysfs - Destroy msi_irqs sysfs entries for devices
  * @dev:   The device(PCI, platform etc) who will remove sysfs 
entries
  * @msi_irq_groups:attribute_group for device msi_irqs entries
@@ -239,6 +253,17 @@ void msi_destroy_sysfs(struct device *de
kfree(msi_irq_groups);
}
 }
+
+/**
+ * msi_device_destroy_sysfs - Destroy msi_irqs sysfs entries for a device
+ * @dev:   The device(PCI, platform etc) for which to remove
+ * sysfs entries
+ */
+void msi_device_destroy_sysfs(struct device *dev)
+{
+   msi_destroy_sysfs(dev, dev->msi.data->attrs);
+   dev->msi.data->attrs = NULL;
+}
 #endif
 
 #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
@@ -686,8 +711,19 @@ int msi_domain_alloc_irqs(struct irq_dom
 {
struct msi_domain_info *info = domain->host_data;
struct msi_domain_ops *ops = info->ops;
+   int ret;
 
-   return ops->domain_alloc_irqs(domain, dev, nvec);
+   ret = ops->domain_alloc_irqs(domain, dev, nvec);
+   if (ret)
+   return ret;
+
+   if (!(info->flags & MSI_FLAG_DEV_SYSFS))
+   return 0;
+
+   ret = msi_device_populate_sysfs(dev);
+   if (ret)
+   msi_domain_free_irqs(domain, dev);
+   return ret;
 }
 
 void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
@@ -726,7 +762,9 @@ void msi_domain_free_irqs(struct irq_dom
struct msi_domain_info *info = domain->host_data;
struct msi_domain_ops *ops = info->ops;
 
-   return ops->domain_free_irqs(domain, dev);
+   if (info->flags & MSI_FLAG_DEV_SYSFS)
+   msi_device_destroy_sysfs(dev);
+   ops->domain_free_irqs(domain, dev);
 }
 
 /**

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 07/37] soc: ti: ti_sci_inta_msi: Allocate MSI device data on first use

2021-11-26 Thread Thomas Gleixner
Allocate the MSI device data on first invocation of the allocation function.

Signed-off-by: Thomas Gleixner 
Cc: Nishanth Menon 
Cc: Tero Kristo 
Cc: Santosh Shilimkar 
Cc: linux-arm-ker...@lists.infradead.org
---
 drivers/soc/ti/ti_sci_inta_msi.c |4 
 1 file changed, 4 insertions(+)

--- a/drivers/soc/ti/ti_sci_inta_msi.c
+++ b/drivers/soc/ti/ti_sci_inta_msi.c
@@ -120,6 +120,10 @@ int ti_sci_inta_msi_domain_alloc_irqs(st
if (pdev->id < 0)
return -ENODEV;
 
+   ret = msi_setup_device_data(dev);
+   if (ret)
+   return ret;
+
nvec = ti_sci_inta_msi_alloc_descs(dev, res);
if (nvec <= 0)
return nvec;

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 06/37] bus: fsl-mc-msi: Allocate MSI device data on first use

2021-11-26 Thread Thomas Gleixner
Allocate the MSI device data on first invocation of the allocation function.

Signed-off-by: Thomas Gleixner 
Cc: Stuart Yoder 
Cc: Laurentiu Tudor 
---
 drivers/bus/fsl-mc/fsl-mc-msi.c |   14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

--- a/drivers/bus/fsl-mc/fsl-mc-msi.c
+++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
@@ -253,6 +253,14 @@ int fsl_mc_msi_domain_alloc_irqs(struct
struct irq_domain *msi_domain;
int error;
 
+   msi_domain = dev_get_msi_domain(dev);
+   if (!msi_domain)
+   return -EINVAL;
+
+   error = msi_setup_device_data(dev);
+   if (error)
+   return error;
+
if (!list_empty(dev_to_msi_list(dev)))
return -EINVAL;
 
@@ -260,12 +268,6 @@ int fsl_mc_msi_domain_alloc_irqs(struct
if (error < 0)
return error;
 
-   msi_domain = dev_get_msi_domain(dev);
-   if (!msi_domain) {
-   error = -EINVAL;
-   goto cleanup_msi_descs;
-   }
-
/*
 * NOTE: Calling this function will trigger the invocation of the
 * its_fsl_mc_msi_prepare() callback

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 04/37] PCI/MSI: Use lock from msi_device_data

2021-11-26 Thread Thomas Gleixner
Remove the register lock from struct device and use the one in
struct msi_device_data.

Signed-off-by: Thomas Gleixner 
---
 drivers/base/core.c|1 -
 drivers/pci/msi/msi.c  |2 +-
 include/linux/device.h |2 --
 3 files changed, 1 insertion(+), 4 deletions(-)

--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2875,7 +2875,6 @@ void device_initialize(struct device *de
device_pm_init(dev);
set_dev_node(dev, NUMA_NO_NODE);
 #ifdef CONFIG_GENERIC_MSI_IRQ
-   raw_spin_lock_init(>msi_lock);
INIT_LIST_HEAD(>msi_list);
 #endif
INIT_LIST_HEAD(>links.consumers);
--- a/drivers/pci/msi/msi.c
+++ b/drivers/pci/msi/msi.c
@@ -18,7 +18,7 @@ int pci_msi_ignore_mask;
 
 static noinline void pci_msi_update_mask(struct msi_desc *desc, u32 clear, u32 
set)
 {
-   raw_spinlock_t *lock = >dev->msi_lock;
+   raw_spinlock_t *lock = >dev->msi.data->lock;
unsigned long flags;
 
if (!desc->pci.msi_attrib.can_mask)
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -422,7 +422,6 @@ struct dev_msi_info {
  * @em_pd: device's energy model performance domain
  * @pins:  For device pin management.
  * See Documentation/driver-api/pin-control.rst for details.
- * @msi_lock:  Lock to protect MSI mask cache and mask register
  * @msi_list:  Hosts MSI descriptors
  * @numa_node: NUMA node this device is close to.
  * @dma_ops:DMA mapping operations for this device.
@@ -520,7 +519,6 @@ struct device {
 #endif
struct dev_msi_info msi;
 #ifdef CONFIG_GENERIC_MSI_IRQ
-   raw_spinlock_t  msi_lock;
struct list_headmsi_list;
 #endif
 #ifdef CONFIG_DMA_OPS

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 05/37] platform-msi: Allocate MSI device data on first use

2021-11-26 Thread Thomas Gleixner
Allocate the MSI device data on first invocation of the allocation function
for platform MSI private data.

Signed-off-by: Thomas Gleixner 
---
 drivers/base/platform-msi.c |8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -204,6 +204,8 @@ platform_msi_alloc_priv_data(struct devi
 irq_write_msi_msg_t write_msi_msg)
 {
struct platform_msi_priv_data *datap;
+   int err;
+
/*
 * Limit the number of interrupts to 2048 per device. Should we
 * need to bump this up, DEV_ID_SHIFT should be adjusted
@@ -218,6 +220,10 @@ platform_msi_alloc_priv_data(struct devi
return ERR_PTR(-EINVAL);
}
 
+   err = msi_setup_device_data(dev);
+   if (err)
+   return ERR_PTR(err);
+
/* Already had a helping of MSI? Greed... */
if (!list_empty(dev_to_msi_list(dev)))
return ERR_PTR(-EBUSY);
@@ -229,7 +235,7 @@ platform_msi_alloc_priv_data(struct devi
datap->devid = ida_simple_get(_msi_devid_ida,
  0, 1 << DEV_ID_SHIFT, GFP_KERNEL);
if (datap->devid < 0) {
-   int err = datap->devid;
+   err = datap->devid;
kfree(datap);
return ERR_PTR(err);
}

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 00/37] genirq/msi, PCI/MSI: Spring cleaning - Part 2

2021-11-26 Thread Thomas Gleixner
This is the second part of [PCI]MSI refactoring which aims to provide the
ability of expanding MSI-X vectors after enabling MSI-X.

The first part of this work can be found here:

https://lore.kernel.org/r/20211126222700.862407...@linutronix.de

This second part has the following important changes:

   1) Cleanup of the MSI related data in struct device

  struct device contains at the moment various MSI related parts. Some
  of them (the irq domain pointer) cannot be moved out, but the rest
  can be allocated on first use. This is in preparation of adding more
  per device MSI data later on.

   2) Consolidation of sysfs handling

  As a first step this moves the sysfs pointer from struct msi_desc
  into the new per device MSI data structure where it belongs.

  Later changes will cleanup this code further, but that's not possible
  at this point.

   3) Store per device properties in the per device MSI data to avoid
  looking up MSI descriptors and analysing their data. Cleanup all
  related use cases.

   4) Provide a function to retrieve the Linux interrupt number for a given
  MSI index similar to pci_irq_vector() and cleanup all open coded
  variants.

This second series is based on:

 git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git msi-v1-part-1

and also available from git:

 git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git msi-v1-part-2

For the curious who can't wait for the next part to arrive the full series
is available via:

 git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git msi-v1-part-4

Thanks,

tglx
---
 arch/powerpc/platforms/cell/axon_msi.c  |6 
 arch/powerpc/platforms/pseries/msi.c|   38 +---
 arch/x86/kernel/apic/msi.c  |5 
 arch/x86/pci/xen.c  |8 
 drivers/base/core.c |1 
 drivers/base/platform-msi.c |  152 -
 drivers/bus/fsl-mc/dprc-driver.c|8 
 drivers/bus/fsl-mc/fsl-mc-allocator.c   |9 -
 drivers/bus/fsl-mc/fsl-mc-msi.c |   26 +--
 drivers/dma/mv_xor_v2.c |   16 -
 drivers/dma/qcom/hidma.c|   44 ++---
 drivers/dma/ti/k3-udma-private.c|6 
 drivers/dma/ti/k3-udma.c|   14 -
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |   23 --
 drivers/irqchip/irq-mbigen.c|4 
 drivers/irqchip/irq-mvebu-icu.c |   12 -
 drivers/irqchip/irq-ti-sci-inta.c   |2 
 drivers/mailbox/bcm-flexrm-mailbox.c|9 -
 drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c|4 
 drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c|4 
 drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c |5 
 drivers/pci/msi/irqdomain.c |   20 +-
 drivers/pci/msi/legacy.c|6 
 drivers/pci/msi/msi.c   |  118 +
 drivers/pci/xen-pcifront.c  |2 
 drivers/perf/arm_smmuv3_pmu.c   |5 
 drivers/soc/fsl/dpio/dpio-driver.c  |8 
 drivers/soc/ti/k3-ringacc.c |6 
 drivers/soc/ti/ti_sci_inta_msi.c|   22 --
 drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c  |4 
 include/linux/device.h  |   26 ++-
 include/linux/fsl/mc.h  |4 
 include/linux/msi.h |  118 +++--
 include/linux/pci.h |1 
 include/linux/soc/ti/ti_sci_inta_msi.h  |1 
 kernel/irq/msi.c|  171 +++-
 36 files changed, 463 insertions(+), 445 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 03/37] PCI/MSI: Allocate MSI device data on first use

2021-11-26 Thread Thomas Gleixner
Allocate MSI device data on first use, i.e. when a PCI driver invokes one
of the PCI/MSI enablement functions.

Signed-off-by: Thomas Gleixner 
---
 drivers/pci/msi/msi.c |   20 +++-
 1 file changed, 15 insertions(+), 5 deletions(-)

--- a/drivers/pci/msi/msi.c
+++ b/drivers/pci/msi/msi.c
@@ -889,10 +889,12 @@ static int __pci_enable_msi_range(struct
 /* deprecated, don't use */
 int pci_enable_msi(struct pci_dev *dev)
 {
-   int rc = __pci_enable_msi_range(dev, 1, 1, NULL);
-   if (rc < 0)
-   return rc;
-   return 0;
+   int rc = msi_setup_device_data(>dev);
+
+   if (!rc)
+   rc = __pci_enable_msi_range(dev, 1, 1, NULL);
+
+   return rc < 0 ? rc : 0;
 }
 EXPORT_SYMBOL(pci_enable_msi);
 
@@ -947,7 +949,11 @@ static int __pci_enable_msix_range(struc
 int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,
int minvec, int maxvec)
 {
-   return __pci_enable_msix_range(dev, entries, minvec, maxvec, NULL, 0);
+   int ret = msi_setup_device_data(>dev);
+
+   if (!ret)
+   ret = __pci_enable_msix_range(dev, entries, minvec, maxvec, 
NULL, 0);
+   return ret;
 }
 EXPORT_SYMBOL(pci_enable_msix_range);
 
@@ -974,8 +980,12 @@ int pci_alloc_irq_vectors_affinity(struc
   struct irq_affinity *affd)
 {
struct irq_affinity msi_default_affd = {0};
+   int ret = msi_setup_device_data(>dev);
int nvecs = -ENOSPC;
 
+   if (ret)
+   return ret;
+
if (flags & PCI_IRQ_AFFINITY) {
if (!affd)
affd = _default_affd;

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 02/37] device: Add device::msi_data pointer and struct msi_device_data

2021-11-26 Thread Thomas Gleixner
Create struct msi_device_data and add a pointer of that type to struct
dev_msi_info, which is part of struct device. Provide an allocator function
which can be invoked from the MSI interrupt allocation code pathes.

Signed-off-by: Thomas Gleixner 
---
 include/linux/device.h |5 +
 include/linux/msi.h|   12 +++-
 kernel/irq/msi.c   |   33 +
 3 files changed, 49 insertions(+), 1 deletion(-)

--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -45,6 +45,7 @@ struct iommu_ops;
 struct iommu_group;
 struct dev_pin_info;
 struct dev_iommu;
+struct msi_device_data;
 
 /**
  * struct subsys_interface - interfaces to device functions
@@ -374,11 +375,15 @@ struct dev_links_info {
 /**
  * struct dev_msi_info - Device data related to MSI
  * @domain:The MSI interrupt domain associated to the device
+ * @data:  Pointer to MSI device data
  */
 struct dev_msi_info {
 #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
struct irq_domain   *domain;
 #endif
+#ifdef CONFIG_GENERIC_MSI_IRQ
+   struct msi_device_data  *data;
+#endif
 };
 
 /**
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -2,6 +2,7 @@
 #ifndef LINUX_MSI_H
 #define LINUX_MSI_H
 
+#include 
 #include 
 #include 
 
@@ -170,6 +171,16 @@ struct msi_desc {
};
 };
 
+/**
+ * msi_device_data - MSI per device data
+ * @lock:  Spinlock to protect register access
+ */
+struct msi_device_data {
+   raw_spinlock_t  lock;
+};
+
+int msi_setup_device_data(struct device *dev);
+
 /* Helpers to hide struct msi_desc implementation details */
 #define msi_desc_to_dev(desc)  ((desc)->dev)
 #define dev_to_msi_list(dev)   (&(dev)->msi_list)
@@ -185,7 +196,6 @@ struct msi_desc {
for (__irq = (desc)->irq;   \
 __irq < ((desc)->irq + (desc)->nvec_used); \
 __irq++)
-
 #ifdef CONFIG_IRQ_MSI_IOMMU
 static inline const void *msi_desc_get_iommu_cookie(struct msi_desc *desc)
 {
--- a/kernel/irq/msi.c
+++ b/kernel/irq/msi.c
@@ -73,6 +73,39 @@ void get_cached_msi_msg(unsigned int irq
 }
 EXPORT_SYMBOL_GPL(get_cached_msi_msg);
 
+static void msi_device_data_release(struct device *dev, void *res)
+{
+   WARN_ON_ONCE(!list_empty(>msi_list));
+   dev->msi.data = NULL;
+}
+
+/**
+ * msi_setup_device_data - Setup MSI device data
+ * @dev:   Device for which MSI device data should be set up
+ *
+ * Return: 0 on success, appropriate error code otherwise
+ *
+ * This can be called more than once for @dev. If the MSI device data is
+ * already allocated the call succeeds. The allocated memory is
+ * automatically released when the device is destroyed.
+ */
+int msi_setup_device_data(struct device *dev)
+{
+   struct msi_device_data *md;
+
+   if (dev->msi.data)
+   return 0;
+
+   md = devres_alloc(msi_device_data_release, sizeof(*md), GFP_KERNEL);
+   if (!md)
+   return -ENOMEM;
+
+   raw_spin_lock_init(>lock);
+   dev->msi.data = md;
+   devres_add(dev, md);
+   return 0;
+}
+
 #ifdef CONFIG_SYSFS
 static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,
 char *buf)

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[patch 01/37] device: Move MSI related data into a struct

2021-11-26 Thread Thomas Gleixner
The only unconditional part of MSI data in struct device is the irqdomain
pointer. Everything else can be allocated on demand. Create a data
structure and move the irqdomain pointer into it. The other MSI specific
parts are going to be removed from struct device in later steps.

Signed-off-by: Thomas Gleixner 
Cc: Greg Kroah-Hartman 
Cc: Will Deacon 
Cc: Santosh Shilimkar 
Cc: iommu@lists.linux-foundation.org
Cc: dmaeng...@vger.kernel.org
---
 drivers/base/platform-msi.c |   12 ++--
 drivers/dma/ti/k3-udma.c|4 ++--
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |2 +-
 drivers/irqchip/irq-mvebu-icu.c |6 +++---
 drivers/soc/ti/k3-ringacc.c |4 ++--
 drivers/soc/ti/ti_sci_inta_msi.c|2 +-
 include/linux/device.h  |   19 +--
 7 files changed, 28 insertions(+), 21 deletions(-)

--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -210,10 +210,10 @@ platform_msi_alloc_priv_data(struct devi
 * accordingly (which would impact the max number of MSI
 * capable devices).
 */
-   if (!dev->msi_domain || !write_msi_msg || !nvec || nvec > MAX_DEV_MSIS)
+   if (!dev->msi.domain || !write_msi_msg || !nvec || nvec > MAX_DEV_MSIS)
return ERR_PTR(-EINVAL);
 
-   if (dev->msi_domain->bus_token != DOMAIN_BUS_PLATFORM_MSI) {
+   if (dev->msi.domain->bus_token != DOMAIN_BUS_PLATFORM_MSI) {
dev_err(dev, "Incompatible msi_domain, giving up\n");
return ERR_PTR(-EINVAL);
}
@@ -269,7 +269,7 @@ int platform_msi_domain_alloc_irqs(struc
if (err)
goto out_free_priv_data;
 
-   err = msi_domain_alloc_irqs(dev->msi_domain, dev, nvec);
+   err = msi_domain_alloc_irqs(dev->msi.domain, dev, nvec);
if (err)
goto out_free_desc;
 
@@ -282,7 +282,7 @@ int platform_msi_domain_alloc_irqs(struc
return 0;
 
 out_free_irqs:
-   msi_domain_free_irqs(dev->msi_domain, dev);
+   msi_domain_free_irqs(dev->msi.domain, dev);
 out_free_desc:
platform_msi_free_descs(dev, 0, nvec);
 out_free_priv_data:
@@ -306,7 +306,7 @@ void platform_msi_domain_free_irqs(struc
platform_msi_free_priv_data(desc->platform.msi_priv_data);
}
 
-   msi_domain_free_irqs(dev->msi_domain, dev);
+   msi_domain_free_irqs(dev->msi.domain, dev);
platform_msi_free_descs(dev, 0, MAX_DEV_MSIS);
 }
 EXPORT_SYMBOL_GPL(platform_msi_domain_free_irqs);
@@ -354,7 +354,7 @@ struct irq_domain *
return NULL;
 
data->host_data = host_data;
-   domain = irq_domain_create_hierarchy(dev->msi_domain, 0,
+   domain = irq_domain_create_hierarchy(dev->msi.domain, 0,
 is_tree ? 0 : nvec,
 dev->fwnode, ops, data);
if (!domain)
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -5279,9 +5279,9 @@ static int udma_probe(struct platform_de
if (IS_ERR(ud->ringacc))
return PTR_ERR(ud->ringacc);
 
-   dev->msi_domain = of_msi_get_domain(dev, dev->of_node,
+   dev->msi.domain = of_msi_get_domain(dev, dev->of_node,
DOMAIN_BUS_TI_SCI_INTA_MSI);
-   if (!dev->msi_domain) {
+   if (!dev->msi.domain) {
dev_err(dev, "Failed to get MSI domain\n");
return -EPROBE_DEFER;
}
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3170,7 +3170,7 @@ static void arm_smmu_setup_msis(struct a
if (!(smmu->features & ARM_SMMU_FEAT_MSI))
return;
 
-   if (!dev->msi_domain) {
+   if (!dev->msi.domain) {
dev_info(smmu->dev, "msi_domain absent - falling back to wired 
irqs\n");
return;
}
--- a/drivers/irqchip/irq-mvebu-icu.c
+++ b/drivers/irqchip/irq-mvebu-icu.c
@@ -314,12 +314,12 @@ static int mvebu_icu_subset_probe(struct
msi_data->subset_data = of_device_get_match_data(dev);
}
 
-   dev->msi_domain = of_msi_get_domain(dev, dev->of_node,
+   dev->msi.domain = of_msi_get_domain(dev, dev->of_node,
DOMAIN_BUS_PLATFORM_MSI);
-   if (!dev->msi_domain)
+   if (!dev->msi.domain)
return -EPROBE_DEFER;
 
-   msi_parent_dn = irq_domain_get_of_node(dev->msi_domain);
+   msi_parent_dn = irq_domain_get_of_node(dev->msi.domain);
if (!msi_parent_dn)
return -ENODEV;
 
--- a/drivers/soc/ti/k3-ringacc.c
+++ b/drivers/soc/ti/k3-ringacc.c
@@ -1356,9 +1356,9 @@ static int k3_ringacc_init(struct platfo
struct resource *res;
int ret, i;
 
-   dev->msi_domain = of_msi_get_domain(dev, dev->of_node,
+   dev->msi.domain = of_msi_get_domain(dev, dev->of_node,
   

Re: [PATCH v2 0/2] iommu/vt-d: Fixes for v5.16-rc3

2021-11-26 Thread Joerg Roedel
On Fri, Nov 26, 2021 at 09:55:54PM +0800, Lu Baolu wrote:
> Update this series with a fix for an issue reported by Intel 0-day
> robot. Sorry for the inconvenience.

Replaced those with the previous fixes, thanks. Please just send a fix
on-top next time. This was already in the published fixes branch, which
I had to rebase now.

Thanks,

Joerg

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v2 2/6] hwtracing: Add trace function support for HiSilicon PCIe Tune and Trace device

2021-11-26 Thread Mathieu Poirier


[...]

> 
> > >> +
> > >> +#define HISI_PTT_TRACE_DMA_IRQ  0
> > >> +#define HISI_PTT_TRACE_BUFLETS_CNT  4
> > >> +#define HISI_PTT_TRACE_BUFLET_SIZE  SZ_4M
> > >> +#define HISI_PTT_TRACE_BUFFER_SIZE  
> > >> (HISI_PTT_TRACE_BUFLET_SIZE * \
> > >> + 
> > >> HISI_PTT_TRACE_BUFLETS_CNT)
> > >> +#define HISI_PTT_FILTER_UPDATE_FIFO_SIZE16
> > >> +
> > >> +/* Delay time for filter updating work */
> > >> +#define HISI_PTT_WORK_DELAY_MS  100UL
> > >> +/* Wait time for DMA hardware to reset */
> > >> +#define HISI_PTT_RESET_WAIT_MS  1000UL
> > >> +/* Poll timeout and interval for waiting hardware work to finish */
> > >> +#define HISI_PTT_WAIT_TIMEOUT_US100UL
> > >> +#define HISI_PTT_WAIT_POLL_INTERVAL_US  100UL
> > >> +
> > >> +#define HISI_PCIE_CORE_PORT_ID(devfn)   (PCI_FUNC(devfn) << 1)
> > >> +
> > >> +enum hisi_ptt_trace_status {
> > >> +HISI_PTT_TRACE_STATUS_OFF = 0,
> > >> +HISI_PTT_TRACE_STATUS_ON,
> > >> +};
> > >> +
> > >> +struct hisi_ptt_dma_buflet {
> > > 
> > > I'm not sure what a "buflet" is...  Probably best to just call this
> > > hisi_ptt_dma_buffer" if it pertains to a buffer.  On that note it is hard 
> > > to
> > > know due to the lack of proper structure documentation.  Please have a 
> > > look at
> > > how "coresight_device" is documented.  The same applies to the rest of the
> > > structures declared below.
> > > 
> > 
> > It's mentioned in section 5 of hisi_ptt.rst as "Driver will allocate each 
> > DMA buffer
> > (we call it buflet) of 4MiB ...".
> 
> I just noticed the documentation in patch 5 - I will read it before continuing
> with this set.
>

As promised I read the documentation and it didn't do much to alliviate my
concern about the terminology.  If a "buflet" is a DMA buffer than simply call
it a DMA buffer, regardless of the size.  

The size of this patchset makes it hard enough to review as it is... On top
of things reviewers have to remember that PTT means "PCIe tune and trace
device", tune means "PCIe link's events" and trace means "TLP headers".

But we also have to keep in mind that a buflet is really just a DMA buffer...

I will not continue reviewing this set.  Please fix the terminology and spin
another revision.  Doing so I suggest you trim down the submission to the
absolute minimum feature set this driver should provide - enhancements can be
made later when a foundation has been laid out.

Robin has pointed out what seems to be serious problems with the
implemenation.  That will also have to be sorted out for the next iteration.

Regards,
Mathieu


> > 
> > The total DMA buffer of PTT device is divided into 4 parts, and each part 
> > is called
> > a 'buflet', which means a small buffer (there exists other words with 
> > similiar
> > format: droplet, wavelet, ...).
> > 
> > The device is designed like this to make sure we won't lose any data when 
> > we have to change
> > the buffer address, the device can continue to write to the next buflet and 
> > don't
> > neet to pause.
> > 
> > >> +struct list_head list;
> > >> +unsigned int size;
> > >> +dma_addr_t dma;
> > >> +
> > >> +/*
> > >> + * The address of the buflet holding the trace data.
> > >> + * See Documentation/trace/hisi-ptt.rst for the details
> > > 
> > > As of this writing, hisi-ptt.rst doesn't exist.
> > > 
> > 
> > The comment intends to direct the user to the documentation if the user
> > want to know details about the data format. The data format is decribed
> > in the section 4 of the doc.
> > 
> > >> + * of the data format.
> > >> + */
> > >> +void *addr;
> > >> +int index;
> > >> +};
> > >> +
> > >> +struct hisi_ptt_trace_ctrl {
> > >> +enum hisi_ptt_trace_status status;
> > >> +struct perf_output_handle handle;
> > >> +struct list_head trace_buf;
> > >> +/*
> > >> + * The index of the buffer which trace data
> > >> + * currently is writing to.
> > >> + */
> > >> +u32 buf_index;
> > >> +
> > >> +int default_cpu;
> > >> +u32 buflet_size;
> > >> +bool is_port;
> > >> +u32 format:1;   /* Format of the traced TLP headers */
> > >> +u32 type:4; /* Type of the TLP headers to trace */
> > >> +u32 direction:2;/* Direction of the TLP headers to 
> > >> trace */
> > >> +u32 filter:16;  /* Root port or Requester to filter the 
> > >> TLP headers */
> > >> +
> > >> +phys_addr_t rmr_addr;
> > >> +size_t rmr_length;
> > >> +bool has_rmr;
> > >> +};
> > >> +
> > >> +struct hisi_ptt_filter_desc {
> > >> +struct list_head list;
> > >> +struct pci_dev *pdev;
> > >> +u16 val;
> > >> +};
> > >> +
> > >> +struct hisi_ptt_pmu_buf {
> > >> +size_t length;
> > >> +int 

[PATCH v2 2/2] iommu/vt-d: Fix unmap_pages support

2021-11-26 Thread Lu Baolu
From: Alex Williamson 

When supporting only the .map and .unmap callbacks of iommu_ops,
the IOMMU driver can make assumptions about the size and alignment
used for mappings based on the driver provided pgsize_bitmap.  VT-d
previously used essentially PAGE_MASK for this bitmap as any power
of two mapping was acceptably filled by native page sizes.

However, with the .map_pages and .unmap_pages interface we're now
getting page-size and count arguments.  If we simply combine these
as (page-size * count) and make use of the previous map/unmap
functions internally, any size and alignment assumptions are very
different.

As an example, a given vfio device assignment VM will often create
a 4MB mapping at IOVA pfn [0x3fe00 - 0x401ff].  On a system that
does not support IOMMU super pages, the unmap_pages interface will
ask to unmap 1024 4KB pages at the base IOVA.  dma_pte_clear_level()
will recurse down to level 2 of the page table where the first half
of the pfn range exactly matches the entire pte level.  We clear the
pte, increment the pfn by the level size, but (oops) the next pte is
on a new page, so we exit the loop an pop back up a level.  When we
then update the pfn based on that higher level, we seem to assume
that the previous pfn value was at the start of the level.  In this
case the level size is 256K pfns, which we add to the base pfn and
get a results of 0x7fe00, which is clearly greater than 0x401ff,
so we're done.  Meanwhile we never cleared the ptes for the remainder
of the range.  When the VM remaps this range, we're overwriting valid
ptes and the VT-d driver complains loudly, as reported by the user
report linked below.

The fix for this seems relatively simple, if each iteration of the
loop in dma_pte_clear_level() is assumed to clear to the end of the
level pte page, then our next pfn should be calculated from level_pfn
rather than our working pfn.

Fixes: 3f34f1259776 ("iommu/vt-d: Implement map/unmap_pages() iommu_ops 
callback")
Reported-by: Ajay Garg 
Signed-off-by: Alex Williamson 
Tested-by: Giovanni Cabiddu 
Link: https://lore.kernel.org/all/20211002124012.18186-1-ajaygargn...@gmail.com/
Link: 
https://lore.kernel.org/r/163659074748.1617923.12716161410774184024.stgit@omen
Signed-off-by: Lu Baolu 
---
 drivers/iommu/intel/iommu.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 0bde0c8b4126..b6a8f3282411 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -1339,13 +1339,11 @@ static struct page *dma_pte_clear_level(struct 
dmar_domain *domain, int level,
pte = [pfn_level_offset(pfn, level)];
 
do {
-   unsigned long level_pfn;
+   unsigned long level_pfn = pfn & level_mask(level);
 
if (!dma_pte_present(pte))
goto next;
 
-   level_pfn = pfn & level_mask(level);
-
/* If range covers entire pagetable, free it */
if (start_pfn <= level_pfn &&
last_pfn >= level_pfn + level_size(level) - 1) {
@@ -1366,7 +1364,7 @@ static struct page *dma_pte_clear_level(struct 
dmar_domain *domain, int level,
   freelist);
}
 next:
-   pfn += level_size(level);
+   pfn = level_pfn + level_size(level);
} while (!first_pte_in_page(++pte) && pfn <= last_pfn);
 
if (first_pte)
-- 
2.25.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 0/2] iommu/vt-d: Fixes for v5.16-rc3

2021-11-26 Thread Lu Baolu
Hi Joerg,

Update this series with a fix for an issue reported by Intel 0-day
robot. Sorry for the inconvenience.

Best regards,
baolu

change log:
v1:
https://lore.kernel.org/all/20211122032458.2549761-1-baolu...@linux.intel.com/

v2: For the patch titled "iommu/vt-d: Fix unmap_pages support",
fixed below issue reported by Intel 0-day robot.

"
drivers/iommu/intel/iommu.c:1344:7: warning: variable 'level_pfn' is
used uninitialized whenever 'if' condition is true
[-Wsometimes-uninitialized]
"

Alex Williamson (1):
  iommu/vt-d: Fix unmap_pages support

Christophe JAILLET (1):
  iommu/vt-d: Fix an unbalanced rcu_read_lock/rcu_read_unlock()

 drivers/iommu/intel/cap_audit.c | 5 +++--
 drivers/iommu/intel/iommu.c | 6 ++
 2 files changed, 5 insertions(+), 6 deletions(-)

-- 
2.25.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v2 1/2] iommu/vt-d: Fix an unbalanced rcu_read_lock/rcu_read_unlock()

2021-11-26 Thread Lu Baolu
From: Christophe JAILLET 

If we return -EOPNOTSUPP, the rcu lock remains lock. This is spurious.
Go through the end of the function instead. This way, the missing
'rcu_read_unlock()' is called.

Fixes: 7afd7f6aa21a ("iommu/vt-d: Check FL and SL capability sanity in scalable 
mode")
Signed-off-by: Christophe JAILLET 
Link: 
https://lore.kernel.org/r/40cc077ca5f543614eab2a10e84d29dd190273f6.1636217517.git.christophe.jail...@wanadoo.fr
Signed-off-by: Lu Baolu 
---
 drivers/iommu/intel/cap_audit.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/intel/cap_audit.c b/drivers/iommu/intel/cap_audit.c
index b39d223926a4..71596fc62822 100644
--- a/drivers/iommu/intel/cap_audit.c
+++ b/drivers/iommu/intel/cap_audit.c
@@ -144,6 +144,7 @@ static int cap_audit_static(struct intel_iommu *iommu, enum 
cap_audit_type type)
 {
struct dmar_drhd_unit *d;
struct intel_iommu *i;
+   int rc = 0;
 
rcu_read_lock();
if (list_empty(_drhd_units))
@@ -169,11 +170,11 @@ static int cap_audit_static(struct intel_iommu *iommu, 
enum cap_audit_type type)
 */
if (intel_cap_smts_sanity() &&
!intel_cap_flts_sanity() && !intel_cap_slts_sanity())
-   return -EOPNOTSUPP;
+   rc = -EOPNOTSUPP;
 
 out:
rcu_read_unlock();
-   return 0;
+   return rc;
 }
 
 int intel_cap_audit(enum cap_audit_type type, struct intel_iommu *iommu)
-- 
2.25.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 2/2] iommu/vt-d: Fix unmap_pages support

2021-11-26 Thread Lu Baolu

On 2021/11/22 11:24, Lu Baolu wrote:

From: Alex Williamson

When supporting only the .map and .unmap callbacks of iommu_ops,
the IOMMU driver can make assumptions about the size and alignment
used for mappings based on the driver provided pgsize_bitmap.  VT-d
previously used essentially PAGE_MASK for this bitmap as any power
of two mapping was acceptably filled by native page sizes.

However, with the .map_pages and .unmap_pages interface we're now
getting page-size and count arguments.  If we simply combine these
as (page-size * count) and make use of the previous map/unmap
functions internally, any size and alignment assumptions are very
different.

As an example, a given vfio device assignment VM will often create
a 4MB mapping at IOVA pfn [0x3fe00 - 0x401ff].  On a system that
does not support IOMMU super pages, the unmap_pages interface will
ask to unmap 1024 4KB pages at the base IOVA.  dma_pte_clear_level()
will recurse down to level 2 of the page table where the first half
of the pfn range exactly matches the entire pte level.  We clear the
pte, increment the pfn by the level size, but (oops) the next pte is
on a new page, so we exit the loop an pop back up a level.  When we
then update the pfn based on that higher level, we seem to assume
that the previous pfn value was at the start of the level.  In this
case the level size is 256K pfns, which we add to the base pfn and
get a results of 0x7fe00, which is clearly greater than 0x401ff,
so we're done.  Meanwhile we never cleared the ptes for the remainder
of the range.  When the VM remaps this range, we're overwriting valid
ptes and the VT-d driver complains loudly, as reported by the user
report linked below.

The fix for this seems relatively simple, if each iteration of the
loop in dma_pte_clear_level() is assumed to clear to the end of the
level pte page, then our next pfn should be calculated from level_pfn
rather than our working pfn.

Fixes: 3f34f1259776 ("iommu/vt-d: Implement map/unmap_pages() iommu_ops 
callback")
Reported-by: Ajay Garg
Signed-off-by: Alex Williamson
Tested-by: Giovanni Cabiddu
Link:https://lore.kernel.org/all/20211002124012.18186-1-ajaygargn...@gmail.com/
Link:https://lore.kernel.org/r/163659074748.1617923.12716161410774184024.stgit@omen
Signed-off-by: Lu Baolu


0-day build robot reported an error on this patch.

"drivers/iommu/intel/iommu.c:1344:7: warning: variable 'level_pfn' is 
used uninitialized whenever 'if' condition is true 
[-Wsometimes-uninitialized]

"

I will send a v2 of this patch. Sorry for the inconvenience.

Best regards
baolu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH] mm: kmemleak: Ignore kmemleak scanning on CMA regions

2021-11-26 Thread Calvin Zhang
Just like this:
commit 620951e27457 ("mm/cma: make kmemleak ignore CMA regions").

Add kmemleak_ignore_phys() for CMA created from of reserved node.

Signed-off-by: Calvin Zhang 
---
 kernel/dma/contiguous.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
index 3d63d91cba5c..66bd9a59615e 100644
--- a/kernel/dma/contiguous.c
+++ b/kernel/dma/contiguous.c
@@ -50,6 +50,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_CMA_SIZE_MBYTES
 #define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES
@@ -426,6 +427,9 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
pr_err("Reserved memory: unable to setup CMA region\n");
return err;
}
+
+   kmemleak_ignore_phys(rmem->base);
+
/* Architecture specific contiguous memory fixup. */
dma_contiguous_early_fixup(rmem->base, rmem->size);
 
-- 
2.30.2

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 3/5] hyperv/IOMMU: Enable swiotlb bounce buffer for Isolation VM

2021-11-26 Thread Tianyu Lan

On 11/26/2021 3:40 PM, Christoph Hellwig wrote:

On Wed, Nov 17, 2021 at 10:00:08PM +0800, Tianyu Lan wrote:

On 11/17/2021 6:01 PM, Christoph Hellwig wrote:

This doesn't really have much to do with normal DMA mapping,
so why does this direct through the dma ops?



According to the previous discussion, dma_alloc_noncontigous()
and dma_vmap_noncontiguous() may be used to handle the noncontigous
memory alloc/map in the netvsc driver. So add alloc/free and vmap/vunmap
callbacks here to handle the case. The previous patch v4 & v5 handles
the allocation and map in the netvsc driver. If this should not go though
dma ops, We also may make it as vmbus specific function and keep
the function in the vmbus driver.


But that only makes sense if they can actually use the normal DMA ops.
If you implement your own incomplete ops and require to use them you
do nothing but adding indirect calls to your fast path and making the
code convoluted.



Because the generic part implementation can't meet the netvsc driver
requests that allocate 16M memory and map pages via vmap_pfn(). So add 
Hyperv alloc_noncontiguous and vmap_noncontiguous callbacks. If this is

not a right way. we should call these hyper-V functions in the netvsc
driver directly, right?

Could you have a look at Michael summary about this series we made and
give some guides?

https://www.mail-archive.com/xen-devel@lists.xenproject.org/msg109284.html

Thanks.





___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu