From: Mika Westerberg <mika.westerberg@linux.intel.com>
To: Andreas Noever <andreas.noever@gmail.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Michael Jamet <michael.jamet@intel.com>,
Yehezkel Bernat <yehezkel.bernat@intel.com>,
Lukas Wunner <lukas@wunner.de>,
Amir Levy <amir.jer.levy@intel.com>,
Andy Lutomirski <luto@kernel.org>,
Mario.Limonciello@dell.com, Jared.Dominguez@dell.com,
Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 04/24] thunderbolt: Add MSI-X support
Date: Mon, 22 May 2017 11:52:00 +0300 [thread overview]
Message-ID: <20170522085200.GT8541@lahna.fi.intel.com> (raw)
In-Reply-To: <CAMxnaaUyTLtu_Ks=TCduQpAMzezhKQ2OjC0i4RJu_-YTfN1K6Q@mail.gmail.com>
On Sun, May 21, 2017 at 07:51:09PM +0200, Andreas Noever wrote:
> On Thu, May 18, 2017 at 4:38 PM, Mika Westerberg
> <mika.westerberg@linux.intel.com> wrote:
> > Intel Thunderbolt controllers support up to 16 MSI-X vectors. Using
> Is that true for all generations? If so can we remove the legacy path?
Yes, I think it has been the case from the beginning. I have here one
Mac Mini with Light Ridge and even it has working MSI-X.
Yehezkel, Michael, Amir, do you know if that's the case for all other
controller as well?
> > MSI-X is preferred over MSI or legacy interrupt and may bring additional
> > performance because there is no need to check the status registers which
> > interrupt was triggered.
> >
> > While there we convert comments in structs tb_ring and tb_nhi to follow
> > kernel-doc format more closely.
> >
> > This code is based on the work done by Amir Levy and Michael Jamet.
> >
> > Signed-off-by: Michael Jamet <michael.jamet@intel.com>
> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> > Reviewed-by: Yehezkel Bernat <yehezkel.bernat@intel.com>
> > ---
> > drivers/thunderbolt/ctl.c | 4 +-
> > drivers/thunderbolt/nhi.c | 159 ++++++++++++++++++++++++++++++++++++-----
> > drivers/thunderbolt/nhi.h | 56 +++++++++++----
> > drivers/thunderbolt/nhi_regs.h | 9 +++
> > 4 files changed, 196 insertions(+), 32 deletions(-)
> >
> > diff --git a/drivers/thunderbolt/ctl.c b/drivers/thunderbolt/ctl.c
> > index 1031d97407a8..889a32dd21e7 100644
> > --- a/drivers/thunderbolt/ctl.c
> > +++ b/drivers/thunderbolt/ctl.c
> > @@ -488,11 +488,11 @@ struct tb_ctl *tb_ctl_alloc(struct tb_nhi *nhi, hotplug_cb cb, void *cb_data)
> > if (!ctl->frame_pool)
> > goto err;
> >
> > - ctl->tx = ring_alloc_tx(nhi, 0, 10);
> > + ctl->tx = ring_alloc_tx(nhi, 0, 10, RING_FLAG_NO_SUSPEND);
> > if (!ctl->tx)
> > goto err;
> >
> > - ctl->rx = ring_alloc_rx(nhi, 0, 10);
> > + ctl->rx = ring_alloc_rx(nhi, 0, 10, RING_FLAG_NO_SUSPEND);
> > if (!ctl->rx)
> > goto err;
> >
> > diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
> > index a8c20413dbda..17f3b1bdb7da 100644
> > --- a/drivers/thunderbolt/nhi.c
> > +++ b/drivers/thunderbolt/nhi.c
> > @@ -21,6 +21,12 @@
> >
> > #define RING_TYPE(ring) ((ring)->is_tx ? "TX ring" : "RX ring")
> >
> > +/*
> > + * Minimal number of vectors when we use MSI-X. Two for control channel
> > + * Rx/Tx and the rest four are for cross domain DMA paths.
> > + */
> > +#define MSIX_MIN_VECS 6
> > +#define MSIX_MAX_VECS 16
> >
> > static int ring_interrupt_index(struct tb_ring *ring)
> > {
> > @@ -239,8 +245,82 @@ int __ring_enqueue(struct tb_ring *ring, struct ring_frame *frame)
> > return ret;
> > }
> >
> > +static irqreturn_t ring_msix(int irq, void *data)
> > +{
> > + struct tb_ring *ring = data;
> > +
> > + schedule_work(&ring->work);
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static void ring_map_unmap_msix(struct tb_ring *ring, bool map)
> > +{
> This function does the same as ring_interrupt_active just for msix,
> right? Can we rename one (or both) to express that?
> For example rename ring_interrput_active -> ring_map_unmap_msi. Or
> just roll this one into ring_interrupt_active and do the right thing
> internally.
Yes, I think we can do that.
> > + u32 step, shift, ivr, misc;
> > + int index;
> > +
> > + if (ring->irq <= 0)
> > + return;
> > +
> > + if (ring->is_tx)
> > + index = ring->hop;
> > + else
> > + index = ring->hop + ring->nhi->hop_count;
> > +
> > + /*
> > + * Ask the hardware to clear interrupt status bits automatically
> > + * since we already know which interrupt was triggered.
> > + */
> > + misc = ioread32(ring->nhi->iobase + REG_DMA_MISC);
> > + if (!(misc & REG_DMA_MISC_INT_AUTO_CLEAR)) {
> > + misc |= REG_DMA_MISC_INT_AUTO_CLEAR;
> > + iowrite32(misc, ring->nhi->iobase + REG_DMA_MISC);
> > + }
> > +
> > + step = index / REG_INT_VEC_ALLOC_REGS * REG_INT_VEC_ALLOC_BITS;
> > + shift = index % REG_INT_VEC_ALLOC_REGS * REG_INT_VEC_ALLOC_BITS;
> > + ivr = ioread32(ring->nhi->iobase + REG_INT_VEC_ALLOC_BASE + step);
> > + ivr &= ~(REG_INT_VEC_ALLOC_MASK << shift);
> > + if (map)
> > + ivr |= ring->vector << shift;
> > + iowrite32(ivr, ring->nhi->iobase + REG_INT_VEC_ALLOC_BASE + step);
> > +}
> > +
> > +static int ring_request_msix(struct tb_ring *ring, bool no_suspend)
> > +{
> > + struct tb_nhi *nhi = ring->nhi;
> > + unsigned long irqflags;
> > + int ret;
> > +
> > + if (!nhi->pdev->msix_enabled)
> > + return 0;
> > +
> > + ret = ida_simple_get(&nhi->msix_ida, 0, MSIX_MAX_VECS, GFP_KERNEL);
> > + if (ret < 0)
> > + return ret;
> > +
> > + ring->vector = ret;
> > +
> > + ring->irq = pci_irq_vector(ring->nhi->pdev, ring->vector);
> > + if (ring->irq < 0)
> > + return ring->irq;
> > +
> > + irqflags = no_suspend ? IRQF_NO_SUSPEND : 0;
> > + return request_irq(ring->irq, ring_msix, irqflags, "thunderbolt", ring);
> > +}
> > +
> > +static void ring_release_msix(struct tb_ring *ring)
> > +{
> > + if (ring->irq <= 0)
> > + return;
> > +
> > + free_irq(ring->irq, ring);
> > + ida_simple_remove(&ring->nhi->msix_ida, ring->vector);
> > + ring->vector = 0;
> > + ring->irq = 0;
> > +}
> > +
> > static struct tb_ring *ring_alloc(struct tb_nhi *nhi, u32 hop, int size,
> > - bool transmit)
> > + bool transmit, unsigned int flags)
> > {
> > struct tb_ring *ring = NULL;
> > dev_info(&nhi->pdev->dev, "allocating %s ring %d of size %d\n",
> > @@ -271,9 +351,14 @@ static struct tb_ring *ring_alloc(struct tb_nhi *nhi, u32 hop, int size,
> > ring->hop = hop;
> > ring->is_tx = transmit;
> > ring->size = size;
> > + ring->flags = flags;
> > ring->head = 0;
> > ring->tail = 0;
> > ring->running = false;
> > +
> > + if (ring_request_msix(ring, flags & RING_FLAG_NO_SUSPEND))
> > + goto err;
> > +
> > ring->descriptors = dma_alloc_coherent(&ring->nhi->pdev->dev,
> > size * sizeof(*ring->descriptors),
> > &ring->descriptors_dma, GFP_KERNEL | __GFP_ZERO);
> > @@ -295,14 +380,16 @@ static struct tb_ring *ring_alloc(struct tb_nhi *nhi, u32 hop, int size,
> > return NULL;
> > }
> >
> > -struct tb_ring *ring_alloc_tx(struct tb_nhi *nhi, int hop, int size)
> > +struct tb_ring *ring_alloc_tx(struct tb_nhi *nhi, int hop, int size,
> > + unsigned int flags)
> > {
> > - return ring_alloc(nhi, hop, size, true);
> > + return ring_alloc(nhi, hop, size, true, flags);
> > }
> >
> > -struct tb_ring *ring_alloc_rx(struct tb_nhi *nhi, int hop, int size)
> > +struct tb_ring *ring_alloc_rx(struct tb_nhi *nhi, int hop, int size,
> > + unsigned int flags)
> > {
> > - return ring_alloc(nhi, hop, size, false);
> > + return ring_alloc(nhi, hop, size, false, flags);
> > }
> >
> > /**
> > @@ -334,6 +421,7 @@ void ring_start(struct tb_ring *ring)
> > ring_iowrite32options(ring,
> > RING_FLAG_ENABLE | RING_FLAG_RAW, 0);
> > }
> > + ring_map_unmap_msix(ring, true);
> > ring_interrupt_active(ring, true);
> > ring->running = true;
> > err:
> > @@ -366,6 +454,7 @@ void ring_stop(struct tb_ring *ring)
> > goto err;
> > }
> > ring_interrupt_active(ring, false);
> > + ring_map_unmap_msix(ring, false);
> >
> > ring_iowrite32options(ring, 0, 0);
> > ring_iowrite64desc(ring, 0, 0);
> > @@ -413,6 +502,8 @@ void ring_free(struct tb_ring *ring)
> > RING_TYPE(ring), ring->hop);
> > }
> >
> > + ring_release_msix(ring);
> > +
> > dma_free_coherent(&ring->nhi->pdev->dev,
> > ring->size * sizeof(*ring->descriptors),
> > ring->descriptors, ring->descriptors_dma);
> There is a comment a couple lines below that states that ring->work is
> only scheduled by nhi_interrupt_work and ring_stop. Please add
> ring_msix to the list.
OK.
> > @@ -528,9 +619,51 @@ static void nhi_shutdown(struct tb_nhi *nhi)
> > * We have to release the irq before calling flush_work. Otherwise an
> > * already executing IRQ handler could call schedule_work again.
> > */
> > - devm_free_irq(&nhi->pdev->dev, nhi->pdev->irq, nhi);
> > + if (!nhi->pdev->msix_enabled)
> > + devm_free_irq(&nhi->pdev->dev, nhi->pdev->irq, nhi);
> > flush_work(&nhi->interrupt_work);
> > mutex_destroy(&nhi->lock);
> > + ida_destroy(&nhi->msix_ida);
> > +}
> > +
> > +static int nhi_init_msi(struct tb_nhi *nhi)
> > +{
> > + struct pci_dev *pdev = nhi->pdev;
> > + int res, irq, nvec;
> > +
> > + /* In case someone left them on. */
> > + nhi_disable_interrupts(nhi);
> > +
> > + ida_init(&nhi->msix_ida);
> > +
> > + /*
> > + * The NHI has 16 MSI-X vectors or a single MSI. We first try to
> > + * get all MSI-X vectors and if we succeed, each ring will have
> > + * one MSI-X. If for some reason that does not work out, we
> > + * fallback to a single MSI.
> > + */
> > + nvec = pci_alloc_irq_vectors(pdev, MSIX_MIN_VECS, MSIX_MAX_VECS,
> > + PCI_IRQ_MSIX);
> > + if (nvec < 0) {
> > + nvec = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
> > + if (nvec < 0)
> > + return nvec;
> > +
> > + INIT_WORK(&nhi->interrupt_work, nhi_interrupt_work);
> As far as I can see INIT_WORK is only called here in the fallback
> case. But flush_work is still called unconditionally in nhi_shutdown.
Good point. I should make it conditional as well (or INIT_WORK()
unconditional).
next prev parent reply other threads:[~2017-05-22 8:54 UTC|newest]
Thread overview: 106+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-18 14:38 [PATCH 00/24] Thunderbolt security levels and NVM firmware upgrade Mika Westerberg
2017-05-18 14:38 ` [PATCH 01/24] thunderbolt: Use const buffer pointer in write operations Mika Westerberg
2017-05-25 13:19 ` Greg Kroah-Hartman
2017-05-18 14:38 ` [PATCH 02/24] thunderbolt: Do not try to read UID if DROM offset is read as 0 Mika Westerberg
2017-05-21 13:46 ` Andreas Noever
2017-05-22 8:40 ` Mika Westerberg
2017-05-22 18:41 ` Andreas Noever
2017-05-22 20:38 ` Mika Westerberg
2017-05-22 20:57 ` Andreas Noever
2017-05-18 14:38 ` [PATCH 03/24] thunderbolt: Do not warn about newer DROM versions Mika Westerberg
2017-05-18 14:38 ` [PATCH 04/24] thunderbolt: Add MSI-X support Mika Westerberg
2017-05-21 17:51 ` Andreas Noever
2017-05-22 8:52 ` Mika Westerberg [this message]
2017-05-22 10:35 ` Bernat, Yehezkel
2017-05-22 11:01 ` Mika Westerberg
2017-05-18 14:38 ` [PATCH 05/24] thunderbolt: Rework capability handling Mika Westerberg
2017-05-18 16:38 ` Andy Shevchenko
2017-05-19 8:12 ` Mika Westerberg
2017-05-19 13:18 ` Andy Shevchenko
2017-05-21 19:09 ` Andreas Noever
2017-05-22 9:45 ` Mika Westerberg
2017-05-22 9:58 ` Levy, Amir (Jer)
2017-05-25 6:13 ` Lukas Wunner
2017-05-18 14:38 ` [PATCH 06/24] thunderbolt: Introduce thunderbolt bus and connection manager Mika Westerberg
2017-05-18 16:43 ` Andy Shevchenko
2017-05-19 8:15 ` Mika Westerberg
2017-05-19 13:16 ` Andy Shevchenko
2017-05-24 10:28 ` Lukas Wunner
2017-05-24 10:39 ` Mika Westerberg
2017-05-25 13:23 ` Greg Kroah-Hartman
2017-05-25 14:42 ` Mika Westerberg
2017-05-18 14:38 ` [PATCH 07/24] thunderbolt: Convert switch to a device Mika Westerberg
2017-05-18 16:49 ` Andy Shevchenko
2017-05-19 8:20 ` Mika Westerberg
2017-05-24 11:09 ` Lukas Wunner
2017-05-24 11:43 ` Mika Westerberg
2017-05-24 13:53 ` Lukas Wunner
2017-05-25 6:57 ` Mika Westerberg
2017-05-18 14:38 ` [PATCH 08/24] thunderbolt: Fail switch adding operation if reading DROM fails Mika Westerberg
2017-05-18 14:38 ` [PATCH 09/24] thunderbolt: Do not fail if DROM data CRC32 is invalid Mika Westerberg
2017-05-18 14:39 ` [PATCH 10/24] thunderbolt: Read vendor and device name from DROM Mika Westerberg
2017-05-18 19:19 ` Andy Shevchenko
2017-05-19 8:22 ` Mika Westerberg
2017-05-19 10:07 ` Lukas Wunner
2017-05-19 10:28 ` Mika Westerberg
2017-05-21 5:31 ` Lukas Wunner
2017-05-21 7:48 ` Mika Westerberg
2017-05-21 9:33 ` Lukas Wunner
2017-05-18 14:39 ` [PATCH 11/24] thunderbolt: Move control channel messages to tb_msgs.h Mika Westerberg
2017-05-18 14:39 ` [PATCH 12/24] thunderbolt: Expose get_route() to other files Mika Westerberg
2017-05-18 14:39 ` [PATCH 13/24] thunderbolt: Expose make_header() " Mika Westerberg
2017-05-18 14:39 ` [PATCH 14/24] thunderbolt: Let the connection manager handle all notifications Mika Westerberg
2017-05-24 14:00 ` Lukas Wunner
2017-05-25 7:02 ` Mika Westerberg
2017-05-18 14:39 ` [PATCH 15/24] thunderbolt: Rework control channel to be more reliable Mika Westerberg
2017-05-25 13:25 ` Greg Kroah-Hartman
2017-05-25 14:35 ` Mika Westerberg
2017-05-18 14:39 ` [PATCH 16/24] thunderbolt: Add Thunderbolt 3 PCI IDs Mika Westerberg
2017-05-18 14:39 ` [PATCH 17/24] thunderbolt: Add support for NHI mailbox Mika Westerberg
2017-05-18 14:39 ` [PATCH 18/24] thunderbolt: Store Thunderbolt generation in the switch structure Mika Westerberg
2017-05-21 4:47 ` Lukas Wunner
2017-05-21 5:29 ` Levy, Amir (Jer)
2017-05-21 5:35 ` Lukas Wunner
2017-05-21 7:40 ` Mika Westerberg
2017-05-21 8:00 ` Mika Westerberg
2017-05-21 8:07 ` Levy, Amir (Jer)
2017-05-21 9:55 ` Bernat, Yehezkel
2017-05-21 10:47 ` Mika Westerberg
2017-05-21 11:18 ` Bernat, Yehezkel
2017-05-21 11:47 ` Mika Westerberg
2017-05-21 10:44 ` Mika Westerberg
2017-05-18 14:39 ` [PATCH 19/24] thunderbolt: Add support for DMA configuration based mailbox Mika Westerberg
2017-05-18 14:39 ` [PATCH 20/24] thunderbolt: Do not touch the hardware if the NHI is gone on resume Mika Westerberg
2017-05-24 14:43 ` Lukas Wunner
2017-05-25 7:10 ` Mika Westerberg
2017-05-18 14:39 ` [PATCH 21/24] thunderbolt: Add support for Internal Connection Manager (ICM) Mika Westerberg
2017-05-18 14:39 ` [PATCH 22/24] thunderbolt: Add support for host and device NVM firmware upgrade Mika Westerberg
2017-05-18 19:35 ` Andy Shevchenko
2017-05-19 8:26 ` Mika Westerberg
2017-05-25 13:28 ` Greg Kroah-Hartman
2017-05-25 14:39 ` Mika Westerberg
2017-05-25 14:57 ` Greg Kroah-Hartman
2017-05-18 14:39 ` [PATCH 23/24] thunderbolt: Add documentation how Thunderbolt bus can be used Mika Westerberg
2017-05-18 14:39 ` [PATCH 24/24] MAINTAINERS: Add maintainers for Thunderbolt driver Mika Westerberg
2017-05-19 16:35 ` [PATCH 00/24] Thunderbolt security levels and NVM firmware upgrade Mario.Limonciello
2017-05-19 17:19 ` Mika Westerberg
2017-05-19 17:54 ` Mario.Limonciello
2017-05-20 8:24 ` Mika Westerberg
2017-05-22 11:37 ` Mika Westerberg
2017-05-22 20:07 ` Mario.Limonciello
2017-05-22 20:10 ` Bernat, Yehezkel
2017-05-22 23:54 ` Mario.Limonciello
2017-05-22 20:48 ` Mika Westerberg
2017-05-23 17:30 ` Mario.Limonciello
2017-05-24 11:11 ` Mika Westerberg
2017-05-24 19:06 ` Mario.Limonciello
2017-05-24 19:32 ` Jamet, Michael
2017-05-25 7:20 ` mika.westerberg
2017-05-25 8:04 ` mika.westerberg
2017-05-25 12:03 ` mika.westerberg
2017-08-11 15:13 ` mika.westerberg
2017-05-25 7:19 ` Mika Westerberg
2017-05-19 18:00 ` Mika Westerberg
2017-05-20 9:15 ` Levy, Amir (Jer)
2017-05-21 8:08 ` mika.westerberg
2017-05-23 13:25 ` Andy Shevchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170522085200.GT8541@lahna.fi.intel.com \
--to=mika.westerberg@linux.intel.com \
--cc=Jared.Dominguez@dell.com \
--cc=Mario.Limonciello@dell.com \
--cc=amir.jer.levy@intel.com \
--cc=andreas.noever@gmail.com \
--cc=andriy.shevchenko@linux.intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lukas@wunner.de \
--cc=luto@kernel.org \
--cc=michael.jamet@intel.com \
--cc=yehezkel.bernat@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.