Skip to content

Commit f0749ae

Browse files
westerigregkh
authored andcommitted
i2c: ismt: Provide a DMA buffer for Interrupt Cause Logging
[ Upstream commit 17a0f3a ] 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]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 828309e commit f0749ae

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[] = {
@@ -409,6 +412,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr,
409412
memset(desc, 0, sizeof(struct ismt_desc));
410413
desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write);
411414

415+
/* Always clear the log entries */
416+
memset(priv->log, 0, ISMT_LOG_ENTRIES * sizeof(u32));
417+
412418
/* Initialize common control bits */
413419
if (likely(pci_dev_msi_enabled(priv->pci_dev)))
414420
desc->control = ISMT_DESC_INT | ISMT_DESC_FAIR;
@@ -693,6 +699,8 @@ static void ismt_hw_init(struct ismt_priv *priv)
693699
/* initialize the Master Descriptor Base Address (MDBA) */
694700
writeq(priv->io_rng_dma, priv->smba + ISMT_MSTR_MDBA);
695701

702+
writeq(priv->log_dma, priv->smba + ISMT_GR_SMTICL);
703+
696704
/* initialize the Master Control Register (MCTRL) */
697705
writel(ISMT_MCTRL_MEIE, priv->smba + ISMT_MSTR_MCTRL);
698706

@@ -780,6 +788,12 @@ static int ismt_dev_init(struct ismt_priv *priv)
780788
priv->head = 0;
781789
init_completion(&priv->cmp);
782790

791+
priv->log = dmam_alloc_coherent(&priv->pci_dev->dev,
792+
ISMT_LOG_ENTRIES * sizeof(u32),
793+
&priv->log_dma, GFP_KERNEL);
794+
if (!priv->log)
795+
return -ENOMEM;
796+
783797
return 0;
784798
}
785799

0 commit comments

Comments
 (0)