On Mon, 2014-08-04 at 10:20 +0200, Maurizio Lombardi wrote: > In the bnx2fc_map_sg() function, the original behaviour is to > allocate the DMA memory by directly calling dma_map_sg() > instead of using scsi_dma_map(). > > In contrast, bnx2fc_unmap_sg_list() calls scsi_dma_unmap(). > > The problem is that bnx2fc_map_sg() passes to the dma_map_sg() function > the pointer to the "device" structure taken from pci_dev > and not from Scsi_Host (as scsi_dma_map/unmap() do). > Great find, Maurizio, Thanks again.
> In some circumstances, the two devices may be different and the > DMA library will be unable to find the correct entry > when freeing the memory. > I'm curious at how the hba->pcidev->dev in the dma_map_sg call could end up being different from the scsi_cmnd's device->host->dma_dev... Can you share the test scenario? > This patch fixes the bug by replacing dma_map_sg() with scsi_dma_map(). > > [56068.747547] WARNING: CPU: 1 PID: 12048 at lib/dma-debug.c:1080 > check_unmap+0x90a/0xa00() > [56068.785706] fcoe ctlr_0: DMA-API: device driver tries to free DMA memory > it has not allocated [device address=0x0000000202a1aa00] [size=36 bytes] > [56068.846700] Modules linked in: 8021q garp stp mrp llc fcoe bnx2fc cnic uio > libfcoe libfc scsi_transport_fc scsi_tgt cfg80211 rfkill x86_pkg_temp_thermal > coretemp kvm_intel kvm crct10dif_pclmul iTCO_wdt crc32_pclmul gpio_ich > crc32c_intel iTCO_vendor_support ghash_clmulni_intel joydev lpc_ich hpwdt > nfsd mfd_core microcode hpilo serio_raw pcspkr ipmi_si auth_rpcgss nfs_acl > lockd shpchp ipmi_msghandler sunrpc xfs e1000e mgag200 i2c_algo_bit > drm_kms_helper ttm ptp drm ata_generic pata_acpi bnx2x i2c_core pps_core hpsa > mdio libcrc32c > [56069.077673] CPU: 1 PID: 12048 Comm: bnx2fc_thread/1 Not tainted > 3.16.0-rc7+ #1 > [56069.115286] Hardware name: HP ProLiant DL120 G7, BIOS J01 07/01/2013 > [56069.145091] 0000000000000009 ffff8801f36dbbd8 ffffffff816c323a > ffff8801f36dbc20 > [56069.185083] ffff8801f36dbc10 ffffffff8108350d ffff8800e9880960 > ffff8801f36dbd00 > [56069.222738] 0000000000000024 0000000202a1aa00 0000000000000001 > ffff8801f36dbc70 > [56069.263389] Call Trace: > [56069.275945] [<ffffffff816c323a>] dump_stack+0x45/0x56 > [56069.302133] [<ffffffff8108350d>] warn_slowpath_common+0x7d/0xa0 > [56069.334050] [<ffffffff8108357c>] warn_slowpath_fmt+0x4c/0x50 > [56069.364537] [<ffffffff8135214c>] ? debug_dma_mapping_error+0x7c/0x90 > [56069.398268] [<ffffffff8135423a>] check_unmap+0x90a/0xa00 > [56069.423761] [<ffffffff81354485>] debug_dma_unmap_sg+0x65/0x110 > [56069.474134] [<ffffffff8145ee93>] scsi_dma_unmap+0x73/0xb0 > [56069.499313] [<ffffffffa04cd9bc>] bnx2fc_process_scsi_cmd_compl+0xcc/0x2a0 > [bnx2fc] > [56069.535588] [<ffffffffa04c759b>] bnx2fc_process_cq_compl+0x21b/0x280 > [bnx2fc] > [56069.570311] [<ffffffffa04c2d76>] bnx2fc_percpu_io_thread+0x106/0x180 > [bnx2fc] > [56069.604560] [<ffffffffa04c2c70>] ? bnx2fc_get_src_mac+0x20/0x20 [bnx2fc] > [56069.635801] [<ffffffff810a4392>] kthread+0xd2/0xf0 > [56069.659421] [<ffffffff810a42c0>] ? kthread_create_on_node+0x170/0x170 > [56069.689416] [<ffffffff816ca3bc>] ret_from_fork+0x7c/0xb0 > [56069.715510] [<ffffffff810a42c0>] ? kthread_create_on_node+0x170/0x170 > > Signed-off-by: Maurizio Lombardi <mlomb...@redhat.com> > --- > drivers/scsi/bnx2fc/bnx2fc_io.c | 6 ++---- > 1 file changed, 2 insertions(+), 4 deletions(-) > > diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c > index 7bc47fc..fe2cd9b 100644 > --- a/drivers/scsi/bnx2fc/bnx2fc_io.c > +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c > @@ -1640,8 +1640,6 @@ static int bnx2fc_split_bd(struct bnx2fc_cmd *io_req, > u64 addr, int sg_len, > > static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req) > { > - struct bnx2fc_interface *interface = io_req->port->priv; > - struct bnx2fc_hba *hba = interface->hba; > struct scsi_cmnd *sc = io_req->sc_cmd; > struct fcoe_bd_ctx *bd = io_req->bd_tbl->bd_tbl; > struct scatterlist *sg; > @@ -1653,8 +1651,8 @@ static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req) > u64 addr; > int i; > > - sg_count = dma_map_sg(&hba->pcidev->dev, scsi_sglist(sc), > - scsi_sg_count(sc), sc->sc_data_direction); > + sg_count = scsi_dma_map(sc); > + I see that scsi_dma_map could possibly return a -ENOMEM. It would be best if we also add the check for sg_count being < 0 and return the bd_count or 0. > scsi_for_each_sg(sc, sg, sg_count, i) { > sg_len = sg_dma_len(sg); > addr = sg_dma_address(sg); -- To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html