From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753203AbdJRNEC (ORCPT ); Wed, 18 Oct 2017 09:04:02 -0400 Received: from mail-qk0-f194.google.com ([209.85.220.194]:53522 "EHLO mail-qk0-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753114AbdJRND6 (ORCPT ); Wed, 18 Oct 2017 09:03:58 -0400 X-Google-Smtp-Source: ABhQp+SeI0CwYzUwPqma3P5+L4VCnFczinXx3W10rr23d3DmCc8UK1xFWeuCabyXCs8V3NbZOsyUPg== Date: Wed, 18 Oct 2017 06:03:53 -0700 From: Tejun Heo To: Huacai Chen Cc: Christoph Hellwig , Marek Szyprowski , Robin Murphy , Andrew Morton , Fuxin Zhang , linux-kernel@vger.kernel.org, Ralf Baechle , James Hogan , linux-mips@linux-mips.org, "James E . J . Bottomley" , "Martin K . Petersen" , linux-scsi@vger.kernel.org, linux-ide@vger.kernel.org, stable@vger.kernel.org Subject: Re: [PATCH V8 5/5] libata: Align DMA buffer to dma_get_cache_alignment() Message-ID: <20171018130353.GA1302522@devbig577.frc2.facebook.com> References: <1508227542-13165-1-git-send-email-chenhc@lemote.com> <1508227542-13165-5-git-send-email-chenhc@lemote.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1508227542-13165-5-git-send-email-chenhc@lemote.com> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Oct 17, 2017 at 04:05:42PM +0800, Huacai Chen wrote: > In non-coherent DMA mode, kernel uses cache flushing operations to > maintain I/O coherency, so in ata_do_dev_read_id() the DMA buffer > should be aligned to ARCH_DMA_MINALIGN. Otherwise, If a DMA buffer > and a kernel structure share a same cache line, and if the kernel > structure has dirty data, cache_invalidate (no writeback) will cause > data corruption. > > Cc: stable@vger.kernel.org > Signed-off-by: Huacai Chen > --- > drivers/ata/libata-core.c | 15 +++++++++++++-- > 1 file changed, 13 insertions(+), 2 deletions(-) > > diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c > index ee4c1ec..e134955 100644 > --- a/drivers/ata/libata-core.c > +++ b/drivers/ata/libata-core.c > @@ -1833,8 +1833,19 @@ static u32 ata_pio_mask_no_iordy(const struct ata_device *adev) > unsigned int ata_do_dev_read_id(struct ata_device *dev, > struct ata_taskfile *tf, u16 *id) > { > - return ata_exec_internal(dev, tf, NULL, DMA_FROM_DEVICE, > - id, sizeof(id[0]) * ATA_ID_WORDS, 0); > + u16 *devid; > + int res, size = sizeof(u16) * ATA_ID_WORDS; > + > + if (IS_ALIGNED((unsigned long)id, dma_get_cache_alignment(&dev->tdev))) > + res = ata_exec_internal(dev, tf, NULL, DMA_FROM_DEVICE, id, size, 0); > + else { > + devid = kmalloc(size, GFP_KERNEL); > + res = ata_exec_internal(dev, tf, NULL, DMA_FROM_DEVICE, devid, size, 0); > + memcpy(id, devid, size); > + kfree(devid); > + } > + > + return res; Hmm... I think it'd be a lot better to ensure that the buffers are aligned properly to begin with. There are only two buffers which are used for id reading - ata_port->sector_buf and ata_device->id. Both are embedded arrays but making them separately allocated aligned buffers shouldn't be difficult. Thanks. -- tejun