From 902836e418b2c07cccb131d928d9718fe4a7888f Mon Sep 17 00:00:00 2001 From: Aravind Mani Date: Wed, 26 Aug 2020 10:43:23 +0530 Subject: [PATCH 1/3] Fix i2c ISMT DMA buffer alignment issue --- patch/ismt_fix.patch | 144 +++++++++++++++++++++++++++++++++++++++++++ patch/series | 1 + 2 files changed, 145 insertions(+) create mode 100644 patch/ismt_fix.patch diff --git a/patch/ismt_fix.patch b/patch/ismt_fix.patch new file mode 100644 index 000000000..fb3a5a15a --- /dev/null +++ b/patch/ismt_fix.patch @@ -0,0 +1,144 @@ +--- +From Commit ID: 5cd5f0bb0d9c32876b3d86b70fb45da10d028be7 +Subject: I2C ISMT 16-byte align the DMA buffer address + +Use only a portion of the data buffer for DMA transfers, which is always +16-byte aligned. This makes the DMA buffer address 16-byte aligned and +compensates for spurious hardware parity errors that may appear when the +DMA buffer address is not 16-byte aligned. + +The data buffer is enlarged in order to accommodate any possible 16-byte +alignment offset and changes the DMA code to only use a portion of the +data buffer, which is 16-byte aligned. + +The symptom of the hardware issue is the same as the one addressed in +v3.12-rc2-5-gbf41691 and manifests by transfers failing with EIO, with +bit 9 being set in the ERRSTS register. + +Signed-off-by: Radu Rendec +Acked-by: Neil Horman +Signed-off-by: Wolfram Sang +--- + +diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c +index c97b48c..848c3a7 100644 +--- a/drivers/i2c/busses/i2c-ismt.c ++++ b/drivers/i2c/busses/i2c-ismt.c +@@ -173,7 +173,7 @@ struct ismt_priv { + dma_addr_t io_rng_dma; /* descriptor HW base addr */ + u8 head; /* ring buffer head pointer */ + struct completion cmp; /* interrupt completion */ +- u8 dma_buffer[I2C_SMBUS_BLOCK_MAX + 1]; /* temp R/W data buffer */ ++ u8 buffer[I2C_SMBUS_BLOCK_MAX + 16]; /* temp R/W data buffer */ + }; + + /** +@@ -324,7 +324,7 @@ static int ismt_process_desc(const struct ismt_desc *desc, + struct ismt_priv *priv, int size, + char read_write) + { +- u8 *dma_buffer = priv->dma_buffer; ++ u8 *dma_buffer = PTR_ALIGN(&priv->buffer[0], 16); + + dev_dbg(&priv->pci_dev->dev, "Processing completed descriptor\n"); + __ismt_desc_dump(&priv->pci_dev->dev, desc); +@@ -397,6 +397,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + struct ismt_desc *desc; + struct ismt_priv *priv = i2c_get_adapdata(adap); + struct device *dev = &priv->pci_dev->dev; ++ u8 *dma_buffer = PTR_ALIGN(&priv->buffer[0], 16); + + if (delay > 0) + udelay(delay); +@@ -404,8 +405,8 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + desc = &priv->hw[priv->head]; + + /* Initialize the DMA buffer */ +- memset(priv->dma_buffer, 0, sizeof(priv->dma_buffer)); +- ++ memset(priv->buffer, 0, sizeof(priv->buffer)); ++ + /* Initialize the descriptor */ + memset(desc, 0, sizeof(struct ismt_desc)); + desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write); +@@ -453,8 +454,8 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + desc->wr_len_cmd = 2; + dma_size = 2; + dma_direction = DMA_TO_DEVICE; +- priv->dma_buffer[0] = command; +- priv->dma_buffer[1] = data->byte; ++ dma_buffer[0] = command; ++ dma_buffer[1] = data->byte; + } else { + /* Read Byte */ + dev_dbg(dev, "I2C_SMBUS_BYTE_DATA: READ\n"); +@@ -473,9 +474,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + desc->wr_len_cmd = 3; + dma_size = 3; + dma_direction = DMA_TO_DEVICE; +- priv->dma_buffer[0] = command; +- priv->dma_buffer[1] = data->word & 0xff; +- priv->dma_buffer[2] = data->word >> 8; ++ dma_buffer[0] = command; ++ dma_buffer[1] = data->word & 0xff; ++ dma_buffer[2] = data->word >> 8; + } else { + /* Read Word */ + dev_dbg(dev, "I2C_SMBUS_WORD_DATA: READ\n"); +@@ -493,9 +494,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + desc->rd_len = 2; + dma_size = 3; + dma_direction = DMA_BIDIRECTIONAL; +- priv->dma_buffer[0] = command; +- priv->dma_buffer[1] = data->word & 0xff; +- priv->dma_buffer[2] = data->word >> 8; ++ dma_buffer[0] = command; ++ dma_buffer[1] = data->word & 0xff; ++ dma_buffer[2] = data->word >> 8; + break; + + case I2C_SMBUS_BLOCK_DATA: +@@ -506,8 +507,8 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + dma_direction = DMA_TO_DEVICE; + desc->wr_len_cmd = dma_size; + desc->control |= ISMT_DESC_BLK; +- priv->dma_buffer[0] = command; +- memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1); ++ dma_buffer[0] = command; ++ memcpy(&dma_buffer[1], &data->block[1], dma_size - 1); + } else { + /* Block Read */ + dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: READ\n"); +@@ -534,8 +535,8 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + dma_direction = DMA_TO_DEVICE; + desc->wr_len_cmd = dma_size; + desc->control |= ISMT_DESC_I2C; +- priv->dma_buffer[0] = command; +- memcpy(&priv->dma_buffer[1], &data->block[1], dma_size - 1); ++ dma_buffer[0] = command; ++ memcpy(&dma_buffer[1], &data->block[1], dma_size - 1); + } else { + /* i2c Block Read */ + dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: READ\n"); +@@ -564,18 +565,18 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + if (dma_size != 0) { + dev_dbg(dev, " dev=%p\n", dev); + dev_dbg(dev, " data=%p\n", data); +- dev_dbg(dev, " dma_buffer=%p\n", priv->dma_buffer); ++ dev_dbg(dev, " dma_buffer=%p\n", dma_buffer); + dev_dbg(dev, " dma_size=%d\n", dma_size); + dev_dbg(dev, " dma_direction=%d\n", dma_direction); + + dma_addr = dma_map_single(dev, +- priv->dma_buffer, ++ dma_buffer, + dma_size, + dma_direction); + + if (dma_mapping_error(dev, dma_addr)) { + dev_err(dev, "Error in mapping dma buffer %p\n", +- priv->dma_buffer); ++ dma_buffer); + return -EIO; + } + diff --git a/patch/series b/patch/series index a18f6d71c..3f0adbbd4 100644 --- a/patch/series +++ b/patch/series @@ -57,6 +57,7 @@ linux-4.13-thermal-intel_pch_thermal-Fix-enable-check-on.patch 0024-config-mellanox-fan-configuration.patch 0025-mlxsw-qsfp_sysfs-Remove-qsfp-valid-time.patch 0026-4.14.-15-56-platform-x86-mlx-platform-Fix-parent-device-in-i2c-mux-reg-device-registration.patch +ismt_fix.patch # # This series applies on GIT commit 1451b36b2b0d62178e42f648d8a18131af18f7d8 # Tkernel-sched-core-fix-cgroup-fork-race.patch From e6095cb7a18649ac20c29a16b602f11c6f71eee0 Mon Sep 17 00:00:00 2001 From: Aravind Mani <53524901+aravindmani-1@users.noreply.github.com> Date: Wed, 26 Aug 2020 10:56:32 +0530 Subject: [PATCH 2/3] Rename ismt_fix.patch to fix_ismt_alignment_issue.patch --- patch/{ismt_fix.patch => fix_ismt_alignment_issue.patch} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename patch/{ismt_fix.patch => fix_ismt_alignment_issue.patch} (100%) diff --git a/patch/ismt_fix.patch b/patch/fix_ismt_alignment_issue.patch similarity index 100% rename from patch/ismt_fix.patch rename to patch/fix_ismt_alignment_issue.patch From 217da366afdfbbe0fa852b0d959dbdcc8df8aa0d Mon Sep 17 00:00:00 2001 From: Aravind Mani <53524901+aravindmani-1@users.noreply.github.com> Date: Wed, 26 Aug 2020 10:57:14 +0530 Subject: [PATCH 3/3] Update series --- patch/series | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patch/series b/patch/series index 3f0adbbd4..af0f55192 100644 --- a/patch/series +++ b/patch/series @@ -57,7 +57,7 @@ linux-4.13-thermal-intel_pch_thermal-Fix-enable-check-on.patch 0024-config-mellanox-fan-configuration.patch 0025-mlxsw-qsfp_sysfs-Remove-qsfp-valid-time.patch 0026-4.14.-15-56-platform-x86-mlx-platform-Fix-parent-device-in-i2c-mux-reg-device-registration.patch -ismt_fix.patch +fix_ismt_alignment_issue.patch # # This series applies on GIT commit 1451b36b2b0d62178e42f648d8a18131af18f7d8 # Tkernel-sched-core-fix-cgroup-fork-race.patch