[PATCH v3 1/4] thunderbolt: Add quirk to support vendor specific implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux