From patchwork Mon Sep 15 11:33:27 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prarit Bhargava X-Patchwork-Id: 4904701 Return-Path: X-Original-To: patchwork-dmaengine@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 2AAE29F32F for ; Mon, 15 Sep 2014 11:31:10 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 8F30E20160 for ; Mon, 15 Sep 2014 11:34:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F27E52015A for ; Mon, 15 Sep 2014 11:33:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753918AbaIOLdo (ORCPT ); Mon, 15 Sep 2014 07:33:44 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37542 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753870AbaIOLdl (ORCPT ); Mon, 15 Sep 2014 07:33:41 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s8FBXYGn016542 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 15 Sep 2014 07:33:35 -0400 Received: from praritdesktop.bos.redhat.com (prarit-guest.khw.lab.eng.bos.redhat.com [10.16.186.145]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s8FBXXHd027801; Mon, 15 Sep 2014 07:33:33 -0400 From: Prarit Bhargava To: linux-kernel@vger.kernel.org Cc: Prarit Bhargava , Dan Williams , Vinod Koul , Dave Jiang , Bartlomiej Zolnierkiewicz , Kyungmin Park , dmaengine@vger.kernel.org Subject: [PATCH] ioatdma, fix dma mapping errors Date: Mon, 15 Sep 2014 07:33:27 -0400 Message-Id: <1410780807-23986-1-git-send-email-prarit@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 Sender: dmaengine-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dmaengine@vger.kernel.org X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Several systems are showing the following stack trace: WARNING: CPU: 0 PID: 2352 at lib/dma-debug.c:1140 check_unmap+0x4ee/0x9e0() ioatdma 0000:00:04.0: DMA-API: device driver failed to check map error[device address=0x0000000465bad000] [size=4096 bytes] [mapped as page] Modules linked in: ioatdma(E+) nfsv3 rpcsec_gss_krb5 nfsv4 dns_resolver nfs fscache cfg80211 rfkill x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm crct10dif_pclmul crc32_pclmul crc32c_intel cdc_ether ses ghash_clmulni_intel usbnet mii enclosure aesni_intel lrw gf128mul glue_helper iTCO_wdt shpchp ablk_helper iTCO_vendor_support cryptd pcspkr ipmi_devintf sb_edac lpc_ich edac_core mfd_core ipmi_si i2c_i801 wmi ipmi_msghandler nfsd auth_rpcgss nfs_acl lockd sunrpc xfs libcrc32c sd_mod crc_t10dif crct10dif_common mgag200 syscopyarea sysfillrect sysimgblt drm_kms_helper ttm igb drm ptp pps_core dca i2c_algo_bit i2ccore megaraid_sas dm_mirror dm_region_hash dm_log dm_mod [last unloaded: ioatdma] CPU: 0 PID: 2352 Comm: insmod Tainted: G E 3.17.0-rc4+ #14 Hardware name: HP ProLiant m300 Server Cartridge/, BIOS H02 01/30/2014 0000000000000009 ffff88007994b7d8 ffffffff816e7225 ffff88007994b820 ffff88007994b810 ffffffff8107e51d ffff88045fc56c00 ffff88046643ee90 ffffffff8338ccd0 0000000000000286 ffffffff81956629 ffff88007994b870 Call Trace: [] dump_stack+0x4d/0x66 [] warn_slowpath_common+0x7d/0xa0 [] warn_slowpath_fmt+0x4c/0x50 [] check_unmap+0x4ee/0x9e0 [] debug_dma_unmap_page+0x5f/0x70 [] ioat_xor_val_self_test+0x498/0xcf0 [ioatdma] [] ? kfree+0xda/0x2b0 [] ? ioat_dma_setup_interrupts+0x120/0x2d0 [ioatdma] [] ioat3_dma_self_test+0x1e/0x30 [ioatdma] [] ioat_probe+0xf4/0x110 [ioatdma] [] ioat3_dma_probe+0x198/0x3a0 [ioatdma] [] ioat_pci_probe+0x11e/0x1b0 [ioatdma] [] local_pci_probe+0x45/0xa0 [] ? pci_match_device+0xe5/0x110 [] pci_device_probe+0xd9/0x130 [] driver_probe_device+0x90/0x3c0 [] __driver_attach+0x93/0xa0 [] ? __device_attach+0x40/0x40 [] bus_for_each_dev+0x6b/0xb0 [] driver_attach+0x1e/0x20 [] bus_add_driver+0x188/0x260 [] ? 0xffffffffa0423000 [] driver_register+0x64/0xf0 [] __pci_register_driver+0x60/0x70 [] ioat_init_module+0x89/0x1000 [ioatdma] [] do_one_initcall+0xbc/0x200 [] ? __vunmap+0xd2/0x120 [] load_module+0x14ec/0x1b50 [] ? store_uevent+0x40/0x40 [] SyS_finit_module+0x86/0xb0 [] system_call_fastpath+0x16/0x1b ---[ end trace 1052ccbbc3db4d08 ]--- Mapped at: [] debug_dma_map_page+0x91/0x140 [] ioat_xor_val_self_test+0x1ce/0xcf0 [ioatdma] [] ioat3_dma_self_test+0x1e/0x30 [ioatdma] [] ioat_probe+0xf4/0x110 [ioatdma] [] ioat3_dma_probe+0x198/0x3a0 [ioatdma] This happens because the current ioatdma DMA test code does not check the return value of dma_map_page() calls with dma_mapping_error(). In addition, it was noticed that mapping for the variable dest_dma is free'd before the last use. This patch fixes these errors by initializing the dma_srcs[] array and checking the returns with dma_mapping_error(). Cc: Dan Williams Cc: Vinod Koul Cc: Dave Jiang Cc: Bartlomiej Zolnierkiewicz Cc: Kyungmin Park Cc: dmaengine@vger.kernel.org Signed-off-by: Prarit Bhargava --- drivers/dma/ioat/dma_v3.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index b9b38a1..8c51b5c 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -1265,9 +1265,17 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device) op = IOAT_OP_XOR; dest_dma = dma_map_page(dev, dest, 0, PAGE_SIZE, DMA_FROM_DEVICE); + if (dma_mapping_error(dev, dest_dma)) + goto dma_unmap; + for (i = 0; i < IOAT_NUM_SRC_TEST; i++) + dma_srcs[i] = DMA_ERROR_CODE; + for (i = 0; i < IOAT_NUM_SRC_TEST; i++) { dma_srcs[i] = dma_map_page(dev, xor_srcs[i], 0, PAGE_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma_srcs[i])) + goto dma_unmap; + } tx = dma->device_prep_dma_xor(dma_chan, dest_dma, dma_srcs, IOAT_NUM_SRC_TEST, PAGE_SIZE, DMA_PREP_INTERRUPT); @@ -1298,7 +1306,6 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device) goto dma_unmap; } - dma_unmap_page(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); for (i = 0; i < IOAT_NUM_SRC_TEST; i++) dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, DMA_TO_DEVICE); @@ -1313,6 +1320,8 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device) } dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); + dma_unmap_page(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); + /* skip validate if the capability is not present */ if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask)) goto free_resources; @@ -1327,8 +1336,13 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device) xor_val_result = 1; for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) + dma_srcs[i] = DMA_ERROR_CODE; + for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) { dma_srcs[i] = dma_map_page(dev, xor_val_srcs[i], 0, PAGE_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma_srcs[i])) + goto dma_unmap; + } tx = dma->device_prep_dma_xor_val(dma_chan, dma_srcs, IOAT_NUM_SRC_TEST + 1, PAGE_SIZE, &xor_val_result, DMA_PREP_INTERRUPT); @@ -1374,8 +1388,13 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device) xor_val_result = 0; for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) + dma_srcs[i] = DMA_ERROR_CODE; + for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) { dma_srcs[i] = dma_map_page(dev, xor_val_srcs[i], 0, PAGE_SIZE, DMA_TO_DEVICE); + if (dma_mapping_error(dev, dma_srcs[i])) + goto dma_unmap; + } tx = dma->device_prep_dma_xor_val(dma_chan, dma_srcs, IOAT_NUM_SRC_TEST + 1, PAGE_SIZE, &xor_val_result, DMA_PREP_INTERRUPT); @@ -1417,14 +1436,18 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device) goto free_resources; dma_unmap: if (op == IOAT_OP_XOR) { - dma_unmap_page(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); + if (dest_dma != DMA_ERROR_CODE) + dma_unmap_page(dev, dest_dma, PAGE_SIZE, + DMA_FROM_DEVICE); for (i = 0; i < IOAT_NUM_SRC_TEST; i++) - dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, - DMA_TO_DEVICE); + if (dma_srcs[i] != DMA_ERROR_CODE) + dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, + DMA_TO_DEVICE); } else if (op == IOAT_OP_XOR_VAL) { for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) - dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, - DMA_TO_DEVICE); + if (dma_srcs[i] != DMA_ERROR_CODE) + dma_unmap_page(dev, dma_srcs[i], PAGE_SIZE, + DMA_TO_DEVICE); } free_resources: dma->device_free_chan_resources(dma_chan);