All of lore.kernel.org
 help / color / mirror / Atom feed
From: Manish Chopra <manishc@marvell.com>
To: Benjamin Poirier <bpoirier@suse.com>,
	GR-Linux-NIC-Dev <GR-Linux-NIC-Dev@marvell.com>,
	"netdev@vger.kernel.org" <netdev@vger.kernel.org>
Subject: RE: [EXT] [PATCH net-next 16/16] qlge: Refill empty buffer queues from wq
Date: Thu, 27 Jun 2019 14:18:27 +0000	[thread overview]
Message-ID: <DM6PR18MB2697EC53399F214EC3DFC4ABABFD0@DM6PR18MB2697.namprd18.prod.outlook.com> (raw)
In-Reply-To: <20190617074858.32467-16-bpoirier@suse.com>

> -----Original Message-----
> From: Benjamin Poirier <bpoirier@suse.com>
> Sent: Monday, June 17, 2019 1:19 PM
> To: Manish Chopra <manishc@marvell.com>; GR-Linux-NIC-Dev <GR-Linux-
> NIC-Dev@marvell.com>; netdev@vger.kernel.org
> Subject: [EXT] [PATCH net-next 16/16] qlge: Refill empty buffer queues from
> wq
> 
> External Email
> 
> ----------------------------------------------------------------------
> When operating at mtu 9000, qlge does order-1 allocations for rx buffers in
> atomic context. This is especially unreliable when free memory is low or
> fragmented. Add an approach similar to commit 3161e453e496 ("virtio: net
> refill on out-of-memory") to qlge so that the device doesn't lock up if there
> are allocation failures.
> 
> Signed-off-by: Benjamin Poirier <bpoirier@suse.com>
> ---
>  drivers/net/ethernet/qlogic/qlge/qlge.h      |  8 ++
>  drivers/net/ethernet/qlogic/qlge/qlge_main.c | 80 ++++++++++++++++----
>  2 files changed, 72 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h
> b/drivers/net/ethernet/qlogic/qlge/qlge.h
> index 1d90b32f6285..9c4d933c1ff7 100644
> --- a/drivers/net/ethernet/qlogic/qlge/qlge.h
> +++ b/drivers/net/ethernet/qlogic/qlge/qlge.h
> @@ -1453,6 +1453,13 @@ struct qlge_bq {
> 
>  #define QLGE_BQ_WRAP(index) ((index) & (QLGE_BQ_LEN - 1))
> 
> +#define QLGE_BQ_HW_OWNED(bq) \
> +({ \
> +	typeof(bq) _bq = bq; \
> +	QLGE_BQ_WRAP(QLGE_BQ_ALIGN((_bq)->next_to_use) - \
> +		     (_bq)->next_to_clean); \
> +})
> +
>  struct rx_ring {
>  	struct cqicb cqicb;	/* The chip's completion queue init control
> block. */
> 
> @@ -1480,6 +1487,7 @@ struct rx_ring {
>  	/* Misc. handler elements. */
>  	u32 irq;		/* Which vector this ring is assigned. */
>  	u32 cpu;		/* Which CPU this should run on. */
> +	struct delayed_work refill_work;
>  	char name[IFNAMSIZ + 5];
>  	struct napi_struct napi;
>  	u8 reserved;
> diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
> b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
> index 7db4c31c9cc4..a13bda566187 100644
> --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
> +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
> @@ -1029,7 +1029,7 @@ static const char * const bq_type_name[] = {
> 
>  /* return 0 or negative error */
>  static int qlge_refill_sb(struct rx_ring *rx_ring,
> -			  struct qlge_bq_desc *sbq_desc)
> +			  struct qlge_bq_desc *sbq_desc, gfp_t gfp)
>  {
>  	struct ql_adapter *qdev = rx_ring->qdev;
>  	struct sk_buff *skb;
> @@ -1041,7 +1041,7 @@ static int qlge_refill_sb(struct rx_ring *rx_ring,
>  		     "ring %u sbq: getting new skb for index %d.\n",
>  		     rx_ring->cq_id, sbq_desc->index);
> 
> -	skb = netdev_alloc_skb(qdev->ndev, SMALL_BUFFER_SIZE);
> +	skb = __netdev_alloc_skb(qdev->ndev, SMALL_BUFFER_SIZE, gfp);
>  	if (!skb)
>  		return -ENOMEM;
>  	skb_reserve(skb, QLGE_SB_PAD);
> @@ -1062,7 +1062,7 @@ static int qlge_refill_sb(struct rx_ring *rx_ring,
> 
>  /* return 0 or negative error */
>  static int qlge_refill_lb(struct rx_ring *rx_ring,
> -			  struct qlge_bq_desc *lbq_desc)
> +			  struct qlge_bq_desc *lbq_desc, gfp_t gfp)
>  {
>  	struct ql_adapter *qdev = rx_ring->qdev;
>  	struct qlge_page_chunk *master_chunk = &rx_ring->master_chunk;
> @@ -1071,8 +1071,7 @@ static int qlge_refill_lb(struct rx_ring *rx_ring,
>  		struct page *page;
>  		dma_addr_t dma_addr;
> 
> -		page = alloc_pages(__GFP_COMP | GFP_ATOMIC,
> -				   qdev->lbq_buf_order);
> +		page = alloc_pages(gfp | __GFP_COMP, qdev-
> >lbq_buf_order);
>  		if (unlikely(!page))
>  			return -ENOMEM;
>  		dma_addr = pci_map_page(qdev->pdev, page, 0, @@ -
> 1109,33 +1108,33 @@ static int qlge_refill_lb(struct rx_ring *rx_ring,
>  	return 0;
>  }
> 
> -static void qlge_refill_bq(struct qlge_bq *bq)
> +/* return 0 or negative error */
> +static int qlge_refill_bq(struct qlge_bq *bq, gfp_t gfp)
>  {
>  	struct rx_ring *rx_ring = QLGE_BQ_CONTAINER(bq);
>  	struct ql_adapter *qdev = rx_ring->qdev;
>  	struct qlge_bq_desc *bq_desc;
>  	int refill_count;
> +	int retval;
>  	int i;
> 
>  	refill_count = QLGE_BQ_WRAP(QLGE_BQ_ALIGN(bq->next_to_clean -
> 1) -
>  				    bq->next_to_use);
>  	if (!refill_count)
> -		return;
> +		return 0;
> 
>  	i = bq->next_to_use;
>  	bq_desc = &bq->queue[i];
>  	i -= QLGE_BQ_LEN;
>  	do {
> -		int retval;
> -
>  		netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev,
>  			     "ring %u %s: try cleaning idx %d\n",
>  			     rx_ring->cq_id, bq_type_name[bq->type], i);
> 
>  		if (bq->type == QLGE_SB)
> -			retval = qlge_refill_sb(rx_ring, bq_desc);
> +			retval = qlge_refill_sb(rx_ring, bq_desc, gfp);
>  		else
> -			retval = qlge_refill_lb(rx_ring, bq_desc);
> +			retval = qlge_refill_lb(rx_ring, bq_desc, gfp);
>  		if (retval < 0) {
>  			netif_err(qdev, ifup, qdev->ndev,
>  				  "ring %u %s: Could not get a page chunk, idx
> %d\n", @@ -1163,12 +1162,52 @@ static void qlge_refill_bq(struct qlge_bq
> *bq)
>  		}
>  		bq->next_to_use = i;
>  	}
> +
> +	return retval;
> +}
> +
> +static void ql_update_buffer_queues(struct rx_ring *rx_ring, gfp_t gfp,
> +				    unsigned long delay)
> +{
> +	bool sbq_fail, lbq_fail;
> +
> +	sbq_fail = !!qlge_refill_bq(&rx_ring->sbq, gfp);
> +	lbq_fail = !!qlge_refill_bq(&rx_ring->lbq, gfp);
> +
> +	/* Minimum number of buffers needed to be able to receive at least
> one
> +	 * frame of any format:
> +	 * sbq: 1 for header + 1 for data
> +	 * lbq: mtu 9000 / lb size
> +	 * Below this, the queue might stall.
> +	 */
> +	if ((sbq_fail && QLGE_BQ_HW_OWNED(&rx_ring->sbq) < 2) ||
> +	    (lbq_fail && QLGE_BQ_HW_OWNED(&rx_ring->lbq) <
> +	     DIV_ROUND_UP(9000, LARGE_BUFFER_MAX_SIZE)))
> +		/* Allocations can take a long time in certain cases (ex.
> +		 * reclaim). Therefore, use a workqueue for long-running
> +		 * work items.
> +		 */
> +		queue_delayed_work_on(smp_processor_id(),
> system_long_wq,
> +				      &rx_ring->refill_work, delay);
>  }
> 

This is probably going to mess up when at the interface load time (qlge_open()) allocation failure occurs, in such cases we don't really want to re-try allocations
using refill_work but rather simply fail the interface load. Just to make sure here in such cases it shouldn't lead to kernel panic etc. while completing qlge_open() and
leaving refill_work executing in background. Or probably handle such allocation failures from the napi context and schedule refill_work from there.



  reply	other threads:[~2019-06-27 14:18 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-17  7:48 [PATCH net-next 01/16] qlge: Remove irq_cnt Benjamin Poirier
2019-06-17  7:48 ` [PATCH net-next 02/16] qlge: Remove page_chunk.last_flag Benjamin Poirier
2019-06-26  9:12   ` Manish Chopra
2019-06-17  7:48 ` [PATCH net-next 03/16] qlge: Deduplicate lbq_buf_size Benjamin Poirier
2019-06-26  9:24   ` [EXT] " Manish Chopra
2019-06-26 11:37     ` Benjamin Poirier
2019-06-26 15:42       ` Willem de Bruijn
2019-06-28  8:57         ` Benjamin Poirier
2019-06-28 14:56           ` Willem de Bruijn
2019-06-17  7:48 ` [PATCH net-next 04/16] qlge: Remove bq_desc.maplen Benjamin Poirier
2019-06-26  9:31   ` Manish Chopra
2019-06-17  7:48 ` [PATCH net-next 05/16] qlge: Remove rx_ring.sbq_buf_size Benjamin Poirier
2019-06-26  9:36   ` [EXT] " Manish Chopra
2019-06-26 11:39     ` Benjamin Poirier
2019-06-26 15:35       ` Willem de Bruijn
2019-06-17  7:48 ` [PATCH net-next 06/16] qlge: Remove useless dma synchronization calls Benjamin Poirier
2019-06-17  9:44   ` [EXT] " Manish Chopra
2019-06-18  2:51     ` Benjamin Poirier
2019-06-17  7:48 ` [PATCH net-next 07/16] qlge: Deduplicate rx buffer queue management Benjamin Poirier
2019-06-27 10:02   ` [EXT] " Manish Chopra
2019-07-09  2:10     ` Benjamin Poirier
2019-06-17  7:48 ` [PATCH net-next 08/16] qlge: Fix dma_sync_single calls Benjamin Poirier
2019-06-17  7:48 ` [PATCH net-next 09/16] qlge: Remove rx_ring.type Benjamin Poirier
2019-06-17  7:48 ` [PATCH net-next 10/16] qlge: Factor out duplicated expression Benjamin Poirier
2019-06-23 17:59   ` David Miller
2019-06-23 18:00     ` David Miller
2019-06-24  7:52     ` Benjamin Poirier
2019-06-25 18:32       ` Manish Chopra
2019-06-28  8:52         ` Benjamin Poirier
2019-06-17  7:48 ` [PATCH net-next 11/16] qlge: Remove qlge_bq.len & size Benjamin Poirier
2019-06-27 10:47   ` Manish Chopra
2019-07-09  6:52     ` Benjamin Poirier
2019-06-17  7:48 ` [PATCH net-next 12/16] qlge: Remove useless memset Benjamin Poirier
2019-06-17  7:48 ` [PATCH net-next 13/16] qlge: Replace memset with assignment Benjamin Poirier
2019-06-17  7:48 ` [PATCH net-next 14/16] qlge: Update buffer queue prod index despite oom Benjamin Poirier
2019-06-17  7:48 ` [PATCH net-next 15/16] qlge: Refill rx buffers up to multiple of 16 Benjamin Poirier
2019-06-17  7:48 ` [PATCH net-next 16/16] qlge: Refill empty buffer queues from wq Benjamin Poirier
2019-06-27 14:18   ` Manish Chopra [this message]
2019-07-10  1:18     ` [EXT] " Benjamin Poirier
2019-06-17 16:49 ` [PATCH net-next 01/16] qlge: Remove irq_cnt Manish Chopra
2019-06-26  8:59 ` Manish Chopra
2019-06-26 11:36   ` Benjamin Poirier
2019-06-26 13:21     ` Manish Chopra
2019-07-05  8:33       ` Benjamin Poirier
2019-07-15  1:40 ` Benjamin Poirier
2019-07-15  9:48   ` Greg Kroah-Hartman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DM6PR18MB2697EC53399F214EC3DFC4ABABFD0@DM6PR18MB2697.namprd18.prod.outlook.com \
    --to=manishc@marvell.com \
    --cc=GR-Linux-NIC-Dev@marvell.com \
    --cc=bpoirier@suse.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.