Roel Kluin reported a bug in two error paths where skbs were wrongly
being freed using kfree(). He provided a fix where it was replaced to
kfree_skb(), as it should be.
However, in i2400mu_rx(), the error path was missing returning an
indication of the failure. Changed to reset rx_skb to NULL and return
it to the caller, i2400mu_rxd(). It will be treated as a transient
error and just ignore the packet.
Depending on the buffering conditions inside the device, the data
packet might be dropped or the device will signal the host again for
data-ready-to-read and the host will retry.
Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
spin_lock_irqsave(&i2400m->rx_lock, flags);
ack_skb = i2400m->ack_skb;
if (ack_skb && !IS_ERR(ack_skb))
spin_lock_irqsave(&i2400m->rx_lock, flags);
ack_skb = i2400m->ack_skb;
if (ack_skb && !IS_ERR(ack_skb))
i2400m->ack_skb = ERR_PTR(code);
spin_unlock_irqrestore(&i2400m->rx_lock, flags);
}
i2400m->ack_skb = ERR_PTR(code);
spin_unlock_irqrestore(&i2400m->rx_lock, flags);
}
* NOTE: this function might realloc the skb (if it is too small),
* so always update with the one returned.
* ERR_PTR() is < 0 on error.
* NOTE: this function might realloc the skb (if it is too small),
* so always update with the one returned.
* ERR_PTR() is < 0 on error.
+ * Will return NULL if it cannot reallocate -- this can be
+ * considered a transient retryable error.
*/
static
struct sk_buff *i2400mu_rx(struct i2400mu *i2400mu, struct sk_buff *rx_skb)
*/
static
struct sk_buff *i2400mu_rx(struct i2400mu *i2400mu, struct sk_buff *rx_skb)
if (printk_ratelimit())
dev_err(dev, "RX: Can't reallocate skb to %d; "
"RX dropped\n", rx_size);
if (printk_ratelimit())
dev_err(dev, "RX: Can't reallocate skb to %d; "
"RX dropped\n", rx_size);
- kfree(rx_skb);
- result = 0;
+ kfree_skb(rx_skb);
+ rx_skb = NULL;
goto out; /* drop it...*/
}
kfree_skb(rx_skb);
goto out; /* drop it...*/
}
kfree_skb(rx_skb);
if (IS_ERR(rx_skb))
goto out;
atomic_dec(&i2400mu->rx_pending_count);
if (IS_ERR(rx_skb))
goto out;
atomic_dec(&i2400mu->rx_pending_count);
- if (rx_skb->len == 0) { /* some ignorable condition */
+ if (rx_skb == NULL || rx_skb->len == 0) {
+ /* some "ignorable" condition */
kfree_skb(rx_skb);
continue;
}
kfree_skb(rx_skb);
continue;
}