From patchwork Thu Jan 4 18:18:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Radu Rendec X-Patchwork-Id: 855763 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="U6Gt6iGL"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zCGJf6Mshz9s7h for ; Fri, 5 Jan 2018 05:18:42 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751762AbeADSSk (ORCPT ); Thu, 4 Jan 2018 13:18:40 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:44640 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751870AbeADSSh (ORCPT ); Thu, 4 Jan 2018 13:18:37 -0500 Received: by mail-wm0-f68.google.com with SMTP id t8so5048079wmc.3 for ; Thu, 04 Jan 2018 10:18:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=+1ItgHaqgBYg0mc5XxhctJS/+s02yfyhy6MowPj3lh4=; b=U6Gt6iGLiNzAKUJ5/sFAkRf5YHxYh/+hrLA6Q5e7GhUMA2xpBUxUHkB0K+daou0Yzy tYpV9MrKJrXb2lWCFNsM6MoAzLyeCRLnzy6BgWEYsocaMrPavc7dugJrkAsfq8NmQwpJ GakPuHtUIBp71bsZXihiF/Riv30AU+RgmzbaWx8H5sbtXc/rrllE0dRysEI2ul4/8P0q pNNEyS84qmlqAn4Qyw8zaUv6H1w+LHajUF6dk2gC3EkQZHrZb4QfaXqPHg6sEbmJB2Mv bz3C/ro/txhvp8VRei6jE+PIAfhoX6dtH0qIhj6UF7nc7rHE1j4tou9MSJbO/C4tp9Q+ FDzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=+1ItgHaqgBYg0mc5XxhctJS/+s02yfyhy6MowPj3lh4=; b=Tf1K50v+BO3hLcK5QbnRpKVophCCOh/pYv8xatz5YKVEq46obZGdc7JKkVnqrRurJA adCXyq4vTq0D3JAgNP08I/4oWDHGd0XqtOoUdpaJlslSCaQ3bkby+G6Xb96M/BIlWZJU LHrONNSA4MXB8upoYiwTNRRnc050LPcd67W5TWlBW9kHDMioRpjPq/LTmTboDN7hD+lE G6nXul7QEEoq+Q8rqFq+CHEYHlpuywHI/j5KNQT4M1Gdfs2MjNWUtvKJFvizzWxjXCwn oV6atdmciPeY+M/k/qpVWvRVCxX/LlPFP5vlyVRumXlTkxMJMp4nsU08NOxYWhtulvgN sU5w== X-Gm-Message-State: AKGB3mJPeEPuQFykvyZNAgSC8e0yUFcqtQzbrw/GN0CuorEeToWyQ/jX e9pMUX4burNKvSjL50TwFb9rRyoE X-Google-Smtp-Source: ACJfBotYP+VUr4rRlxe5KcMIK/G0GOWzDzjneMSQ4YwOZu630ixHB8XMRnVSTpek1HT2XSekzjIwwg== X-Received: by 10.80.213.154 with SMTP id v26mr584078edi.170.1515089916069; Thu, 04 Jan 2018 10:18:36 -0800 (PST) Received: from rrendec.ire.aristanetworks.com ([217.173.96.166]) by smtp.gmail.com with ESMTPSA id o15sm2508661edk.25.2018.01.04.10.18.35 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 04 Jan 2018 10:18:35 -0800 (PST) From: Radu Rendec To: Neil Horman Cc: linux-i2c@vger.kernel.org Subject: [PATCH v2] i2c: ismt: 16-byte align the DMA buffer address Date: Thu, 4 Jan 2018 18:18:13 +0000 Message-Id: <20180104181813.25474-1-radu.rendec@gmail.com> X-Mailer: git-send-email 2.13.6 Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org 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 --- drivers/i2c/busses/i2c-ismt.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index b51adffa4841..f4f806135119 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c @@ -172,7 +172,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 */ }; /** @@ -320,7 +320,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); @@ -393,11 +393,12 @@ 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); 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)); @@ -446,8 +447,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"); @@ -466,9 +467,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"); @@ -486,9 +487,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: @@ -499,8 +500,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"); @@ -527,8 +528,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"); @@ -557,18 +558,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; }