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?

Reply via email to