Commit fe24ba08 authored by Florian Fainelli's avatar Florian Fainelli Committed by David S. Miller

net: systemport: check harder for out of memory conditions

There is a potential case where we might be failing to refill a
control block, leaving it with both a NULL skb pointer *and* a NULL
dma_unmap_addr.

The way we process incoming packets, by first calling
dma_unmap_single(), and then only checking for a potential NULL skb can
lead to situations where do pass a NULL dma_unmap_addr() to
dma_unmap_single(), resulting in an oops.

Fix this my moving the NULL skb check earlier, since no backing skb
also means no corresponding DMA mapping for this packet.
Signed-off-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 278d436a
...@@ -534,6 +534,25 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, ...@@ -534,6 +534,25 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
while ((processed < to_process) && (processed < budget)) { while ((processed < to_process) && (processed < budget)) {
cb = &priv->rx_cbs[priv->rx_read_ptr]; cb = &priv->rx_cbs[priv->rx_read_ptr];
skb = cb->skb; skb = cb->skb;
processed++;
priv->rx_read_ptr++;
if (priv->rx_read_ptr == priv->num_rx_bds)
priv->rx_read_ptr = 0;
/* We do not have a backing SKB, so we do not a corresponding
* DMA mapping for this incoming packet since
* bcm_sysport_rx_refill always either has both skb and mapping
* or none.
*/
if (unlikely(!skb)) {
netif_err(priv, rx_err, ndev, "out of memory!\n");
ndev->stats.rx_dropped++;
ndev->stats.rx_errors++;
goto refill;
}
dma_unmap_single(kdev, dma_unmap_addr(cb, dma_addr), dma_unmap_single(kdev, dma_unmap_addr(cb, dma_addr),
RX_BUF_LENGTH, DMA_FROM_DEVICE); RX_BUF_LENGTH, DMA_FROM_DEVICE);
...@@ -543,23 +562,11 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, ...@@ -543,23 +562,11 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
status = (rsb->rx_status_len >> DESC_STATUS_SHIFT) & status = (rsb->rx_status_len >> DESC_STATUS_SHIFT) &
DESC_STATUS_MASK; DESC_STATUS_MASK;
processed++;
priv->rx_read_ptr++;
if (priv->rx_read_ptr == priv->num_rx_bds)
priv->rx_read_ptr = 0;
netif_dbg(priv, rx_status, ndev, netif_dbg(priv, rx_status, ndev,
"p=%d, c=%d, rd_ptr=%d, len=%d, flag=0x%04x\n", "p=%d, c=%d, rd_ptr=%d, len=%d, flag=0x%04x\n",
p_index, priv->rx_c_index, priv->rx_read_ptr, p_index, priv->rx_c_index, priv->rx_read_ptr,
len, status); len, status);
if (unlikely(!skb)) {
netif_err(priv, rx_err, ndev, "out of memory!\n");
ndev->stats.rx_dropped++;
ndev->stats.rx_errors++;
goto refill;
}
if (unlikely(!(status & DESC_EOP) || !(status & DESC_SOP))) { if (unlikely(!(status & DESC_EOP) || !(status & DESC_SOP))) {
netif_err(priv, rx_status, ndev, "fragmented packet!\n"); netif_err(priv, rx_status, ndev, "fragmented packet!\n");
ndev->stats.rx_dropped++; ndev->stats.rx_dropped++;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment