|
@@ -91,6 +91,8 @@ static int buf_sz = DEFAULT_BUFSIZE;
|
|
|
module_param(buf_sz, int, S_IRUGO | S_IWUSR);
|
|
|
MODULE_PARM_DESC(buf_sz, "DMA buffer size");
|
|
|
|
|
|
+#define STMMAC_RX_COPYBREAK 256
|
|
|
+
|
|
|
static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
|
|
|
NETIF_MSG_LINK | NETIF_MSG_IFUP |
|
|
|
NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
|
|
@@ -1808,6 +1810,7 @@ static int stmmac_open(struct net_device *dev)
|
|
|
priv->xstats.threshold = tc;
|
|
|
|
|
|
priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
|
|
|
+ priv->rx_copybreak = STMMAC_RX_COPYBREAK;
|
|
|
|
|
|
ret = alloc_dma_desc_resources(priv);
|
|
|
if (ret < 0) {
|
|
@@ -2159,8 +2162,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
|
|
|
-
|
|
|
- if (unlikely(skb == NULL))
|
|
|
+ if (unlikely(!skb))
|
|
|
break;
|
|
|
|
|
|
priv->rx_skbuff[entry] = skb;
|
|
@@ -2282,23 +2284,52 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
|
|
|
pr_debug("\tframe size %d, COE: %d\n",
|
|
|
frame_len, status);
|
|
|
}
|
|
|
- skb = priv->rx_skbuff[entry];
|
|
|
- if (unlikely(!skb)) {
|
|
|
- pr_err("%s: Inconsistent Rx descriptor chain\n",
|
|
|
- priv->dev->name);
|
|
|
- priv->dev->stats.rx_dropped++;
|
|
|
- break;
|
|
|
+
|
|
|
+ if (unlikely(frame_len < priv->rx_copybreak)) {
|
|
|
+ skb = netdev_alloc_skb_ip_align(priv->dev,
|
|
|
+ frame_len);
|
|
|
+ if (unlikely(!skb)) {
|
|
|
+ if (net_ratelimit())
|
|
|
+ dev_warn(priv->device,
|
|
|
+ "packet dropped\n");
|
|
|
+ priv->dev->stats.rx_dropped++;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ dma_sync_single_for_cpu(priv->device,
|
|
|
+ priv->rx_skbuff_dma
|
|
|
+ [entry], frame_len,
|
|
|
+ DMA_FROM_DEVICE);
|
|
|
+ skb_copy_to_linear_data(skb,
|
|
|
+ priv->
|
|
|
+ rx_skbuff[entry]->data,
|
|
|
+ frame_len);
|
|
|
+
|
|
|
+ skb_put(skb, frame_len);
|
|
|
+ dma_sync_single_for_device(priv->device,
|
|
|
+ priv->rx_skbuff_dma
|
|
|
+ [entry], frame_len,
|
|
|
+ DMA_FROM_DEVICE);
|
|
|
+ } else {
|
|
|
+ skb = priv->rx_skbuff[entry];
|
|
|
+ if (unlikely(!skb)) {
|
|
|
+ pr_err("%s: Inconsistent Rx chain\n",
|
|
|
+ priv->dev->name);
|
|
|
+ priv->dev->stats.rx_dropped++;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ prefetch(skb->data - NET_IP_ALIGN);
|
|
|
+ priv->rx_skbuff[entry] = NULL;
|
|
|
+
|
|
|
+ skb_put(skb, frame_len);
|
|
|
+ dma_unmap_single(priv->device,
|
|
|
+ priv->rx_skbuff_dma[entry],
|
|
|
+ priv->dma_buf_sz,
|
|
|
+ DMA_FROM_DEVICE);
|
|
|
}
|
|
|
- prefetch(skb->data - NET_IP_ALIGN);
|
|
|
- priv->rx_skbuff[entry] = NULL;
|
|
|
|
|
|
stmmac_get_rx_hwtstamp(priv, entry, skb);
|
|
|
|
|
|
- skb_put(skb, frame_len);
|
|
|
- dma_unmap_single(priv->device,
|
|
|
- priv->rx_skbuff_dma[entry],
|
|
|
- priv->dma_buf_sz, DMA_FROM_DEVICE);
|
|
|
-
|
|
|
if (netif_msg_pktdata(priv)) {
|
|
|
pr_debug("frame received (%dbytes)", frame_len);
|
|
|
print_pkt(skb->data, frame_len);
|