Commit 3c5e979b authored by Will Deacon's avatar Will Deacon Committed by David S. Miller

net: smsc911x: fix skb handling in receive path

The SMSC911x driver resets the ->head, ->data and ->tail pointers in the
skb on the reset path in order to avoid buffer overflow due to packet
padding performed by the hardware.

This patch fixes the receive path so that the skb pointers are fixed up
after the data has been read from the device, The error path is also
fixed to use number of words consistently and prevent erroneous FIFO
fastforwarding when skipping over bad data.
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 51c61a28
...@@ -1166,10 +1166,8 @@ smsc911x_rx_counterrors(struct net_device *dev, unsigned int rxstat) ...@@ -1166,10 +1166,8 @@ smsc911x_rx_counterrors(struct net_device *dev, unsigned int rxstat)
/* Quickly dumps bad packets */ /* Quickly dumps bad packets */
static void static void
smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktbytes) smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktwords)
{ {
unsigned int pktwords = (pktbytes + NET_IP_ALIGN + 3) >> 2;
if (likely(pktwords >= 4)) { if (likely(pktwords >= 4)) {
unsigned int timeout = 500; unsigned int timeout = 500;
unsigned int val; unsigned int val;
...@@ -1233,7 +1231,7 @@ static int smsc911x_poll(struct napi_struct *napi, int budget) ...@@ -1233,7 +1231,7 @@ static int smsc911x_poll(struct napi_struct *napi, int budget)
continue; continue;
} }
skb = netdev_alloc_skb(dev, pktlength + NET_IP_ALIGN); skb = netdev_alloc_skb(dev, pktwords << 2);
if (unlikely(!skb)) { if (unlikely(!skb)) {
SMSC_WARN(pdata, rx_err, SMSC_WARN(pdata, rx_err,
"Unable to allocate skb for rx packet"); "Unable to allocate skb for rx packet");
...@@ -1243,14 +1241,12 @@ static int smsc911x_poll(struct napi_struct *napi, int budget) ...@@ -1243,14 +1241,12 @@ static int smsc911x_poll(struct napi_struct *napi, int budget)
break; break;
} }
skb->data = skb->head; pdata->ops->rx_readfifo(pdata,
skb_reset_tail_pointer(skb); (unsigned int *)skb->data, pktwords);
/* Align IP on 16B boundary */ /* Align IP on 16B boundary */
skb_reserve(skb, NET_IP_ALIGN); skb_reserve(skb, NET_IP_ALIGN);
skb_put(skb, pktlength - 4); skb_put(skb, pktlength - 4);
pdata->ops->rx_readfifo(pdata,
(unsigned int *)skb->head, pktwords);
skb->protocol = eth_type_trans(skb, dev); skb->protocol = eth_type_trans(skb, dev);
skb_checksum_none_assert(skb); skb_checksum_none_assert(skb);
netif_receive_skb(skb); netif_receive_skb(skb);
...@@ -1565,7 +1561,7 @@ static int smsc911x_open(struct net_device *dev) ...@@ -1565,7 +1561,7 @@ static int smsc911x_open(struct net_device *dev)
smsc911x_reg_write(pdata, FIFO_INT, temp); smsc911x_reg_write(pdata, FIFO_INT, temp);
/* set RX Data offset to 2 bytes for alignment */ /* set RX Data offset to 2 bytes for alignment */
smsc911x_reg_write(pdata, RX_CFG, (2 << 8)); smsc911x_reg_write(pdata, RX_CFG, (NET_IP_ALIGN << 8));
/* enable NAPI polling before enabling RX interrupts */ /* enable NAPI polling before enabling RX interrupts */
napi_enable(&pdata->napi); napi_enable(&pdata->napi);
......
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