diff options
-rw-r--r-- | drivers/net/ethernet/aquantia/atlantic/aq_cfg.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 27 |
2 files changed, 20 insertions, 9 deletions
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h index 3944ce7f0870..aba550770adf 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h @@ -38,6 +38,8 @@ #define AQ_CFG_TX_CLEAN_BUDGET 256U +#define AQ_CFG_RX_HDR_SIZE 256U + /* LRO */ #define AQ_CFG_IS_LRO_DEF 1U diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c index e2ffb159cbe2..4558f16c0ca6 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c @@ -201,17 +201,18 @@ int aq_ring_rx_clean(struct aq_ring_s *self, int budget) { struct net_device *ndev = aq_nic_get_ndev(self->aq_nic); - int err = 0; bool is_rsc_completed = true; + int err = 0; for (; (self->sw_head != self->hw_head) && budget; self->sw_head = aq_ring_next_dx(self, self->sw_head), --budget, ++(*work_done)) { struct aq_ring_buff_s *buff = &self->buff_ring[self->sw_head]; + struct aq_ring_buff_s *buff_ = NULL; struct sk_buff *skb = NULL; unsigned int next_ = 0U; unsigned int i = 0U; - struct aq_ring_buff_s *buff_ = NULL; + u16 hdr_len; if (buff->is_error) { __free_pages(buff->page, 0); @@ -255,20 +256,28 @@ int aq_ring_rx_clean(struct aq_ring_s *self, err = -ENOMEM; goto err_exit; } - skb_put(skb, buff->len); } else { - skb = netdev_alloc_skb(ndev, ETH_HLEN); + skb = napi_alloc_skb(napi, AQ_CFG_RX_HDR_SIZE); if (unlikely(!skb)) { err = -ENOMEM; goto err_exit; } - skb_put(skb, ETH_HLEN); - memcpy(skb->data, page_address(buff->page), ETH_HLEN); - skb_add_rx_frag(skb, 0, buff->page, ETH_HLEN, - buff->len - ETH_HLEN, - SKB_TRUESIZE(buff->len - ETH_HLEN)); + hdr_len = buff->len; + if (hdr_len > AQ_CFG_RX_HDR_SIZE) + hdr_len = eth_get_headlen(page_address(buff->page), + AQ_CFG_RX_HDR_SIZE); + + memcpy(__skb_put(skb, hdr_len), page_address(buff->page), + ALIGN(hdr_len, sizeof(long))); + + if (buff->len - hdr_len > 0) { + skb_add_rx_frag(skb, 0, buff->page, + hdr_len, + buff->len - hdr_len, + SKB_TRUESIZE(buff->len - hdr_len)); + } if (!buff->is_eop) { for (i = 1U, next_ = buff->next, |