On Sunday 25 November 2007 01:27:54 Francois Romieu wrote: > Francois Romieu <[EMAIL PROTECTED]> : > > Alistair John Strachan <[EMAIL PROTECTED]> : > > [...] > > > > > The "choke" affects other devices on the system too, notably libata, > > > which does not recover gracefully. In my logs, I see a stream of: > > > > > > DMA: Out of SW-IOMMU space for 7222 bytes at device 0000:04:00.0 > > > DMA: Out of SW-IOMMU space for 7222 bytes at device 0000:04:00.0 > > > > You are using jumbo frames, aren't you ? > > See below for my late night crap. At least it should avoid the driver > issuing Rx/Tx DMA with the single static buffer of lib/swiotlb.c > (io_tlb_overflow_buffer). Ghee.
No improvement. It might be possible to reproduce the problem on your end if you add iommu support and force enable the swiotlb (which should be possible even with <4GB RAM). > diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c > index 1f647b9..72a7370 100644 > --- a/drivers/net/r8169.c > +++ b/drivers/net/r8169.c > @@ -2262,10 +2262,16 @@ static struct sk_buff *rtl8169_alloc_rx_skb(struct > pci_dev *pdev, mapping = pci_map_single(pdev, skb->data, rx_buf_sz, > PCI_DMA_FROMDEVICE); > > + if (pci_dma_mapping_error(mapping)) > + goto err_kfree_skb; > + > rtl8169_map_to_asic(desc, mapping, rx_buf_sz); > out: > return skb; > > +err_kfree_skb: > + dev_kfree_skb(skb); > + skb = NULL; > err_out: > rtl8169_make_unusable_by_asic(desc); > goto out; > @@ -2486,6 +2492,7 @@ static int rtl8169_xmit_frags(struct rtl8169_private > *tp, struct sk_buff *skb, dma_addr_t mapping; > u32 status, len; > void *addr; > + int rc; > > entry = (entry + 1) % NUM_TX_DESC; > > @@ -2493,6 +2500,22 @@ static int rtl8169_xmit_frags(struct rtl8169_private > *tp, struct sk_buff *skb, len = frag->size; > addr = ((void *) page_address(frag->page)) + frag->page_offset; > mapping = pci_map_single(tp->pci_dev, addr, len, > PCI_DMA_TODEVICE); > + rc = pci_dma_mapping_error(mapping); > + if (unlikely(rc < 0)) { > + while (cur_frag-- > 0) { > + frag = info->frags + cur_frag; > + entry = (entry - 1) % NUM_TX_DESC; > + txd = tp->TxDescArray + entry; > + len = frag->size; > + mapping = le64_to_cpu(txd->addr); > + pci_unmap_single(tp->pci_dev, mapping, len, > + PCI_DMA_TODEVICE); > + txd->opts1 = 0x00; > + txd->opts2 = 0x00; > + txd->addr = 0x00; > + } > + return rc; > + } > > /* anti gcc 2.95.3 bugware (sic) */ > status = opts1 | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); > @@ -2534,13 +2557,13 @@ static inline u32 rtl8169_tso_csum(struct sk_buff > *skb, struct net_device *dev) static int rtl8169_start_xmit(struct sk_buff > *skb, struct net_device *dev) { > struct rtl8169_private *tp = netdev_priv(dev); > - unsigned int frags, entry = tp->cur_tx % NUM_TX_DESC; > + unsigned int entry = tp->cur_tx % NUM_TX_DESC; > struct TxDesc *txd = tp->TxDescArray + entry; > void __iomem *ioaddr = tp->mmio_addr; > dma_addr_t mapping; > u32 status, len; > u32 opts1; > - int ret = NETDEV_TX_OK; > + int frags, ret = NETDEV_TX_OK; > > if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) { > if (netif_msg_drv(tp)) { > @@ -2557,7 +2580,11 @@ static int rtl8169_start_xmit(struct sk_buff *skb, > struct net_device *dev) opts1 = DescOwn | rtl8169_tso_csum(skb, dev); > > frags = rtl8169_xmit_frags(tp, skb, opts1); > - if (frags) { > + if (frags < 0) { > + printk(KERN_ERR "%s: PCI mapping failure (%d).\n", dev->name, > + frags); > + goto err_busy; > + } else if (frags > 0) { > len = skb_headlen(skb); > opts1 |= FirstFrag; > } else { > @@ -2605,6 +2632,7 @@ out: > > err_stop: > netif_stop_queue(dev); > +err_busy: > ret = NETDEV_TX_BUSY; > err_update_stats: > dev->stats.tx_dropped++; -- Cheers, Alistair. 137/1 Warrender Park Road, Edinburgh, UK. - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html