Message ID | 163474883845.2608004.9330596081850512248.stgit@djiang5-desk3.ch.intel.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | dmaengine: idxd: Add interrupt handle revoke support | expand |
On 20-10-21, 09:53, Dave Jiang wrote: > The helper is called at the completion of the interrupt handle refresh > event. It issues drain descriptors to each of the wq with associated > interrupt handle. The drain descriptor will have interrupt request set but > without completion record. This will ensure all descriptors with incorrect > interrupt completion handle get drained and a completion interrupt is > triggered for the guest driver to process them. > > Reviewed-by: Kevin Tian <kevin.tian@intel.com> > Signed-off-by: Dave Jiang <dave.jiang@intel.com> > --- > drivers/dma/idxd/irq.c | 41 +++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 41 insertions(+) > > diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c > index 573a2f6d0f7f..8bca0ed2d23c 100644 > --- a/drivers/dma/idxd/irq.c > +++ b/drivers/dma/idxd/irq.c > @@ -55,6 +55,47 @@ static void idxd_device_reinit(struct work_struct *work) > idxd_device_clear_state(idxd); > } > > +/* > + * The function sends a drain descriptor for the interrupt handle. The drain ensures > + * all descriptors with this interrupt handle is flushed and the interrupt > + * will allow the cleanup of the outstanding descriptors. > + */ > +static void idxd_int_handle_revoke_drain(struct idxd_irq_entry *ie) > +{ > + struct idxd_wq *wq = ie->wq; > + struct idxd_device *idxd = ie->idxd; > + struct device *dev = &idxd->pdev->dev; > + struct dsa_hw_desc desc; > + void __iomem *portal; > + int rc; > + > + memset(&desc, 0, sizeof(desc)); declare and init it and avoid the memset: struct dsa_hw_desc desc = {}; > + > + /* Issue a simple drain operation with interrupt but no completion record */ > + desc.flags = IDXD_OP_FLAG_RCI; > + desc.opcode = DSA_OPCODE_DRAIN; > + desc.priv = 1; > + > + if (ie->pasid != INVALID_IOASID) > + desc.pasid = ie->pasid; > + desc.int_handle = ie->int_handle; > + portal = idxd_wq_portal_addr(wq); > + > + /* > + * The wmb() makes sure that the descriptor is all there before we > + * issue. > + */ > + wmb(); > + if (wq_dedicated(wq)) { > + iosubmit_cmds512(portal, &desc, 1); > + } else { > + rc = enqcmds(portal, &desc); > + /* This should not fail unless hardware failed. */ > + if (rc < 0) > + dev_warn(dev, "Failed to submit drain desc on wq %d\n", wq->id); > + } > +} > + > static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) > { > struct device *dev = &idxd->pdev->dev; >
On 10/24/2021 10:06 PM, Vinod Koul wrote: > On 20-10-21, 09:53, Dave Jiang wrote: >> The helper is called at the completion of the interrupt handle refresh >> event. It issues drain descriptors to each of the wq with associated >> interrupt handle. The drain descriptor will have interrupt request set but >> without completion record. This will ensure all descriptors with incorrect >> interrupt completion handle get drained and a completion interrupt is >> triggered for the guest driver to process them. >> >> Reviewed-by: Kevin Tian <kevin.tian@intel.com> >> Signed-off-by: Dave Jiang <dave.jiang@intel.com> >> --- >> drivers/dma/idxd/irq.c | 41 +++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 41 insertions(+) >> >> diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c >> index 573a2f6d0f7f..8bca0ed2d23c 100644 >> --- a/drivers/dma/idxd/irq.c >> +++ b/drivers/dma/idxd/irq.c >> @@ -55,6 +55,47 @@ static void idxd_device_reinit(struct work_struct *work) >> idxd_device_clear_state(idxd); >> } >> >> +/* >> + * The function sends a drain descriptor for the interrupt handle. The drain ensures >> + * all descriptors with this interrupt handle is flushed and the interrupt >> + * will allow the cleanup of the outstanding descriptors. >> + */ >> +static void idxd_int_handle_revoke_drain(struct idxd_irq_entry *ie) >> +{ >> + struct idxd_wq *wq = ie->wq; >> + struct idxd_device *idxd = ie->idxd; >> + struct device *dev = &idxd->pdev->dev; >> + struct dsa_hw_desc desc; >> + void __iomem *portal; >> + int rc; >> + >> + memset(&desc, 0, sizeof(desc)); > declare and init it and avoid the memset: > struct dsa_hw_desc desc = {}; Thanks. Will fix. > >> + >> + /* Issue a simple drain operation with interrupt but no completion record */ >> + desc.flags = IDXD_OP_FLAG_RCI; >> + desc.opcode = DSA_OPCODE_DRAIN; >> + desc.priv = 1; >> + >> + if (ie->pasid != INVALID_IOASID) >> + desc.pasid = ie->pasid; >> + desc.int_handle = ie->int_handle; >> + portal = idxd_wq_portal_addr(wq); >> + >> + /* >> + * The wmb() makes sure that the descriptor is all there before we >> + * issue. >> + */ >> + wmb(); >> + if (wq_dedicated(wq)) { >> + iosubmit_cmds512(portal, &desc, 1); >> + } else { >> + rc = enqcmds(portal, &desc); >> + /* This should not fail unless hardware failed. */ >> + if (rc < 0) >> + dev_warn(dev, "Failed to submit drain desc on wq %d\n", wq->id); >> + } >> +} >> + >> static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) >> { >> struct device *dev = &idxd->pdev->dev; >>
diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c index 573a2f6d0f7f..8bca0ed2d23c 100644 --- a/drivers/dma/idxd/irq.c +++ b/drivers/dma/idxd/irq.c @@ -55,6 +55,47 @@ static void idxd_device_reinit(struct work_struct *work) idxd_device_clear_state(idxd); } +/* + * The function sends a drain descriptor for the interrupt handle. The drain ensures + * all descriptors with this interrupt handle is flushed and the interrupt + * will allow the cleanup of the outstanding descriptors. + */ +static void idxd_int_handle_revoke_drain(struct idxd_irq_entry *ie) +{ + struct idxd_wq *wq = ie->wq; + struct idxd_device *idxd = ie->idxd; + struct device *dev = &idxd->pdev->dev; + struct dsa_hw_desc desc; + void __iomem *portal; + int rc; + + memset(&desc, 0, sizeof(desc)); + + /* Issue a simple drain operation with interrupt but no completion record */ + desc.flags = IDXD_OP_FLAG_RCI; + desc.opcode = DSA_OPCODE_DRAIN; + desc.priv = 1; + + if (ie->pasid != INVALID_IOASID) + desc.pasid = ie->pasid; + desc.int_handle = ie->int_handle; + portal = idxd_wq_portal_addr(wq); + + /* + * The wmb() makes sure that the descriptor is all there before we + * issue. + */ + wmb(); + if (wq_dedicated(wq)) { + iosubmit_cmds512(portal, &desc, 1); + } else { + rc = enqcmds(portal, &desc); + /* This should not fail unless hardware failed. */ + if (rc < 0) + dev_warn(dev, "Failed to submit drain desc on wq %d\n", wq->id); + } +} + static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) { struct device *dev = &idxd->pdev->dev;