From patchwork Tue Oct 17 08:05:42 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Huacai Chen X-Patchwork-Id: 10011069 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E13DD600CC for ; Tue, 17 Oct 2017 08:05:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D1919287C5 for ; Tue, 17 Oct 2017 08:05:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C5E71287CD; Tue, 17 Oct 2017 08:05:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 62CDC287C5 for ; Tue, 17 Oct 2017 08:05:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934079AbdJQIFD (ORCPT ); Tue, 17 Oct 2017 04:05:03 -0400 Received: from smtpbg202.qq.com ([184.105.206.29]:32882 "EHLO smtpbg202.qq.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932957AbdJQIEw (ORCPT ); Tue, 17 Oct 2017 04:04:52 -0400 X-QQ-mid: bizesmtp2t1508227425tpvm6avuo Received: from software.domain.org (unknown [222.92.8.142]) by esmtp4.qq.com (ESMTP) with id ; Tue, 17 Oct 2017 16:03:43 +0800 (CST) X-QQ-SSF: 01100000008000F0FOF0B00A0000000 X-QQ-FEAT: EcrU/iQvn3uxvvTZDzIEobhhT1q142jIIOKfMAieF5MJqEEC1On1PTI9KNPhU qQoF1hXr87xkEb4tRYLHfu04Fav1hfIEGVvddCa203leGuzeoGamHAVoTJhLhu/8MAAkc92 duLRwdAdb+OWVOYXvqcSDz1RiSjKa2ll/ZIV6r/txf013AHLoitJL7yDbkbDZvqNkEWK4fM v5NQxGI9MDAlJN3OZKKfuNj577OkiArRpZYcn1V3ii6WeRCZ7p76qH7e8Ym+OSwCXx98tUk oBJWsvUk38bVK+sigeAcvNPdOQe/cxCg6vBa32kAR6xoqk X-QQ-GoodBg: 0 From: Huacai Chen To: Christoph Hellwig Cc: 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, Tejun Heo , linux-ide@vger.kernel.org, Huacai Chen , stable@vger.kernel.org Subject: [PATCH V8 5/5] libata: Align DMA buffer to dma_get_cache_alignment() Date: Tue, 17 Oct 2017 16:05:42 +0800 Message-Id: <1508227542-13165-5-git-send-email-chenhc@lemote.com> X-Mailer: git-send-email 2.7.0 In-Reply-To: <1508227542-13165-1-git-send-email-chenhc@lemote.com> References: <1508227542-13165-1-git-send-email-chenhc@lemote.com> X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:lemote.com:qybgforeign:qybgforeign1 X-QQ-Bgrelay: 1 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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; } /**