Netdev List
 help / color / mirror / Atom feed
From: mingming cao <mmc@linux.ibm.com>
To: Simon Horman <horms@kernel.org>
Cc: netdev@vger.kernel.org, bjking1@linux.ibm.com,
	haren@linux.ibm.com, ricklind@linux.ibm.com, kuba@kernel.org,
	edumazet@google.com, pabeni@redhat.com,
	linuxppc-dev@lists.ozlabs.org, maddy@linux.ibm.com,
	mpe@ellerman.id.au, Dave Marquardt <davemarq@linux.ibm.com>
Subject: Re: [PATCH net-next v3 08/15] ibmveth: Refactor open/close into MQ-ready resource pipeline
Date: Thu, 16 Jul 2026 17:53:00 -0700	[thread overview]
Message-ID: <7262cceb-2e91-4107-8c24-d5a6b6c4281f@linux.ibm.com> (raw)
In-Reply-To: <20260714124736.GK1364329@horms.kernel.org>

On 7/14/26 5:47 AM, Simon Horman wrote:

> On Mon, Jul 06, 2026 at 12:35:56PM -0700, Mingming Cao wrote:
>
> ...
>
>> diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
> ...
*

Hi, Simon


Thanks for the careful read on open/close — these were all fair points.

*
>>   /**
>>    * ibmveth_register_logical_lan_queue - Register subordinate queue with hypervisor
>>    * @adapter: ibmveth adapter structure
>> @@ -1466,208 +1479,108 @@ ibmveth_register_rx_queues(struct ibmveth_adapter *adapter, u64 mac_address)
>>   static int ibmveth_open(struct net_device *netdev)
>>   {
>>   	struct ibmveth_adapter *adapter = netdev_priv(netdev);
>> -	u64 mac_address;
>> +	u64 mac_address = ether_addr_to_u64(netdev->dev_addr);
>>   	int rxq_entries = 1;
>> -	unsigned long lpar_rc;
>>   	int rc;
>> -	union ibmveth_buf_desc rxq_desc;
>>   	int i;
>> -	struct device *dev;
>>   
>>   	netdev_dbg(netdev, "open starting\n");
>>   
>> -	napi_enable(&adapter->napi[0]);
>> -
>> -	for(i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
>> +	for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
>>   		rxq_entries += adapter->rx_buff_pool[0][i].size;
>>   
>> -	rc = -ENOMEM;
>> -	adapter->buffer_list_addr[0] = (void *)get_zeroed_page(GFP_KERNEL);
>> -	if (!adapter->buffer_list_addr[0]) {
>> -		netdev_err(netdev, "unable to allocate list pages\n");
>> +	rc = ibmveth_alloc_rx_qstats(adapter);
>> +	if (rc)
>>   		goto out;
>> -	}
>>   
>> -	adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
>> -	if (!adapter->filter_list_addr) {
>> -		netdev_err(netdev, "unable to allocate filter pages\n");
>> -		goto out_free_buffer_list;
>> -	}
>> -
>> -	dev = &adapter->vdev->dev;
>> +	rc = ibmveth_alloc_filter_list(adapter);
>> +	if (rc)
>> +		goto out_free_rx_qstats;
>>   
>> -	adapter->rx_queue[0].queue_len = sizeof(struct ibmveth_rx_q_entry) *
>> -						rxq_entries;
>> -	adapter->rx_queue[0].queue_addr =
>> -		dma_alloc_coherent(dev, adapter->rx_queue[0].queue_len,
>> -				   &adapter->rx_queue[0].queue_dma, GFP_KERNEL);
>> -	if (!adapter->rx_queue[0].queue_addr)
>> +	rc = ibmveth_alloc_rx_queues(adapter, rxq_entries);
>> +	if (rc)
>>   		goto out_free_filter_list;
>>   
>> -	adapter->buffer_list_dma[0] = dma_map_single(dev,
>> -						     adapter->buffer_list_addr[0],
>> -						     4096, DMA_BIDIRECTIONAL);
>> -	if (dma_mapping_error(dev, adapter->buffer_list_dma[0])) {
>> -		netdev_err(netdev, "unable to map buffer list pages\n");
>> +	rc = ibmveth_alloc_buffer_pools(adapter);
>> +	if (rc)
>>   		goto out_free_queue_mem;
>> -	}
>>   
>> -	adapter->filter_list_dma = dma_map_single(dev,
>> -			adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL);
>> -	if (dma_mapping_error(dev, adapter->filter_list_dma)) {
>> -		netdev_err(netdev, "unable to map filter list pages\n");
>> -		goto out_unmap_buffer_list;
>> -	}
>> +	rc = ibmveth_register_rx_queues(adapter, mac_address);
>> +	if (rc)
>> +		goto out_free_buffer_pools;
>>   
>> -	for (i = 0; i < netdev->real_num_tx_queues; i++) {
>> -		if (ibmveth_allocate_tx_ltb(adapter, i))
>> -			goto out_free_tx_ltb;
>> +	rc = netif_set_real_num_rx_queues(netdev, adapter->num_rx_queues);
>> +	if (rc) {
>> +		netdev_err(netdev, "failed to set number of rx queues\n");
>> +		goto out_unregister_queues;
>>   	}
>>   
>> -	adapter->rx_queue[0].index = 0;
>> -	adapter->rx_queue[0].num_slots = rxq_entries;
>> -	adapter->rx_queue[0].toggle = 1;
>> -
>> -	mac_address = ether_addr_to_u64(netdev->dev_addr);
>> -
>> -	rxq_desc.fields.flags_len = IBMVETH_BUF_VALID |
>> -					adapter->rx_queue[0].queue_len;
>> -	rxq_desc.fields.address = adapter->rx_queue[0].queue_dma;
>> -
>> -	netdev_dbg(netdev, "buffer list @ 0x%p\n", adapter->buffer_list_addr[0]);
>> -	netdev_dbg(netdev, "filter list @ 0x%p\n", adapter->filter_list_addr);
>> -	netdev_dbg(netdev, "receive q   @ 0x%p\n", adapter->rx_queue[0].queue_addr);
>> -
>> -	h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE);
>> -
>> -	lpar_rc = ibmveth_register_logical_lan(adapter, rxq_desc, mac_address);
>> -
>> -	if (lpar_rc != H_SUCCESS) {
>> -		netdev_err(netdev, "h_register_logical_lan failed with %ld\n",
>> -			   lpar_rc);
>> -		netdev_err(netdev, "buffer TCE:0x%llx filter TCE:0x%llx rxq "
>> -			   "desc:0x%llx MAC:0x%llx\n",
>> -				     adapter->buffer_list_dma[0],
>> -				     adapter->filter_list_dma,
>> -				     rxq_desc.desc,
>> -				     mac_address);
>> -		rc = -ENONET;
>> -		goto out_unmap_filter_list;
>> -	}
>> +	rc = ibmveth_setup_rx_interrupts(adapter);
>> +	if (rc)
>> +		goto out_unregister_queues;
>>   
>> -	for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
>> -		if (!adapter->rx_buff_pool[0][i].active)
>> -			continue;
>> -		if (ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[0][i])) {
>> -			netdev_err(netdev, "unable to alloc pool\n");
>> -			adapter->rx_buff_pool[0][i].active = 0;
>> -			rc = -ENOMEM;
>> -			goto out_free_buffer_pools;
>> +	if (adapter->num_rx_queues > 1) {
>> +		for (i = 0; i < adapter->num_rx_queues; i++) {
>> +			netdev_dbg(netdev, "initial replenish cycle for queue %d\n", i);
>> +			ibmveth_replenish_task(adapter, i);
> ibmveth_replenish_task() only has one parameter
> until a later patch in this series.
*

Agreed. Will address this In v4.

the multi-arg replenish call moves to the patch that introduces

the queue-index parameter (or that patch lands

before this open() wiring).

*
>>   		}
>> +	} else {
>> +		netdev_dbg(netdev, "initial replenish cycle\n");
>> +		ibmveth_interrupt(adapter->queue_irq[0], &adapter->napi[0]);
>>   	}
>>   
>> -	netdev_dbg(netdev, "registering irq 0x%x\n", netdev->irq);
>> -	rc = request_irq(netdev->irq, ibmveth_interrupt, 0, netdev->name,
>> -			 netdev);
>> -	if (rc != 0) {
>> -		netdev_err(netdev, "unable to request irq 0x%x, rc %d\n",
>> -			   netdev->irq, rc);
>> -		do {
>> -			lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
>> -		} while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY));
>> -
>> -		goto out_free_buffer_pools;
>> -	}
>> -
>> -	rc = -ENOMEM;
>> -
>> -	netdev_dbg(netdev, "initial replenish cycle\n");
>> -	ibmveth_interrupt(netdev->irq, netdev);
>> +	rc = ibmveth_alloc_tx_resources(adapter);
>> +	if (rc)
>> +		goto out_cleanup_rx_interrupts;
>>   
>>   	netif_tx_start_all_queues(netdev);
>>   
>>   	netdev_dbg(netdev, "open complete\n");
>> -
>>   	return 0;
>>   
>> +out_cleanup_rx_interrupts:
>> +	ibmveth_cleanup_rx_interrupts(adapter);
>> +out_free_tx_resources:
>> +	ibmveth_free_tx_resources(adapter);
> The out_free_tx_resources label is unused until a later patch of this
> series, so it should be added in that patch rather than this one.
*

Agreed — will introduce out_free_tx_resources only when a caller

needs that jump target.

*
>
> And it's not clear to me that ibmveth_free_tx_resources() should
> be called when jumping to out_cleanup_rx_interrupts as
> in that case ibmveth_alloc_tx_resources() hasn't run successfully.
>
> The AI-generated review on sashiko.dev also highlights the error handling
> here:
>
>   "Are the unwind labels ordered incorrectly here?
>
>   "If ibmveth_setup_rx_interrupts() fails, it jumps to
>    out_unregister_queues, which is placed after out_free_buffer_pools. Does
>    this mean we skip freeing the buffer pools and leak memory?
*

Yes — those gotos currently skip free_buffer_pools(). Will fix

unwind ordering in v4 so buffer pools are always released.

*

>
>   "Also, if ibmveth_alloc_tx_resources() fails, it internally frees
>    partially allocated LTBs. It then jumps to out_cleanup_rx_interrupts and
>    falls through to out_free_tx_resources. Because ibmveth_free_tx_ltb()
>    calls dma_unmap_single() unconditionally without checking or zeroing
>    tx_ltb_dma, will this cause a double free and an invalid DMA unmap?

**

*Correct — on alloc_tx_resources() failure TX is already partially*

*

cleaned inside the helper, so falling through to

free_tx_resources() is wrong and can double-unmap. Will fix the

open() unwind graph in v4.

*

>
>   "Finally, in the fall-through path from out_cleanup_rx_interrupts,
>    out_free_buffer_pools is executed before out_unregister_queues (which
>    calls ibmveth_free_all_queues() to unregister the logical LAN). Does this
>    free and unmap the RX buffers while the hypervisor's logical LAN is still
>    active, potentially allowing the hypervisor to DMA incoming packets into
>    freed memory?
>
**

*Agreed — freeing RX pools before h_free_logical_lan() is unsafe.*

*

v4 will unregister/free the logical LAN before releasing buffer

pools on both open failure and close

**

*Thanks,*

*

Mingming

*

*

>>   out_free_buffer_pools:
>> -	while (--i >= 0) {
>> -		if (adapter->rx_buff_pool[0][i].active)
>> -			ibmveth_free_buffer_pool(adapter,
>> -						 &adapter->rx_buff_pool[0][i]);
>> -	}
>> -out_unmap_filter_list:
>> -	dma_unmap_single(dev, adapter->filter_list_dma, 4096,
>> -			 DMA_BIDIRECTIONAL);
>> -
>> -out_free_tx_ltb:
>> -	while (--i >= 0) {
>> -		ibmveth_free_tx_ltb(adapter, i);
>> -	}
>> -
>> -out_unmap_buffer_list:
>> -	dma_unmap_single(dev, adapter->buffer_list_dma[0], 4096,
>> -			 DMA_BIDIRECTIONAL);
>> +	ibmveth_free_buffer_pools(adapter);
>> +out_unregister_queues:
>> +	ibmveth_dispose_subordinate_irq_mappings(adapter);
>> +	ibmveth_free_all_queues(adapter);
>>   out_free_queue_mem:
>> -	dma_free_coherent(dev, adapter->rx_queue[0].queue_len,
>> -			  adapter->rx_queue[0].queue_addr,
>> -			  adapter->rx_queue[0].queue_dma);
>> +	ibmveth_cleanup_rx_resources(adapter);
>>   out_free_filter_list:
>> -	free_page((unsigned long)adapter->filter_list_addr);
>> -out_free_buffer_list:
>> -	free_page((unsigned long)adapter->buffer_list_addr[0]);
>> +	ibmveth_free_filter_list(adapter);
>> +out_free_rx_qstats:
>> +	ibmveth_free_rx_qstats(adapter);
>>   out:
>> -	napi_disable(&adapter->napi[0]);
>>   	return rc;
>>   }
> ...

  reply	other threads:[~2026-07-17  0:53 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-06 19:35 [PATCH net-next v3 00/15] ibmveth: Add multi-queue RX support Mingming Cao
2026-07-06 19:35 ` [PATCH net-next v3 01/15] ibmveth: Add MQ RX hypercall wrappers and call definitions Mingming Cao
2026-07-06 19:35 ` [PATCH net-next v3 02/15] ibmveth: Prepare MQ RX adapter and statistics structures Mingming Cao
2026-07-06 19:35 ` [PATCH net-next v3 03/15] ibmveth: Refactor RX resource allocation for MQ RX bring-up Mingming Cao
2026-07-06 19:35 ` [PATCH net-next v3 04/15] ibmveth: Refactor buffer pool management for per-queue MQ RX Mingming Cao
2026-07-06 19:35 ` [PATCH net-next v3 05/15] ibmveth: Refactor RX interrupt control for MQ RX queues Mingming Cao
2026-07-14 12:43   ` Simon Horman
2026-07-17  0:17     ` mingming cao
2026-07-06 19:35 ` [PATCH net-next v3 06/15] ibmveth: Refactor TX resource allocation in open/close paths Mingming Cao
2026-07-06 19:35 ` [PATCH net-next v3 07/15] ibmveth: Add RX queue register/deregister helpers for MQ Mingming Cao
2026-07-14 12:43   ` Simon Horman
2026-07-17  0:33     ` mingming cao
2026-07-06 19:35 ` [PATCH net-next v3 08/15] ibmveth: Refactor open/close into MQ-ready resource pipeline Mingming Cao
2026-07-14 12:47   ` Simon Horman
2026-07-17  0:53     ` mingming cao [this message]
2026-07-06 19:35 ` [PATCH net-next v3 09/15] ibmveth: Add queue-aware RX buffer submit helper for MQ Mingming Cao
2026-07-14 12:50   ` Simon Horman
2026-07-17  1:02     ` mingming cao
2026-07-06 19:35 ` [PATCH net-next v3 10/15] ibmveth: Enable multi-queue RX receive path Mingming Cao
2026-07-14 12:55   ` Simon Horman
2026-07-17  1:27     ` mingming cao
2026-07-06 19:35 ` [PATCH net-next v3 11/15] ibmveth: Add per-queue RX and TX statistics collection and reporting Mingming Cao
2026-07-14 12:59   ` Simon Horman
2026-07-17  1:39     ` mingming cao
2026-07-06 19:36 ` [PATCH net-next v3 12/15] ibmveth: Expose per-queue buffer pool details via sysfs Mingming Cao
2026-07-14 13:01   ` Simon Horman
2026-07-17  1:54     ` mingming cao
2026-07-06 19:36 ` [PATCH net-next v3 13/15] ibmveth: Implement incremental MQ RX queue resize Mingming Cao
2026-07-14 13:03   ` Simon Horman
2026-07-17  2:40     ` mingming cao
2026-07-06 19:36 ` [PATCH net-next v3 14/15] ibmveth: Wire ethtool set_channels to " Mingming Cao
2026-07-14 13:07   ` Simon Horman
2026-07-17  3:02     ` mingming cao
2026-07-06 19:36 ` [PATCH net-next v3 15/15] ibmveth: Fix MQ RX poll and shutdown hangs after " Mingming Cao
2026-07-14 13:10   ` Simon Horman
2026-07-17  3:08     ` mingming cao

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=7262cceb-2e91-4107-8c24-d5a6b6c4281f@linux.ibm.com \
    --to=mmc@linux.ibm.com \
    --cc=bjking1@linux.ibm.com \
    --cc=davemarq@linux.ibm.com \
    --cc=edumazet@google.com \
    --cc=haren@linux.ibm.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=maddy@linux.ibm.com \
    --cc=mpe@ellerman.id.au \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=ricklind@linux.ibm.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox