On Tue, 22 Oct 2019 13:31:12 -0700, Shannon Nelson wrote: > diff --git a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c > b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c > index ab6663d94f42..8c96f5fe43a2 100644 > --- a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c > +++ b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c > @@ -34,52 +34,107 @@ static inline struct netdev_queue *q_to_ndq(struct > ionic_queue *q) > return netdev_get_tx_queue(q->lif->netdev, q->index); > } > > -static void ionic_rx_recycle(struct ionic_queue *q, struct ionic_desc_info > *desc_info, > - struct sk_buff *skb) > +static struct sk_buff *ionic_rx_skb_alloc(struct ionic_queue *q, > + unsigned int len, bool frags) > { > - struct ionic_rxq_desc *old = desc_info->desc; > - struct ionic_rxq_desc *new = q->head->desc; > + struct ionic_lif *lif = q->lif; > + struct ionic_rx_stats *stats; > + struct net_device *netdev; > + struct sk_buff *skb; > + > + netdev = lif->netdev; > + stats = q_to_rx_stats(q); > > - new->addr = old->addr; > - new->len = old->len; > + if (frags) > + skb = napi_get_frags(&q_to_qcq(q)->napi); > + else > + skb = netdev_alloc_skb_ip_align(netdev, len); > > - ionic_rxq_post(q, true, ionic_rx_clean, skb); > + if (unlikely(!skb)) { > + net_warn_ratelimited("%s: SKB alloc failed on %s!\n", > + netdev->name, q->name); > + stats->alloc_err++; > + return NULL; > + } > + > + return skb; > } > > -static bool ionic_rx_copybreak(struct ionic_queue *q, struct ionic_desc_info > *desc_info, > - struct ionic_cq_info *cq_info, struct sk_buff > **skb) > +static struct sk_buff *ionic_rx_frags(struct ionic_queue *q, > + struct ionic_desc_info *desc_info, > + struct ionic_cq_info *cq_info) > { > struct ionic_rxq_comp *comp = cq_info->cq_desc; > - struct ionic_rxq_desc *desc = desc_info->desc; > - struct net_device *netdev = q->lif->netdev; > struct device *dev = q->lif->ionic->dev; > - struct sk_buff *new_skb; > - u16 clen, dlen; > - > - clen = le16_to_cpu(comp->len); > - dlen = le16_to_cpu(desc->len); > - if (clen > q->lif->rx_copybreak) { > - dma_unmap_single(dev, (dma_addr_t)le64_to_cpu(desc->addr), > - dlen, DMA_FROM_DEVICE); > - return false; > - } > + struct ionic_page_info *page_info; > + struct sk_buff *skb; > + unsigned int i; > + u16 frag_len; > + u16 len; > > - new_skb = netdev_alloc_skb_ip_align(netdev, clen); > - if (!new_skb) { > - dma_unmap_single(dev, (dma_addr_t)le64_to_cpu(desc->addr), > - dlen, DMA_FROM_DEVICE); > - return false; > - } > + page_info = &desc_info->pages[0]; > + len = le16_to_cpu(comp->len); > > - dma_sync_single_for_cpu(dev, (dma_addr_t)le64_to_cpu(desc->addr), > - clen, DMA_FROM_DEVICE); > + prefetch(page_address(page_info->page) + NET_IP_ALIGN); > > - memcpy(new_skb->data, (*skb)->data, clen); > + skb = ionic_rx_skb_alloc(q, len, true); > + if (unlikely(!skb)) > + return NULL; > > - ionic_rx_recycle(q, desc_info, *skb); > - *skb = new_skb; > + i = comp->num_sg_elems + 1; > + do { > + if (unlikely(!page_info->page)) { > + dev_kfree_skb(skb); > + return NULL; > + }
Would you not potentially free the napi->skb here? is that okay?