// SPDX-License-Identifier: GPL-2.0-only
/*
* Thunderbolt driver - NHI driver
*
* The NHI (native host interface) is the pci device that allows us to send and
* receive frames from the thunderbolt bus.
*
* Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>
* Copyright (C) 2018, Intel Corporation
*/
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/iommu.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/property.h>
#include <linux/string_helpers.h>
#include "nhi.h"
#include "nhi_regs.h"
#include "tb.h"
#define RING_TYPE(ring) ((ring)->is_tx ? "TX ring" : "RX ring")
#define RING_FIRST_USABLE_HOPID 1
/*
* Used with QUIRK_E2E to specify an unused HopID the Rx credits are
* transferred.
*/
#define RING_E2E_RESERVED_HOPID RING_FIRST_USABLE_HOPID
/*
* 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
#define NHI_MAILBOX_TIMEOUT 500 /* ms */
/* Host interface quirks */
#define QUIRK_AUTO_CLEAR_INT BIT(0)
#define QUIRK_E2E BIT(1)
static bool host_reset = true;
module_param(host_reset, bool, 0444);
MODULE_PARM_DESC(host_reset, "reset USB4 host router (default: true)");
static int ring_interrupt_index(const struct tb_ring *ring)
{
int bit = ring->hop;
if (!ring->is_tx)
bit += ring->nhi->hop_count;
return bit;
}
static void nhi_mask_interrupt(struct tb_nhi *nhi, int mask, int ring)
{
if (nhi->quirks & QUIRK_AUTO_CLEAR_INT) {
u32 val;
val = ioread32(nhi->iobase + REG_RING_INTERRUPT_BASE + ring);
iowrite32(val & ~mask, nhi->iobase + REG_RING_INTERRUPT_BASE + ring);
} else {
iowrite32(mask, nhi->iobase + REG_RING_INTERRUPT_MASK_CLEAR_BASE + ring);
}
}
static void nhi_clear_interrupt(struct tb_nhi *nhi, int ring)
{
if (nhi->quirks & QUIRK_AUTO_CLEAR_INT)
ioread32(nhi->iobase + REG_RING_NOTIFY_BASE + ring);
else
iowrite32(~0, nhi->iobase + REG_RING_INT_CLEAR + ring);
}
/*
* ring_interrupt_active() - activate/deactivate interrupts for a single ring
*
* ring->nhi->lock must be held.
*/
static void ring_interrupt_active(struct tb_ring *ring, bool active)
{
int index = ring_interrupt_index(ring) / 32 * 4;
int reg = REG_RING_INTERRUPT_BASE + index;
int interrupt_bit = ring_interrupt_index(ring) & 31;
int mask = 1 << interrupt_bit;
u32 old, new;
if (ring->irq > 0) {
u32 step, shift, ivr, misc;
void __iomem *ivr_base;
int auto_clear_bit;
int index;
if (ring->is_tx)
index = ring->hop;
else
index = ring->hop + ring->nhi->hop_count;
/*
* Intel routers support a bit that isn't part of
* the USB4 spec to ask the hardware to clear
* interrupt status bits automatically since
* we already know which interrupt was triggered.
*
* Other routers explicitly disable auto-clear
* to prevent conditions that may occur where two
* MSIX interrupts are simultaneously active and
* reading the register clears both of them.
*/
misc = ioread32(ring->nhi->iobase + REG_DMA_MISC);
if (ring->nhi->quirks & QUIRK_AUTO_CLEAR_INT)
auto_clear_bit = REG_DMA_MISC_INT_AUTO_CLEAR;
else
auto_clear_bit = REG_DMA_MISC_DISABLE_AUTO_CLEAR;
if (!(misc & auto_clear_bit))
iowrite32(misc | auto_clear_bit,
ring->nhi->iobase + REG_DMA_MISC);
ivr_base = ring->nhi->iobase + REG_INT_VEC_ALLOC_BASE;
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(ivr_base + step);
ivr &= ~(REG_INT_VEC_ALLOC_MASK << shift);
if (active)
ivr |= ring->vector << shift;
iowrite32(ivr, ivr_base + step);
}
old = ioread32(ring->nhi->iobase + reg);
if (active)
new = old | mask;
else
new = old & ~mask;
dev_dbg(&ring->nhi->pdev->dev,
"%s interrupt at register %#x bit %d (%#x -> %#x)\n",
active ? "enabling" : "disabling", reg, interrupt_bit, old, new);
if (new == old)
dev_WARN(&ring->nhi->pdev->dev,
"interrupt for %s %d is already %s\n",
RING_TYPE(ring), ring->hop,
active ? "enabled" : "disabled");
if (active)
iowrite32(new, ring->nhi->iobase + reg);
else
nhi_mask_interrupt(ring->nhi, mask, index);
}
/*
* nhi_disable_interrupts() - disable interrupts for all rings
*
* Use only during init and shutdown.
*/
static void nhi_disable_interrupts(struct tb_nhi *nhi)
{
int i = 0;
/* disable interrupts */
for (i = 0; i < RING_INTERRUPT_REG_COUNT(nhi); i++)
nhi_mask_interrupt(nhi, ~0, 4 * i);
/* clear interrupt status bits */
for (i = 0; i < RING_NOTIFY_REG_COUNT(nhi); i++)
nhi_clear_interrupt(nhi, 4 * i);
}
/* ring helper methods */
static void __iomem *ring_desc_base(struct tb_ring *ring)
{
void __iomem *io = ring->nhi->iobase;
io += ring->is_tx ? REG_TX_RING_BASE : REG_RX_RING_BASE;
io += ring->hop * 16;
return io;
}
static void __iomem *ring_options_base(struct tb_ring *ring)
{
void __iomem *io = ring->nhi->iobase;
io += ring->is_tx ? REG_TX_OPTIONS_BASE : REG_RX_OPTIONS_BASE;
io += ring->hop * 32;
return io;
}
static void ring_iowrite_cons(struct tb_ring *ring, u16 cons)
{
/*
* The other 16-bits in the register is read-only and writes to it
* are ignored by the hardware so we can save one ioread32() by
* filling the read-only bits with zeroes.
*/
iowrite32(cons, ring_desc_base(ring) + 8);
}
static void ring_iowrite_prod(struct tb_ring *ring, u16 prod)
{
/* See ring_iowrite_cons() above for explanation */
iowrite32(prod << 16, ring_desc_base(ring) + 8);
}
static void ring_iowrite32desc(struct tb_ring *ring, u32 value, u32 offset)
{
iowrite32(value, ring_desc_base(ring) + offset);
}
static void ring_iowrite64desc(struct tb_ring *ring, u64 value, u32 offset)
{
iowrite32(value, ring_desc_base(ring) + offset);
iowrite32(value >> 32, ring_desc_base(ring) + offset + 4);
}
static void ring_iowrite32options(struct tb_ring *ring, u32 value, u32 offset)
{
iowrite32(value, ring_options_base(ring) + offset);
}
static bool ring_f
|