From: Sanjay R Mehta <sanju.mehta@xxxxxxx> Introduce nhi_check_quirks() routine to handle any vendor specific quirks to manage a hardware specific implementation. On Intel system, the USB4 controller requires the REG_DMA_MISC_INT_AUTO_CLEAR to be set. Hence handle it accordingly as per the USB4 specification via a quirk. Fixes: 046bee1f9ab8 ("thunderbolt: Add MSI-X support") Suggested-by: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx> Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@xxxxxxx> Signed-off-by: Sanjay R Mehta <sanju.mehta@xxxxxxx> --- drivers/thunderbolt/nhi.c | 18 ++++++++++++++---- include/linux/thunderbolt.h | 1 + 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index fa44332..7979638 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -43,6 +43,12 @@ static int ring_interrupt_index(struct tb_ring *ring) return bit; } +static void nhi_check_quirks(struct tb_nhi *nhi) +{ + if (nhi->pdev->vendor == PCI_VENDOR_ID_INTEL) + nhi->quirks |= REG_DMA_MISC_INT_AUTO_CLEAR; +} + /* * ring_interrupt_active() - activate/deactivate interrupts for a single ring * @@ -70,10 +76,12 @@ static void ring_interrupt_active(struct tb_ring *ring, bool active) * 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); + if (ring->nhi->quirks & REG_DMA_MISC_INT_AUTO_CLEAR) { + 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); + } } ivr_base = ring->nhi->iobase + REG_INT_VEC_ALLOC_BASE; @@ -1190,6 +1198,8 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (!nhi->tx_rings || !nhi->rx_rings) return -ENOMEM; + nhi_check_quirks(nhi); + res = nhi_init_msi(nhi); if (res) { dev_err(&pdev->dev, "cannot enable MSI, aborting\n"); diff --git a/include/linux/thunderbolt.h b/include/linux/thunderbolt.h index e7c96c3..2144123 100644 --- a/include/linux/thunderbolt.h +++ b/include/linux/thunderbolt.h @@ -480,6 +480,7 @@ struct tb_nhi { bool going_away; struct work_struct interrupt_work; u32 hop_count; + u32 quirks; }; /** -- 2.7.4