public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
From: Paolo Abeni <pabeni@redhat.com>
To: Xuan Zhuo <xuanzhuo@linux.alibaba.com>, netdev@vger.kernel.org
Cc: Andrew Lunn <andrew+netdev@lunn.ch>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>,
	Wen Gu <guwen@linux.alibaba.com>,
	Philo Lu <lulie@linux.alibaba.com>,
	Lorenzo Bianconi <lorenzo@kernel.org>,
	Vadim Fedorenko <vadim.fedorenko@linux.dev>,
	Dong Yibo <dong100@mucse.com>,
	Heiner Kallweit <hkallweit1@gmail.com>,
	Lukas Bulwahn <lukas.bulwahn@redhat.com>,
	Dust Li <dust.li@linux.alibaba.com>
Subject: Re: [PATCH net-next v28 4/8] eea: create/destroy rx,tx queues for netdevice open and stop
Date: Thu, 5 Mar 2026 11:16:32 +0100	[thread overview]
Message-ID: <e6c3b053-75d7-46b5-9fd0-ac6de498456f@redhat.com> (raw)
In-Reply-To: <20260302024604.25354-5-xuanzhuo@linux.alibaba.com>

On 3/2/26 3:46 AM, Xuan Zhuo wrote:
> Add basic driver framework for the Alibaba Elastic Ethernet Adapter(EEA).
> 
> This commit introduces the implementation for the netdevice open and
> stop.
> 
> Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
> Reviewed-by: Philo Lu <lulie@linux.alibaba.com>
> Signed-off-by: Wen Gu <guwen@linux.alibaba.com>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>  drivers/net/ethernet/alibaba/eea/Makefile  |   4 +-
>  drivers/net/ethernet/alibaba/eea/eea_net.c | 530 ++++++++++++++++++++-
>  drivers/net/ethernet/alibaba/eea/eea_net.h |  45 ++
>  drivers/net/ethernet/alibaba/eea/eea_pci.c | 182 ++++++-
>  drivers/net/ethernet/alibaba/eea/eea_pci.h |  13 +
>  drivers/net/ethernet/alibaba/eea/eea_rx.c  | 254 ++++++++++
>  drivers/net/ethernet/alibaba/eea/eea_tx.c  | 104 ++++
>  7 files changed, 1127 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/net/ethernet/alibaba/eea/eea_rx.c
>  create mode 100644 drivers/net/ethernet/alibaba/eea/eea_tx.c
> 
> diff --git a/drivers/net/ethernet/alibaba/eea/Makefile b/drivers/net/ethernet/alibaba/eea/Makefile
> index 91f318e8e046..fa34a005fa01 100644
> --- a/drivers/net/ethernet/alibaba/eea/Makefile
> +++ b/drivers/net/ethernet/alibaba/eea/Makefile
> @@ -3,4 +3,6 @@ obj-$(CONFIG_EEA) += eea.o
>  eea-y := eea_ring.o \
>  	eea_net.o \
>  	eea_pci.o \
> -	eea_adminq.o
> +	eea_adminq.o \
> +	eea_tx.o \
> +	eea_rx.o
> diff --git a/drivers/net/ethernet/alibaba/eea/eea_net.c b/drivers/net/ethernet/alibaba/eea/eea_net.c
> index 31cb9ca5b408..2ebf0053d05e 100644
> --- a/drivers/net/ethernet/alibaba/eea/eea_net.c
> +++ b/drivers/net/ethernet/alibaba/eea/eea_net.c
> @@ -18,6 +18,453 @@
>  
>  #define EEA_SPLIT_HDR_SIZE 128
>  
> +static irqreturn_t eea_irq_handler(int irq, void *data)
> +{
> +	struct eea_irq_blk *blk = data;
> +
> +	napi_schedule_irqoff(&blk->napi);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void eea_free_irq_blk(struct eea_net *enet)
> +{
> +	struct eea_irq_blk *blk;
> +	u32 num;
> +	int i;
> +
> +	if (!enet->irq_blks)
> +		return;
> +
> +	num = enet->edev->rx_num;
> +
> +	for (i = 0; i < num; i++) {
> +		blk = &enet->irq_blks[i];
> +
> +		if (blk->ready)
> +			eea_pci_free_irq(blk);
> +
> +		blk->ready = false;
> +	}
> +
> +	kvfree(enet->irq_blks);
> +	enet->irq_blks = NULL;
> +}
> +
> +static int eea_alloc_irq_blks(struct eea_net *enet, u32 num)
> +{
> +	struct eea_device *edev = enet->edev;
> +	struct eea_irq_blk *blk, *irq_blks;
> +	int i, err;
> +
> +	irq_blks = kvcalloc(num, sizeof(*blk), GFP_KERNEL);
> +	if (!irq_blks)
> +		return -ENOMEM;
> +
> +	enet->irq_blks = irq_blks;
> +
> +	for (i = 0; i < num; i++) {
> +		blk = &irq_blks[i];
> +		blk->idx = i;
> +
> +		/* vec 0 is for error notify. */
> +		blk->msix_vec = i + 1;
> +
> +		err = eea_pci_request_irq(edev, blk, eea_irq_handler);
> +		if (err)
> +			goto err_free_irq_blk;
> +
> +		blk->ready = true;
> +	}
> +
> +	return 0;
> +
> +err_free_irq_blk:
> +	eea_free_irq_blk(enet);
> +	return err;
> +}
> +
> +static int eea_update_queues(struct eea_net *enet)
> +{
> +	return netif_set_real_num_queues(enet->netdev, enet->cfg.tx_ring_num,
> +					 enet->cfg.rx_ring_num);
> +}
> +
> +void eea_init_ctx(struct eea_net *enet, struct eea_net_init_ctx *ctx)
> +{
> +	memset(ctx, 0, sizeof(*ctx));
> +
> +	ctx->netdev = enet->netdev;
> +	ctx->edev = enet->edev;
> +	ctx->cfg = enet->cfg;
> +}
> +
> +static void eea_bind_q_and_cfg(struct eea_net *enet,
> +			       struct eea_net_init_ctx *ctx)
> +{
> +	struct eea_irq_blk *blk;
> +	struct eea_net_rx *rx;
> +	struct eea_net_tx *tx;
> +	int i;
> +
> +	enet->cfg = ctx->cfg;
> +	enet->rx = ctx->rx;
> +	enet->tx = ctx->tx;
> +
> +	for (i = 0; i < ctx->cfg.rx_ring_num; i++) {
> +		blk = &enet->irq_blks[i];
> +
> +		rx = ctx->rx[i];
> +		tx = &ctx->tx[i];
> +
> +		rx->enet = enet;
> +		rx->napi = &blk->napi;
> +		rx->ering->msix_vec = blk->msix_vec;
> +
> +		tx->enet = enet;
> +		tx->ering->msix_vec = blk->msix_vec;
> +
> +		blk->rx = rx;
> +	}
> +}
> +
> +static void eea_unbind_q_and_cfg(struct eea_net *enet,
> +				 struct eea_net_init_ctx *ctx)
> +{
> +	struct eea_irq_blk *blk;
> +	struct eea_net_rx *rx;
> +	int i;
> +
> +	ctx->cfg = enet->cfg;
> +	ctx->rx = enet->rx;
> +	ctx->tx = enet->tx;
> +
> +	enet->rx = NULL;
> +	enet->tx = NULL;
> +
> +	for (i = 0; i < ctx->cfg.rx_ring_num; i++) {
> +		blk = &enet->irq_blks[i];
> +
> +		rx = ctx->rx[i];
> +
> +		rx->napi = NULL;
> +
> +		blk->rx = NULL;
> +	}
> +}
> +
> +static void eea_free_rxtx_q_mem(struct eea_net_init_ctx *ctx)
> +{
> +	struct eea_net_rx *rx;
> +	struct eea_net_tx *tx;
> +	int i;
> +
> +	for (i = 0; i < ctx->cfg.rx_ring_num; i++) {
> +		rx = ctx->rx[i];
> +		tx = &ctx->tx[i];
> +
> +		eea_free_rx(rx, &ctx->cfg);
> +		eea_free_tx(tx, &ctx->cfg);
> +	}
> +
> +	kvfree(ctx->rx);
> +	kvfree(ctx->tx);
> +}
> +
> +/* alloc tx/rx: struct, ring, meta, pp, napi */
> +static int eea_alloc_rxtx_q_mem(struct eea_net_init_ctx *ctx)
> +{
> +	struct eea_net_rx *rx;
> +	struct eea_net_tx *tx;
> +	int err, i;
> +
> +	ctx->tx = kvcalloc(ctx->cfg.tx_ring_num, sizeof(*ctx->tx), GFP_KERNEL);
> +	if (!ctx->tx)
> +		return -ENOMEM;
> +
> +	ctx->rx = kvcalloc(ctx->cfg.rx_ring_num, sizeof(*ctx->rx), GFP_KERNEL);
> +	if (!ctx->rx)
> +		goto err_free_tx;
> +
> +	ctx->cfg.rx_sq_desc_size = sizeof(struct eea_rx_desc);
> +	ctx->cfg.rx_cq_desc_size = sizeof(struct eea_rx_cdesc);
> +	ctx->cfg.tx_sq_desc_size = sizeof(struct eea_tx_desc);
> +	ctx->cfg.tx_cq_desc_size = sizeof(struct eea_tx_cdesc);
> +
> +	ctx->cfg.tx_cq_desc_size /= 2;
> +
> +	if (!ctx->cfg.split_hdr)
> +		ctx->cfg.rx_sq_desc_size /= 2;
> +
> +	for (i = 0; i < ctx->cfg.rx_ring_num; i++) {
> +		rx = eea_alloc_rx(ctx, i);
> +		if (!rx)
> +			goto err_free;
> +
> +		ctx->rx[i] = rx;
> +
> +		tx = ctx->tx + i;
> +		err = eea_alloc_tx(ctx, tx, i);
> +		if (err)
> +			goto err_free;
> +	}
> +
> +	return 0;
> +
> +err_free:
> +	for (i = 0; i < ctx->cfg.rx_ring_num; i++) {
> +		rx = ctx->rx[i];
> +		tx = ctx->tx + i;
> +
> +		eea_free_rx(rx, &ctx->cfg);
> +		eea_free_tx(tx, &ctx->cfg);
> +	}
> +
> +	kvfree(ctx->rx);
> +
> +err_free_tx:
> +	kvfree(ctx->tx);
> +	return -ENOMEM;
> +}
> +
> +static int eea_hw_active_ring(struct eea_net *enet)
> +{
> +	return eea_adminq_create_q(enet, /* qidx = */ 0,
> +				   enet->cfg.rx_ring_num +
> +				   enet->cfg.tx_ring_num, 0);
> +}
> +
> +static int eea_hw_unactive_ring(struct eea_net *enet)
> +{
> +	int err;
> +
> +	err = eea_adminq_destroy_all_q(enet);
> +	if (err)
> +		netdev_warn(enet->netdev, "unactive rxtx ring failed.\n");
> +
> +	return err;
> +}
> +
> +/* stop rx napi, stop tx queue. */
> +static void eea_stop_rxtx(struct net_device *netdev)
> +{
> +	struct eea_net *enet = netdev_priv(netdev);
> +	int i;
> +
> +	netif_tx_disable(netdev);
> +
> +	for (i = 0; i < enet->cfg.rx_ring_num; i++)
> +		enet_rx_stop(enet->rx[i]);
> +
> +	netif_carrier_off(netdev);
> +}
> +
> +static void eea_start_rxtx(struct eea_net *enet)
> +{
> +	int i;
> +
> +	for (i = 0; i < enet->cfg.rx_ring_num; i++)
> +		enet_rx_start(enet->rx[i]);
> +
> +	netif_tx_start_all_queues(enet->netdev);
> +	netif_carrier_on(enet->netdev);
> +
> +	enet->started = true;
> +}
> +
> +static int eea_netdev_stop(struct net_device *netdev)
> +{
> +	struct eea_net *enet = netdev_priv(netdev);
> +	struct eea_net_init_ctx ctx;
> +
> +	/* This function can be called during device anomaly recovery. To
> +	 * prevent duplicate stop operations, the `started` flag is introduced
> +	 * for checking.
> +	 */
> +
> +	if (!enet->started) {
> +		netdev_warn(netdev, "eea netdev stop: but dev is not started.\n");
> +		return 0;
> +	}
> +
> +	eea_stop_rxtx(netdev);
> +	eea_hw_unactive_ring(enet);
> +	eea_unbind_q_and_cfg(enet, &ctx);
> +	eea_free_rxtx_q_mem(&ctx);
> +
> +	enet->started = false;
> +
> +	return 0;
> +}
> +
> +static int eea_netdev_open(struct net_device *netdev)
> +{
> +	struct eea_net *enet = netdev_priv(netdev);
> +	struct eea_net_init_ctx ctx;
> +	int err;
> +
> +	if (enet->link_err) {
> +		netdev_err(netdev, "netdev open err, because link error: %d\n",
> +			   enet->link_err);
> +		return -EBUSY;
> +	}
> +
> +	eea_init_ctx(enet, &ctx);
> +
> +	err = eea_alloc_rxtx_q_mem(&ctx);
> +	if (err)
> +		goto err_done;
> +
> +	eea_bind_q_and_cfg(enet, &ctx);
> +
> +	err = eea_update_queues(enet);
> +	if (err)
> +		goto err_free_q;
> +
> +	err = eea_hw_active_ring(enet);
> +	if (err)
> +		goto err_free_q;
> +
> +	eea_start_rxtx(enet);
> +
> +	return 0;
> +
> +err_free_q:
> +	eea_unbind_q_and_cfg(enet, &ctx);
> +	eea_free_rxtx_q_mem(&ctx);
> +
> +err_done:
> +	return err;
> +}
> +
> +/* resources: ring, buffers, irq */
> +int eea_reset_hw_resources(struct eea_net *enet, struct eea_net_init_ctx *ctx)
> +{
> +	struct eea_net_init_ctx ctx_old = {0};
> +	int err, error;
> +
> +	if (!netif_running(enet->netdev) || !enet->started) {
> +		enet->cfg = ctx->cfg;
> +		return 0;
> +	}
> +
> +	err = eea_alloc_rxtx_q_mem(ctx);
> +	if (err) {
> +		netdev_warn(enet->netdev,
> +			    "eea reset: alloc q failed. stop reset. err %d\n",
> +			    err);
> +		return err;
> +	}
> +
> +	eea_stop_rxtx(enet->netdev);
> +	eea_hw_unactive_ring(enet);
> +
> +	eea_unbind_q_and_cfg(enet, &ctx_old);
> +	eea_bind_q_and_cfg(enet, ctx);
> +
> +	err = eea_update_queues(enet);
> +	if (err) {
> +		netdev_err(enet->netdev,
> +			   "eea reset: set real num queues failed. err %d\n",
> +			   err);
> +		goto err_bind_old;
> +	}
> +
> +	err = eea_hw_active_ring(enet);

AFAICS the need for admins queue destroy and recreation on cfg change is
what prevents a safe configuration swap (together with irq allocation,
see below). Could you instead keep the admin queue always alive i.e.
with maximum number of erings configured, and just enable/them as needded?

If not, please document explicitly the constraint in the commit message.

[...]
> @@ -140,14 +591,65 @@ static struct eea_net *eea_netdev_alloc(struct eea_device *edev, u32 pairs)
>  	enet->edev = edev;
>  	edev->enet = enet;
>  
> +	err = eea_alloc_irq_blks(enet, pairs);
> +	if (err) {

I'm likely lost, but AFAICS eea_alloc_irq_blks() is invoked only here,
and allocates edev->rx_num interrupts. rx_num is the number of RX
channel at device probe time.

set_channels can later change such value, i.e. increasing it. But I
don't see other irqs allocated.

Also the irq handler takes a direct pointer to the napi struct, as
opposed to Jakub's suggestion of using a ptr to a p

> +		dev_err(edev->dma_dev,
> +			"eea_alloc_irq_blks failed with pairs %d\n", pairs);
> +		free_netdev(netdev);
> +		return NULL;
> +	}
> +
>  	return enet;
>  }
>  
> +static void eea_update_ts_off(struct eea_device *edev, struct eea_net *enet)
> +{
> +	u64 ts;
> +
> +	ts = eea_pci_device_ts(edev);
> +
> +	enet->hw_ts_offset = ktime_get_real() - ts;
> +}
> +
> +static int eea_net_reprobe(struct eea_device *edev)
> +{
> +	struct eea_net *enet = edev->enet;
> +	int err = 0;
> +
> +	enet->edev = edev;
> +
> +	if (!enet->adminq.ring) {
> +		err = eea_create_adminq(enet, edev->rx_num + edev->tx_num);
> +		if (err)
> +			return err;
> +	}
> +
> +	err = eea_alloc_irq_blks(enet, edev->rx_num);
> +	if (err) {
> +		eea_destroy_adminq(enet);
> +		return -ENOMEM;
> +	}
> +
> +	eea_update_ts_off(edev, enet);
> +
> +	if (edev->ha_reset_netdev_running) {
> +		rtnl_lock();
> +		enet->link_err = 0;
> +		err = eea_netdev_open(enet->netdev);
> +		rtnl_unlock();
> +	}
> +
> +	return err;
> +}
> +
>  int eea_net_probe(struct eea_device *edev)
>  {
>  	struct eea_net *enet;
>  	int err = -ENOMEM;
>  
> +	if (edev->ha_reset)
> +		return eea_net_reprobe(edev);
> +
>  	enet = eea_netdev_alloc(edev, edev->rx_num);
>  	if (!enet)
>  		return -ENOMEM;
> @@ -168,6 +670,7 @@ int eea_net_probe(struct eea_device *edev)
>  	if (err)
>  		goto err_reset_dev;
>  
> +	eea_update_ts_off(edev, enet);
>  	netif_carrier_off(enet->netdev);
>  
>  	netdev_dbg(enet->netdev, "eea probe success.\n");
> @@ -179,10 +682,29 @@ int eea_net_probe(struct eea_device *edev)
>  	eea_destroy_adminq(enet);
>  
>  err_free_netdev:
> +	eea_free_irq_blk(enet);
>  	free_netdev(enet->netdev);
>  	return err;
>  }
>  
> +static void eea_net_ha_reset_remove(struct eea_net *enet,
> +				    struct eea_device *edev,
> +				    struct net_device *netdev)
> +{
> +	rtnl_lock();
> +	edev->ha_reset_netdev_running = false;
> +	if (netif_running(enet->netdev)) {
> +		eea_netdev_stop(enet->netdev);
> +		enet->link_err = EEA_LINK_ERR_HA_RESET_DEV;
> +		edev->ha_reset_netdev_running = true;
> +	}
> +	rtnl_unlock();
> +
> +	eea_device_reset(edev);
> +	eea_destroy_adminq(enet);
> +	eea_free_irq_blk(enet);
> +}
> +
>  void eea_net_remove(struct eea_device *edev)
>  {
>  	struct net_device *netdev;
> @@ -191,12 +713,16 @@ void eea_net_remove(struct eea_device *edev)
>  	enet = edev->enet;
>  	netdev = enet->netdev;
>  
> +	if (edev->ha_reset) {
> +		eea_net_ha_reset_remove(enet, edev, netdev);
> +		return;
> +	}
> +
>  	unregister_netdev(netdev);
> -	netdev_dbg(enet->netdev, "eea removed.\n");
>  
>  	eea_device_reset(edev);
> -
>  	eea_destroy_adminq(enet);
> +	eea_free_irq_blk(enet);
>  
>  	free_netdev(netdev);
>  }
> diff --git a/drivers/net/ethernet/alibaba/eea/eea_net.h b/drivers/net/ethernet/alibaba/eea/eea_net.h
> index ab487bc88af2..0398e781dfdb 100644
> --- a/drivers/net/ethernet/alibaba/eea/eea_net.h
> +++ b/drivers/net/ethernet/alibaba/eea/eea_net.h
> @@ -18,6 +18,8 @@
>  #define EEA_VER_MINOR		0
>  #define EEA_VER_SUB_MINOR	0
>  
> +struct eea_tx_meta;
> +
>  struct eea_net_tx {
>  	struct eea_net *enet;
>  
> @@ -101,6 +103,18 @@ struct eea_net_cfg {
>  	u8 tx_cq_desc_size;
>  
>  	u32 split_hdr;
> +
> +	struct hwtstamp_config ts_cfg;
> +};
> +
> +struct eea_net_init_ctx {
> +	struct eea_net_cfg cfg;
> +
> +	struct eea_net_tx *tx;
> +	struct eea_net_rx **rx;
> +
> +	struct net_device *netdev;
> +	struct eea_device *edev;
>  };
>  
>  enum {
> @@ -109,6 +123,17 @@ enum {
>  	EEA_LINK_ERR_LINK_DOWN,
>  };
>  
> +struct eea_irq_blk {
> +	struct napi_struct napi;
> +	u16 msix_vec;
> +	bool ready;
> +	struct eea_net_rx *rx;
> +	char irq_name[32];
> +	int irq;
> +	int idx;
> +
> +};
> +
>  struct eea_net {
>  	struct eea_device *edev;
>  	struct net_device *netdev;
> @@ -121,6 +146,8 @@ struct eea_net {
>  	struct eea_net_cfg cfg;
>  	struct eea_net_cfg cfg_hw;
>  
> +	struct eea_irq_blk *irq_blks;
> +
>  	u32 link_err;
>  
>  	bool started;
> @@ -134,4 +161,22 @@ struct eea_net {
>  int eea_net_probe(struct eea_device *edev);
>  void eea_net_remove(struct eea_device *edev);
>  
> +int eea_reset_hw_resources(struct eea_net *enet, struct eea_net_init_ctx *ctx);
> +void eea_init_ctx(struct eea_net *enet, struct eea_net_init_ctx *ctx);
> +int eea_queues_check_and_reset(struct eea_device *edev);
> +
> +/* rx apis */
> +void enet_rx_stop(struct eea_net_rx *rx);
> +void enet_rx_start(struct eea_net_rx *rx);
> +
> +void eea_free_rx(struct eea_net_rx *rx, struct eea_net_cfg *cfg);
> +struct eea_net_rx *eea_alloc_rx(struct eea_net_init_ctx *ctx, u32 idx);
> +
> +/* tx apis */
> +int eea_poll_tx(struct eea_net_tx *tx, int budget);
> +netdev_tx_t eea_tx_xmit(struct sk_buff *skb, struct net_device *netdev);
> +
> +void eea_free_tx(struct eea_net_tx *tx, struct eea_net_cfg *cfg);
> +int eea_alloc_tx(struct eea_net_init_ctx *ctx, struct eea_net_tx *tx, u32 idx);
> +
>  #endif
> diff --git a/drivers/net/ethernet/alibaba/eea/eea_pci.c b/drivers/net/ethernet/alibaba/eea/eea_pci.c
> index 97efac753cfb..e42b0298eebb 100644
> --- a/drivers/net/ethernet/alibaba/eea/eea_pci.c
> +++ b/drivers/net/ethernet/alibaba/eea/eea_pci.c
> @@ -13,6 +13,9 @@
>  
>  #define EEA_PCI_DB_OFFSET 4096
>  
> +#define EEA_PCI_CAP_RESET_DEVICE 0xFA
> +#define EEA_PCI_CAP_RESET_FLAG BIT(1)
> +
>  struct eea_pci_cfg {
>  	__le32 reserve0;
>  	__le32 reserve1;
> @@ -51,6 +54,7 @@ struct eea_pci_device {
>  	void __iomem *reg;
>  	void __iomem *db_base;
>  
> +	struct work_struct ha_handle_work;
>  	char ha_irq_name[32];
>  	u8 reset_pos;
>  };
> @@ -67,6 +71,11 @@ struct eea_pci_device {
>  #define cfg_read32(reg, item) ioread32(cfg_pointer(reg, item))
>  #define cfg_readq(reg, item) readq(cfg_pointer(reg, item))
>  
> +/* Due to circular references, we have to add function definitions here. */
> +static int __eea_pci_probe(struct pci_dev *pci_dev,
> +			   struct eea_pci_device *ep_dev);
> +static void __eea_pci_remove(struct pci_dev *pci_dev, bool flush_ha_work);
> +
>  const char *eea_pci_name(struct eea_device *edev)
>  {
>  	return pci_name(edev->ep_dev->pci_dev);
> @@ -250,6 +259,150 @@ void eea_pci_active_aq(struct eea_ring *ering, int msix_vec)
>  				    cfg_read32(ep_dev->reg, aq_db_off));
>  }
>  
> +void eea_pci_free_irq(struct eea_irq_blk *blk)
> +{
> +	irq_update_affinity_hint(blk->irq, NULL);
> +	free_irq(blk->irq, blk);
> +}
> +
> +int eea_pci_request_irq(struct eea_device *edev, struct eea_irq_blk *blk,
> +			irqreturn_t (*callback)(int irq, void *data))
> +{
> +	struct eea_pci_device *ep_dev = edev->ep_dev;
> +	int irq;
> +
> +	snprintf(blk->irq_name, sizeof(blk->irq_name), "eea-q%d@%s", blk->idx,
> +		 pci_name(ep_dev->pci_dev));
> +
> +	irq = pci_irq_vector(ep_dev->pci_dev, blk->msix_vec);
> +
> +	blk->irq = irq;
> +
> +	return request_irq(irq, callback, IRQF_NO_AUTOEN, blk->irq_name, blk);
> +}
> +
> +static void eea_ha_handle_reset(struct eea_pci_device *ep_dev)
> +{
> +	struct eea_device *edev;
> +	struct pci_dev *pci_dev;
> +	u16 reset;
> +	int err;
> +
> +	if (!ep_dev->reset_pos) {
> +		eea_queues_check_and_reset(&ep_dev->edev);
> +		return;
> +	}
> +
> +	edev = &ep_dev->edev;
> +
> +	pci_read_config_word(ep_dev->pci_dev, ep_dev->reset_pos, &reset);
> +
> +	/* clear bit */
> +	pci_write_config_word(ep_dev->pci_dev, ep_dev->reset_pos, 0xFFFF);
> +
> +	if (reset & EEA_PCI_CAP_RESET_FLAG) {
> +		dev_warn(&ep_dev->pci_dev->dev, "recv device reset request.\n");
> +
> +		pci_dev = ep_dev->pci_dev;
> +
> +		/* The pci remove callback may hold this lock. If the
> +		 * pci remove callback is called, then we can ignore the
> +		 * ha interrupt.
> +		 */
> +		if (mutex_trylock(&edev->ha_lock)) {
> +			edev->ha_reset = true;
> +
> +			__eea_pci_remove(pci_dev, false);
> +			err = __eea_pci_probe(pci_dev, ep_dev);
> +			if (err)
> +				dev_err(&ep_dev->pci_dev->dev,
> +					"ha: re-setup failed.\n");

AI still notes:
---
What happens if __eea_pci_probe() fails during HA reset recovery? Jakub
Kicinski's AI review in v25 noted that when probe fails after remove
succeeded, the device is left in a removed state with no error beyond this
single dev_err() message.

The function returns 1 (from the implicit flow) indicating success, even
though reprobe failed and the device is now non-functional. Should this
check
for errors and at minimum log the failure state more prominently?

Reference:
https://lore.kernel.org/netdev/20260204040054.1698677-2-kuba@kernel.org/
---


  reply	other threads:[~2026-03-05 10:16 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-02  2:45 [PATCH net-next v28 0/8] eea: Add basic driver framework for Alibaba Elastic Ethernet Adaptor Xuan Zhuo
2026-03-02  2:45 ` [PATCH net-next v28 1/8] eea: introduce PCI framework Xuan Zhuo
2026-03-02  2:45 ` [PATCH net-next v28 2/8] eea: introduce ring and descriptor structures Xuan Zhuo
2026-03-02  2:45 ` [PATCH net-next v28 3/8] eea: probe the netdevice and create adminq Xuan Zhuo
2026-03-06  2:44   ` [net-next,v28,3/8] " Jakub Kicinski
2026-03-02  2:46 ` [PATCH net-next v28 4/8] eea: create/destroy rx,tx queues for netdevice open and stop Xuan Zhuo
2026-03-05 10:16   ` Paolo Abeni [this message]
2026-03-09  8:51     ` Xuan Zhuo
2026-03-10  8:38       ` Paolo Abeni
2026-03-02  2:46 ` [PATCH net-next v28 5/8] eea: implement packet receive logic Xuan Zhuo
2026-03-02  2:46 ` [PATCH net-next v28 6/8] eea: implement packet transmit logic Xuan Zhuo
2026-03-02  2:46 ` [PATCH net-next v28 7/8] eea: introduce ethtool support Xuan Zhuo
2026-03-02  2:46 ` [PATCH net-next v28 8/8] eea: introduce callback for ndo_get_stats64 Xuan Zhuo

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=e6c3b053-75d7-46b5-9fd0-ac6de498456f@redhat.com \
    --to=pabeni@redhat.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=dong100@mucse.com \
    --cc=dust.li@linux.alibaba.com \
    --cc=edumazet@google.com \
    --cc=guwen@linux.alibaba.com \
    --cc=hkallweit1@gmail.com \
    --cc=kuba@kernel.org \
    --cc=lorenzo@kernel.org \
    --cc=lukas.bulwahn@redhat.com \
    --cc=lulie@linux.alibaba.com \
    --cc=netdev@vger.kernel.org \
    --cc=vadim.fedorenko@linux.dev \
    --cc=xuanzhuo@linux.alibaba.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