From e98edb5c673c95676ff26dd50d9d2b2fcb96de88 Mon Sep 17 00:00:00 2001 From: "Justin M. Forbes" Date: Fri, 12 Apr 2013 09:12:04 -0500 Subject: [PATCH] Fix forcedeth DMA check error (rhbz 928024) --- forcedeth-dma-error-check.patch | 132 ++++++++++++++++++++++++++++++++ kernel.spec | 9 +++ 2 files changed, 141 insertions(+) create mode 100644 forcedeth-dma-error-check.patch diff --git a/forcedeth-dma-error-check.patch b/forcedeth-dma-error-check.patch new file mode 100644 index 000000000..0baee2a61 --- /dev/null +++ b/forcedeth-dma-error-check.patch @@ -0,0 +1,132 @@ +This backtrace was recently reported on a 3.9 kernel: + +Actual results: from syslog /var/log/messsages: +kernel: [17539.340285] ------------[ cut here ]------------ +kernel: [17539.341012] WARNING: at lib/dma-debug.c:937 check_unmap+0x493/0x960() +kernel: [17539.341012] Hardware name: MS-7125 +kernel: [17539.341012] forcedeth 0000:00:0a.0: DMA-API: device driver failed to +check map error[device address=0x0000000013c88000] [size=544 bytes] [mapped as +page] +kernel: [17539.341012] Modules linked in: fuse ebtable_nat ipt_MASQUERADE +nf_conntrack_netbios_ns nf_conntrack_broadcast ip6table_nat nf_nat_ipv6 +ip6table_mangle ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 iptable_nat +nf_nat_ipv4 nf_nat iptable_mangle nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack +nf_conntrack bnep bluetooth rfkill ebtable_filter ebtables ip6table_filter +ip6_tables snd_hda_codec_hdmi snd_cmipci snd_mpu401_uart snd_hda_intel +snd_intel8x0 snd_opl3_lib snd_ac97_codec gameport snd_hda_codec snd_rawmidi +ac97_bus snd_hwdep snd_seq snd_seq_device snd_pcm snd_page_alloc snd_timer snd +k8temp soundcore serio_raw i2c_nforce2 forcedeth ata_generic pata_acpi nouveau +video mxm_wmi wmi i2c_algo_bit drm_kms_helper ttm drm i2c_core sata_sil pata_amd +sata_nv uinput +kernel: [17539.341012] Pid: 17340, comm: sshd Not tainted +3.9.0-0.rc4.git0.1.fc19.i686.PAE #1 +kernel: [17539.341012] Call Trace: +kernel: [17539.341012] [] warn_slowpath_common+0x6c/0xa0 +kernel: [17539.341012] [] ? check_unmap+0x493/0x960 +kernel: [17539.341012] [] ? check_unmap+0x493/0x960 +kernel: [17539.341012] [] warn_slowpath_fmt+0x33/0x40 +kernel: [17539.341012] [] check_unmap+0x493/0x960 +kernel: [17539.341012] [] ? sched_clock_cpu+0xdf/0x150 +kernel: [17539.341012] [] debug_dma_unmap_page+0x67/0x70 +kernel: [17539.341012] [] nv_unmap_txskb.isra.32+0x92/0x100 + +Its pretty plainly the result of an skb fragment getting unmapped without having +its initial mapping operation checked for errors. This patch corrects that. + +Signed-off-by: Neil Horman +CC: "David S. Miller" +--- + drivers/net/ethernet/nvidia/forcedeth.c | 41 ++++++++++++++++++++++++++++++++- + 1 file changed, 40 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c +index b62262c..5ae1247 100644 +--- a/drivers/net/ethernet/nvidia/forcedeth.c ++++ b/drivers/net/ethernet/nvidia/forcedeth.c +@@ -2200,6 +2200,7 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev) + struct ring_desc *start_tx; + struct ring_desc *prev_tx; + struct nv_skb_map *prev_tx_ctx; ++ struct nv_skb_map *tmp_tx_ctx = NULL, *start_tx_ctx = NULL; + unsigned long flags; + + /* add fragments to entries count */ +@@ -2261,12 +2262,31 @@ static netdev_tx_t nv_start_xmit(struct sk_buff *skb, struct net_device *dev) + do { + prev_tx = put_tx; + prev_tx_ctx = np->put_tx_ctx; ++ if (!start_tx_ctx) ++ start_tx_ctx = tmp_tx_ctx = np->put_tx_ctx; ++ + bcnt = (frag_size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : frag_size; + np->put_tx_ctx->dma = skb_frag_dma_map( + &np->pci_dev->dev, + frag, offset, + bcnt, + DMA_TO_DEVICE); ++ if (dma_mapping_error(&np->pci_dev->dev, np->put_tx_ctx->dma)) { ++ ++ /* Unwind the mapped fragments */ ++ do { ++ nv_unmap_txskb(np, start_tx_ctx); ++ if (unlikely(tmp_tx_ctx++ == np->last_tx_ctx)) ++ tmp_tx_ctx = np->first_tx_ctx; ++ } while (tmp_tx_ctx != np->put_tx_ctx); ++ kfree_skb(skb); ++ np->put_tx_ctx = start_tx_ctx; ++ u64_stats_update_begin(&np->swstats_tx_syncp); ++ np->stat_tx_dropped++; ++ u64_stats_update_end(&np->swstats_tx_syncp); ++ return NETDEV_TX_OK; ++ } ++ + np->put_tx_ctx->dma_len = bcnt; + np->put_tx_ctx->dma_single = 0; + put_tx->buf = cpu_to_le32(np->put_tx_ctx->dma); +@@ -2327,7 +2347,8 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb, + struct ring_desc_ex *start_tx; + struct ring_desc_ex *prev_tx; + struct nv_skb_map *prev_tx_ctx; +- struct nv_skb_map *start_tx_ctx; ++ struct nv_skb_map *start_tx_ctx = NULL; ++ struct nv_skb_map *tmp_tx_ctx = NULL; + unsigned long flags; + + /* add fragments to entries count */ +@@ -2392,11 +2413,29 @@ static netdev_tx_t nv_start_xmit_optimized(struct sk_buff *skb, + prev_tx = put_tx; + prev_tx_ctx = np->put_tx_ctx; + bcnt = (frag_size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : frag_size; ++ if (!start_tx_ctx) ++ start_tx_ctx = tmp_tx_ctx = np->put_tx_ctx; + np->put_tx_ctx->dma = skb_frag_dma_map( + &np->pci_dev->dev, + frag, offset, + bcnt, + DMA_TO_DEVICE); ++ ++ if (dma_mapping_error(&np->pci_dev->dev, np->put_tx_ctx->dma)) { ++ ++ /* Unwind the mapped fragments */ ++ do { ++ nv_unmap_txskb(np, start_tx_ctx); ++ if (unlikely(tmp_tx_ctx++ == np->last_tx_ctx)) ++ tmp_tx_ctx = np->first_tx_ctx; ++ } while (tmp_tx_ctx != np->put_tx_ctx); ++ kfree_skb(skb); ++ np->put_tx_ctx = start_tx_ctx; ++ u64_stats_update_begin(&np->swstats_tx_syncp); ++ np->stat_tx_dropped++; ++ u64_stats_update_end(&np->swstats_tx_syncp); ++ return NETDEV_TX_OK; ++ } + np->put_tx_ctx->dma_len = bcnt; + np->put_tx_ctx->dma_single = 0; + put_tx->bufhigh = cpu_to_le32(dma_high(np->put_tx_ctx->dma)); +-- +1.7.11.7 + +-- +To unsubscribe from this list: send the line "unsubscribe netdev" in +the body of a message to majordomo@vger.kernel.org +More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file diff --git a/kernel.spec b/kernel.spec index b0aa13f3f..5c8a8e54a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -749,6 +749,9 @@ Patch23006: fix-child-thread-introspection.patch #rhbz 949875 Patch23007: libsas-use-right-function-to-alloc-smp-response.patch +#rhbz 928024 +Patch23008: forcedeth-dma-error-check.patch + # END OF PATCH DEFINITIONS %endif @@ -1448,6 +1451,9 @@ ApplyPatch fix-child-thread-introspection.patch #rhbz 949875 ApplyPatch libsas-use-right-function-to-alloc-smp-response.patch +#rhbz 928024 +ApplyPatch forcedeth-dma-error-check.patch + # END OF PATCH APPLICATIONS %endif @@ -2281,6 +2287,9 @@ fi # ||----w | # || || %changelog +* Fri Apr 12 2013 Justin M. Forbes +- Fix forcedeth DMA check error (rhbz 928024) + * Thu Apr 11 2013 Dave Jones - Print out some extra debug information when we hit bad page tables.