Skip to content

Commit 17a0f3a

Browse files
westeriwsakernel
authored andcommitted
i2c: ismt: Provide a DMA buffer for Interrupt Cause Logging
Before sending a MSI the hardware writes information pertinent to the interrupt cause to a memory location pointed by SMTICL register. This memory holds three double words where the least significant bit tells whether the interrupt cause of master/target/error is valid. The driver does not use this but we need to set it up because otherwise it will perform DMA write to the default address (0) and this will cause an IOMMU fault such as below: DMAR: DRHD: handling fault status reg 2 DMAR: [DMA Write] Request device [00:12.0] PASID ffffffff fault addr 0 [fault reason 05] PTE Write access is not set To prevent this from happening, provide a proper DMA buffer for this that then gets mapped by the IOMMU accordingly. Signed-off-by: Mika Westerberg <[email protected]> Reviewed-by: From: Andy Shevchenko <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent a2537c9 commit 17a0f3a

File tree

1 file changed

+14
-0
lines changed

1 file changed

+14
-0
lines changed

drivers/i2c/busses/i2c-ismt.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282

8383
#define ISMT_DESC_ENTRIES 2 /* number of descriptor entries */
8484
#define ISMT_MAX_RETRIES 3 /* number of SMBus retries to attempt */
85+
#define ISMT_LOG_ENTRIES 3 /* number of interrupt cause log entries */
8586

8687
/* Hardware Descriptor Constants - Control Field */
8788
#define ISMT_DESC_CWRL 0x01 /* Command/Write Length */
@@ -175,6 +176,8 @@ struct ismt_priv {
175176
u8 head; /* ring buffer head pointer */
176177
struct completion cmp; /* interrupt completion */
177178
u8 buffer[I2C_SMBUS_BLOCK_MAX + 16]; /* temp R/W data buffer */
179+
dma_addr_t log_dma;
180+
u32 *log;
178181
};
179182

180183
static const struct pci_device_id ismt_ids[] = {
@@ -411,6 +414,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
411414
memset(desc, 0, sizeof(struct ismt_desc));
412415
desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write);
413416

417+
/* Always clear the log entries */
418+
memset(priv->log, 0, ISMT_LOG_ENTRIES * sizeof(u32));
419+
414420
/* Initialize common control bits */
415421
if (likely(pci_dev_msi_enabled(priv->pci_dev)))
416422
desc->control = ISMT_DESC_INT | ISMT_DESC_FAIR;
@@ -708,6 +714,8 @@ static void ismt_hw_init(struct ismt_priv *priv)
708714
/* initialize the Master Descriptor Base Address (MDBA) */
709715
writeq(priv->io_rng_dma, priv->smba + ISMT_MSTR_MDBA);
710716

717+
writeq(priv->log_dma, priv->smba + ISMT_GR_SMTICL);
718+
711719
/* initialize the Master Control Register (MCTRL) */
712720
writel(ISMT_MCTRL_MEIE, priv->smba + ISMT_MSTR_MCTRL);
713721

@@ -795,6 +803,12 @@ static int ismt_dev_init(struct ismt_priv *priv)
795803
priv->head = 0;
796804
init_completion(&priv->cmp);
797805

806+
priv->log = dmam_alloc_coherent(&priv->pci_dev->dev,
807+
ISMT_LOG_ENTRIES * sizeof(u32),
808+
&priv->log_dma, GFP_KERNEL);
809+
if (!priv->log)
810+
return -ENOMEM;
811+
798812
return 0;
799813
}
800814

0 commit comments

Comments
 (0)