mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
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: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
278d436a47
commit
fe24ba082b
1 changed files with 19 additions and 12 deletions
|
@ -534,6 +534,25 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
|
|||
while ((processed < to_process) && (processed < budget)) {
|
||||
cb = &priv->rx_cbs[priv->rx_read_ptr];
|
||||
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),
|
||||
RX_BUF_LENGTH, DMA_FROM_DEVICE);
|
||||
|
||||
|
@ -543,23 +562,11 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
|
|||
status = (rsb->rx_status_len >> DESC_STATUS_SHIFT) &
|
||||
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,
|
||||
"p=%d, c=%d, rd_ptr=%d, len=%d, flag=0x%04x\n",
|
||||
p_index, priv->rx_c_index, priv->rx_read_ptr,
|
||||
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))) {
|
||||
netif_err(priv, rx_status, ndev, "fragmented packet!\n");
|
||||
ndev->stats.rx_dropped++;
|
||||
|
|
Loading…
Reference in a new issue