All of lore.kernel.org
 help / color / mirror / Atom feed
* Questions on Interruption handling
@ 2014-10-22 17:43 Angelo Brito
  2014-10-22 18:10 ` Keith Busch
  2014-10-23 16:53 ` Matthew Wilcox
  0 siblings, 2 replies; 11+ messages in thread
From: Angelo Brito @ 2014-10-22 17:43 UTC (permalink / raw)


Hello all!

I had some issues with the Interruption handling. The scenario is as follows:
We have a NVMe Device with single MSI enabled and some of its
transfers took about 1000 jiffies (ms) to execute. We saw this when we
used IOMeter to benchmark a NVMe controller and we noticed that about
1 in 10 commands took much longer than expected. When we traced
through the kernel code we tracked the issue to come from the nvme_irq
function. In most cases, it is triggered by the interrupts and all
CQEs in the queue are processed correctly. In some cases, though, we
found out that a new CQE arrived while the nvme_irq function was
processing previous entries or just after the CQ doorbell has been
sent. These entries were overlooked by the driver and picked up later
by the nvme_kthread function, which reexecutes the nvme_process_cq
function once every second.

We read the NVMe specification 1.1 section 7.5.1.1 and noticed that it
defined a procedure to not loose any interrupts in a Legacy or MSI
system. The Host Software Interrupt Handling should mask and clear the
interruptions by using the INTMS and INTMC registers. We are proposing
a change to the nvme_irq function as described below. This is probably
not needed on MSI-X enabled devices but it is harmless to leave it in
for them as well.

So we modified the nvme_irq function and tested it on our controller
and the problem was fixed. Below annexed is the modified code, since
we don't know how to submit it. Sorry about that.

static irqreturn_t nvme_irq(int irq, void *data)
{
        irqreturn_t result;
        struct nvme_queue *nvmeq = data;
+        u32 maskvec;
+
+        /* We calculate which mask vector we use. */
+        maskvec = 1 << nvmeq->cq_vector;
+
        spin_lock(&nvmeq->q_lock);
+
+       /* We mask interrupts to this vector. */
+        writel(maskvec, &nvmeq->dev->bar->intms);
+
        nvme_process_cq(nvmeq);
        result = nvmeq->cqe_seen ? IRQ_HANDLED : IRQ_NONE;
        nvmeq->cqe_seen = 0;
+
+       /* And we unmask interrupt to this vector. */
+        writel(maskvec, &nvmeq->dev->bar->intmc);
+
        spin_unlock(&nvmeq->q_lock);
        return result;
}


Regards,
Angelo Silva Brito.
Digital System Engineer from Silicon Reef
http://about.me/angelobrito
_________________________________________________

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2015-01-21  0:08 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-22 17:43 Questions on Interruption handling Angelo Brito
2014-10-22 18:10 ` Keith Busch
2014-10-23 13:30   ` Angelo Brito
2014-10-23 14:26   ` Angelo Brito
2014-10-23 16:53 ` Matthew Wilcox
2014-10-24 16:51   ` Angelo Brito
2014-10-24 17:49     ` Matthew Wilcox
2014-10-24 17:59       ` Angelo Brito
2015-01-20 19:13         ` Angelo Brito
2015-01-20 22:35           ` Keith Busch
2015-01-21  0:08             ` Angelo Brito

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.