Подробности

[В начало]

Проблема в реализации № L0009

Краткое описание

drivers/net/znet.c: Вызов функции might_sleep из контекста spin_lock_irqsave/spin_unlock_irqrestore

Подробное описание

Драйвер drivers/net/znet.c вызывает функцию might_sleep в атомарном контексте. Функция free_dma, которая содержит путь к might_sleep, вызывается после claim_dma_lock (внутри spin_lock_irqsave - кроме архитектуры aprisc): .drivers/net/znet.c:

 168 static int znet_request_resources (struct net_device *dev)
...
 189        flags = claim_dma_lock();
 190        free_dma (znet->tx_dma);
 191        release_dma_lock (flags);
...
Путь до might_sleep из from znet_request_resources:
  • znet_request_resources вызывает free_dma в arch/blackfin/kernel/bfin_dma_5xx.c:181
  • free_dma выызвает might_lsep в arch/blackfin/kernel/bfin_dma_5xx.c:195
  • Способы устранения

    drivers/net/znet.c |    8 --------
     1 files changed, 0 insertions(+), 8 deletions(-)
    
    diff --git a/drivers/net/znet.c b/drivers/net/znet.c
    index a0384b6..b423473 100644
    --- a/drivers/net/znet.c
    +++ b/drivers/net/znet.c
    @@ -169,7 +169,6 @@ static void znet_tx_timeout (struct net_device *dev);
     static int znet_request_resources (struct net_device *dev)
     {
            struct znet_private *znet = netdev_priv(dev);
    -       unsigned long flags;
     
            if (request_irq (dev->irq, &znet_interrupt, 0, "ZNet", dev))
                    goto failed;
    @@ -187,13 +186,9 @@ static int znet_request_resources (struct net_device *dev)
      free_sia:
            release_region (znet->sia_base, znet->sia_size);
      free_tx_dma:
    -       flags = claim_dma_lock();
            free_dma (znet->tx_dma);
    -       release_dma_lock (flags);
      free_rx_dma:
    -       flags = claim_dma_lock();
            free_dma (znet->rx_dma);
    -       release_dma_lock (flags);
      free_irq:
            free_irq (dev->irq, dev);
      failed:
    @@ -203,14 +198,11 @@ static int znet_request_resources (struct net_device *dev)
     static void znet_release_resources (struct net_device *dev)
     {
            struct znet_private *znet = netdev_priv(dev);
    -       unsigned long flags;
     
            release_region (znet->sia_base, znet->sia_size);
            release_region (dev->base_addr, znet->io_size);
    -       flags = claim_dma_lock();
            free_dma (znet->tx_dma);
            free_dma (znet->rx_dma);
    -       release_dma_lock (flags);
            free_irq (dev->irq, dev);
     }
    

    Компонент

    linux-kernel 2.6.31

    Принято

    http://lkml.org/lkml/2009/10/7/317
    commit

    Статус

    Исправлено в ядре 2.6.32

    [В начало]