net: bcmgenet: 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
fe24ba082b
commit
b629be5c83
@ -1274,12 +1274,29 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
|
|||||||
|
|
||||||
while ((rxpktprocessed < rxpkttoprocess) &&
|
while ((rxpktprocessed < rxpkttoprocess) &&
|
||||||
(rxpktprocessed < budget)) {
|
(rxpktprocessed < budget)) {
|
||||||
|
cb = &priv->rx_cbs[priv->rx_read_ptr];
|
||||||
|
skb = cb->skb;
|
||||||
|
|
||||||
|
rxpktprocessed++;
|
||||||
|
|
||||||
|
priv->rx_read_ptr++;
|
||||||
|
priv->rx_read_ptr &= (priv->num_rx_bds - 1);
|
||||||
|
|
||||||
|
/* We do not have a backing SKB, so we do not have a
|
||||||
|
* corresponding DMA mapping for this incoming packet since
|
||||||
|
* bcmgenet_rx_refill always either has both skb and mapping or
|
||||||
|
* none.
|
||||||
|
*/
|
||||||
|
if (unlikely(!skb)) {
|
||||||
|
dev->stats.rx_dropped++;
|
||||||
|
dev->stats.rx_errors++;
|
||||||
|
goto refill;
|
||||||
|
}
|
||||||
|
|
||||||
/* Unmap the packet contents such that we can use the
|
/* Unmap the packet contents such that we can use the
|
||||||
* RSV from the 64 bytes descriptor when enabled and save
|
* RSV from the 64 bytes descriptor when enabled and save
|
||||||
* a 32-bits register read
|
* a 32-bits register read
|
||||||
*/
|
*/
|
||||||
cb = &priv->rx_cbs[priv->rx_read_ptr];
|
|
||||||
skb = cb->skb;
|
|
||||||
dma_unmap_single(&dev->dev, dma_unmap_addr(cb, dma_addr),
|
dma_unmap_single(&dev->dev, dma_unmap_addr(cb, dma_addr),
|
||||||
priv->rx_buf_len, DMA_FROM_DEVICE);
|
priv->rx_buf_len, DMA_FROM_DEVICE);
|
||||||
|
|
||||||
@ -1307,18 +1324,6 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv,
|
|||||||
__func__, p_index, priv->rx_c_index,
|
__func__, p_index, priv->rx_c_index,
|
||||||
priv->rx_read_ptr, dma_length_status);
|
priv->rx_read_ptr, dma_length_status);
|
||||||
|
|
||||||
rxpktprocessed++;
|
|
||||||
|
|
||||||
priv->rx_read_ptr++;
|
|
||||||
priv->rx_read_ptr &= (priv->num_rx_bds - 1);
|
|
||||||
|
|
||||||
/* out of memory, just drop packets at the hardware level */
|
|
||||||
if (unlikely(!skb)) {
|
|
||||||
dev->stats.rx_dropped++;
|
|
||||||
dev->stats.rx_errors++;
|
|
||||||
goto refill;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unlikely(!(dma_flag & DMA_EOP) || !(dma_flag & DMA_SOP))) {
|
if (unlikely(!(dma_flag & DMA_EOP) || !(dma_flag & DMA_SOP))) {
|
||||||
netif_err(priv, rx_status, dev,
|
netif_err(priv, rx_status, dev,
|
||||||
"dropping fragmented packet!\n");
|
"dropping fragmented packet!\n");
|
||||||
|
Loading…
Reference in New Issue
Block a user