From: Denis Kirjanov Date: Sun, 14 Apr 2013 21:11:29 +0000 (+0000) Subject: sis900: check for DMA map errors X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=1e8edc2ab35da30b08b008c26822ec956052bf4b;p=linux-beck.git sis900: check for DMA map errors The first backtrace appears on tx path with DMA mapping operations debug enabled. [ 345.637919] ------------[ cut here ]------------ [ 345.637971] WARNING: at lib/dma-debug.c:937 check_unmap+0x4df/0x910() [ 345.637977] Hardware name: System Name [ 345.637987] sis900 0000:00:01.1: DMA-API: device driver failed to check map error[device address=0x000000000d4aed02] [si ze=60 bytes] [mapped as single] [ 345.637993] Modules linked in: bridge stp llc dmfe sundance 3c59x sis900 [ 345.638022] Pid: 0, comm: swapper Not tainted 3.9.0-rc6+ #4 [ 345.638028] Call Trace: [ 345.638042] [] ? check_unmap+0x4df/0x910 [ 345.638059] [] warn_slowpath_common+0x7c/0xa0 [ 345.638070] [] ? check_unmap+0x4df/0x910 [ 345.638081] [] warn_slowpath_fmt+0x2e/0x30 [ 345.638092] [] check_unmap+0x4df/0x910 [ 345.638107] [] ? save_stack_trace+0x2b/0x50 [ 345.638120] [] ? mark_lock+0x31e/0x5d0 [ 345.638132] [] ? __lock_acquire+0x4ec/0x7d0 [ 345.638143] [] debug_dma_unmap_page+0x6d/0x80 [ 345.638166] [] sis900_interrupt+0x49c/0x860 [sis900] [ 345.638195] [] handle_irq_event_percpu+0x43/0x1c0 [ 345.638206] [] ? handle_irq_event+0x2e/0x60 [ 345.638217] [] handle_irq_event+0x37/0x60 [ 345.638235] [] ? irq_set_chip_data+0x40/0x40 [ 345.638246] [] handle_level_irq+0x52/0xa0 [ 345.638251] [] ? do_IRQ+0x39/0xa0 [ 345.638293] [] ? common_interrupt+0x31/0x36 [ 345.638347] [] ? br_flood_forward+0x12/0x20 [bridge] [ 345.638364] [] ? br_dev_queue_push_xmit+0x60/0x60 [bridge] [ 345.638381] [] ? br_handle_frame_finish+0x25b/0x280 [bridge] [ 345.638399] [] ? br_handle_frame+0x193/0x290 [bridge] [ 345.638416] [] ? br_handle_frame_finish+0x280/0x280 [bridge] [ 345.638431] [] ? __netif_receive_skb_core+0x1d7/0x710 [ 345.638442] [] ? __netif_receive_skb_core+0x69/0x710 [ 345.638454] [] ? __netif_receive_skb+0x21/0x70 [ 345.638464] [] ? process_backlog+0x85/0x130 [ 345.638476] [] ? net_rx_action+0xfb/0x1d0 [ 345.638497] [] ? __do_softirq+0xa8/0x1f0 [ 345.638527] [] ? _raw_spin_unlock+0x1d/0x20 [ 345.638538] [] ? handle_irq+0x20/0xd0 [ 345.638550] [] ? irq_exit+0x97/0xa0 [ 345.638560] [] ? do_IRQ+0x42/0xa0 [ 345.638580] [] ? hrtimer_start+0x23/0x30 [ 345.638580] [] ? common_interrupt+0x31/0x36 [ 345.638580] [] ? default_idle+0x33/0xc0 [ 345.638580] [] ? cpu_idle+0x4c/0x70 [ 345.638580] [] ? rest_init+0xa0/0xb0 [ 345.638580] [] ? reciprocal_value+0x50/0x50 [ 345.638580] [] ? start_kernel+0x28f/0x320 [ 345.638580] [] ? repair_env_string+0x60/0x60 [ 345.638580] [] ? i386_start_kernel+0x39/0xa0 [ 345.638580] ---[ end trace a244264b69b8a7ae ]--- [ 345.638580] Mapped at: [ 345.638580] [] debug_dma_map_page+0x65/0x110 [ 345.638580] [] sis900_start_xmit+0x129/0x210 [sis900] [ 345.638580] [] dev_hard_start_xmit+0x1b7/0x530 [ 345.638580] [] sch_direct_xmit+0x8e/0x280 [ 345.638580] [] dev_queue_xmit+0x1a9/0x5b0 Signed-off-by: Denis Kirjanov Signed-off-by: David S. Miller --- diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index e45829628d5f..eb4aea3fe793 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -1187,8 +1187,14 @@ sis900_init_rx_ring(struct net_device *net_dev) } sis_priv->rx_skbuff[i] = skb; sis_priv->rx_ring[i].cmdsts = RX_BUF_SIZE; - sis_priv->rx_ring[i].bufptr = pci_map_single(sis_priv->pci_dev, - skb->data, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + sis_priv->rx_ring[i].bufptr = pci_map_single(sis_priv->pci_dev, + skb->data, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + if (unlikely(pci_dma_mapping_error(sis_priv->pci_dev, + sis_priv->rx_ring[i].bufptr))) { + dev_kfree_skb(skb); + sis_priv->rx_skbuff[i] = NULL; + break; + } } sis_priv->dirty_rx = (unsigned int) (i - NUM_RX_DESC); @@ -1621,6 +1627,14 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev) /* set the transmit buffer descriptor and enable Transmit State Machine */ sis_priv->tx_ring[entry].bufptr = pci_map_single(sis_priv->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); + if (unlikely(pci_dma_mapping_error(sis_priv->pci_dev, + sis_priv->tx_ring[entry].bufptr))) { + dev_kfree_skb(skb); + sis_priv->tx_skbuff[entry] = NULL; + net_dev->stats.tx_dropped++; + spin_unlock_irqrestore(&sis_priv->lock, flags); + return NETDEV_TX_OK; + } sis_priv->tx_ring[entry].cmdsts = (OWN | skb->len); sw32(cr, TxENA | sr32(cr)); @@ -1824,9 +1838,15 @@ static int sis900_rx(struct net_device *net_dev) refill_rx_ring: sis_priv->rx_skbuff[entry] = skb; sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE; - sis_priv->rx_ring[entry].bufptr = + sis_priv->rx_ring[entry].bufptr = pci_map_single(sis_priv->pci_dev, skb->data, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + if (unlikely(pci_dma_mapping_error(sis_priv->pci_dev, + sis_priv->rx_ring[entry].bufptr))) { + dev_kfree_skb_irq(skb); + sis_priv->rx_skbuff[entry] = NULL; + break; + } } sis_priv->cur_rx++; entry = sis_priv->cur_rx % NUM_RX_DESC; @@ -1852,9 +1872,15 @@ refill_rx_ring: } sis_priv->rx_skbuff[entry] = skb; sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE; - sis_priv->rx_ring[entry].bufptr = + sis_priv->rx_ring[entry].bufptr = pci_map_single(sis_priv->pci_dev, skb->data, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); + if (unlikely(pci_dma_mapping_error(sis_priv->pci_dev, + sis_priv->rx_ring[entry].bufptr))) { + dev_kfree_skb_irq(skb); + sis_priv->rx_skbuff[entry] = NULL; + break; + } } } /* re-enable the potentially idle receive state matchine */