Commit 413f0271 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

net: protect NAPI enablement with netdev_lock()



Wrap napi_enable() / napi_disable() with netdev_lock().
Provide the "already locked" flavor of the API.

iavf needs the usual adjustment. A number of drivers call
napi_enable() under a spin lock, so they have to be modified
to take netdev_lock() first, then spin lock then call
napi_enable_locked().

Protecting napi_enable() implies that napi->napi_id is protected
by netdev_lock().

Acked-by: Francois Romieu <romieu@fr.zoreil.com> # via-velocity
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Reviewed-by: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
Link: https://patch.msgid.link/20250115035319.559603-7-kuba@kernel.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 1b23cdbd
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -462,7 +462,7 @@ static void pcnet32_netif_start(struct net_device *dev)
	val = lp->a->read_csr(ioaddr, CSR3);
	val &= 0x00ff;
	lp->a->write_csr(ioaddr, CSR3, val);
	napi_enable(&lp->napi);
	napi_enable_locked(&lp->napi);
}

/*
@@ -889,6 +889,7 @@ static int pcnet32_set_ringparam(struct net_device *dev,
	if (netif_running(dev))
		pcnet32_netif_stop(dev);

	netdev_lock(dev);
	spin_lock_irqsave(&lp->lock, flags);
	lp->a->write_csr(ioaddr, CSR0, CSR0_STOP);	/* stop the chip */

@@ -920,6 +921,7 @@ static int pcnet32_set_ringparam(struct net_device *dev,
	}

	spin_unlock_irqrestore(&lp->lock, flags);
	netdev_unlock(dev);

	netif_info(lp, drv, dev, "Ring Param Settings: RX: %d, TX: %d\n",
		   lp->rx_ring_size, lp->tx_ring_size);
@@ -985,6 +987,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
	if (netif_running(dev))
		pcnet32_netif_stop(dev);

	netdev_lock(dev);
	spin_lock_irqsave(&lp->lock, flags);
	lp->a->write_csr(ioaddr, CSR0, CSR0_STOP);	/* stop the chip */

@@ -1122,6 +1125,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1)
		lp->a->write_bcr(ioaddr, 20, 4);	/* return to 16bit mode */
	}
	spin_unlock_irqrestore(&lp->lock, flags);
	netdev_unlock(dev);

	return rc;
}				/* end pcnet32_loopback_test  */
@@ -2101,6 +2105,7 @@ static int pcnet32_open(struct net_device *dev)
		return -EAGAIN;
	}

	netdev_lock(dev);
	spin_lock_irqsave(&lp->lock, flags);
	/* Check for a valid station address */
	if (!is_valid_ether_addr(dev->dev_addr)) {
@@ -2266,7 +2271,7 @@ static int pcnet32_open(struct net_device *dev)
		goto err_free_ring;
	}

	napi_enable(&lp->napi);
	napi_enable_locked(&lp->napi);

	/* Re-initialize the PCNET32, and start it when done. */
	lp->a->write_csr(ioaddr, 1, (lp->init_dma_addr & 0xffff));
@@ -2300,6 +2305,7 @@ static int pcnet32_open(struct net_device *dev)
		     lp->a->read_csr(ioaddr, CSR0));

	spin_unlock_irqrestore(&lp->lock, flags);
	netdev_unlock(dev);

	return 0;		/* Always succeed */

@@ -2315,6 +2321,7 @@ static int pcnet32_open(struct net_device *dev)

err_free_irq:
	spin_unlock_irqrestore(&lp->lock, flags);
	netdev_unlock(dev);
	free_irq(dev->irq, dev);
	return rc;
}
+2 −2
Original line number Diff line number Diff line
@@ -1180,7 +1180,7 @@ static void iavf_napi_enable_all(struct iavf_adapter *adapter)

		q_vector = &adapter->q_vectors[q_idx];
		napi = &q_vector->napi;
		napi_enable(napi);
		napi_enable_locked(napi);
	}
}

@@ -1196,7 +1196,7 @@ static void iavf_napi_disable_all(struct iavf_adapter *adapter)

	for (q_idx = 0; q_idx < q_vectors; q_idx++) {
		q_vector = &adapter->q_vectors[q_idx];
		napi_disable(&q_vector->napi);
		napi_disable_locked(&q_vector->napi);
	}
}

+4 −1
Original line number Diff line number Diff line
@@ -4392,6 +4392,7 @@ static int mvneta_cpu_online(unsigned int cpu, struct hlist_node *node)
	if (pp->neta_armada3700)
		return 0;

	netdev_lock(port->napi.dev);
	spin_lock(&pp->lock);
	/*
	 * Configuring the driver for a new CPU while the driver is
@@ -4418,7 +4419,7 @@ static int mvneta_cpu_online(unsigned int cpu, struct hlist_node *node)

	/* Mask all ethernet port interrupts */
	on_each_cpu(mvneta_percpu_mask_interrupt, pp, true);
	napi_enable(&port->napi);
	napi_enable_locked(&port->napi);

	/*
	 * Enable per-CPU interrupts on the CPU that is
@@ -4439,6 +4440,8 @@ static int mvneta_cpu_online(unsigned int cpu, struct hlist_node *node)
		    MVNETA_CAUSE_LINK_CHANGE);
	netif_tx_start_all_queues(pp->dev);
	spin_unlock(&pp->lock);
	netdev_unlock(port->napi.dev);

	return 0;
}

+4 −2
Original line number Diff line number Diff line
@@ -2320,7 +2320,8 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)
		if (ret < 0)
			goto out_free_tmp_vptr_1;

		napi_disable(&vptr->napi);
		netdev_lock(dev);
		napi_disable_locked(&vptr->napi);

		spin_lock_irqsave(&vptr->lock, flags);

@@ -2342,12 +2343,13 @@ static int velocity_change_mtu(struct net_device *dev, int new_mtu)

		velocity_give_many_rx_descs(vptr);

		napi_enable(&vptr->napi);
		napi_enable_locked(&vptr->napi);

		mac_enable_int(vptr->mac_regs);
		netif_start_queue(dev);

		spin_unlock_irqrestore(&vptr->lock, flags);
		netdev_unlock(dev);

		velocity_free_rings(tmp_vptr);

+3 −8
Original line number Diff line number Diff line
@@ -382,7 +382,7 @@ struct napi_struct {
	struct sk_buff		*skb;
	struct list_head	rx_list; /* Pending GRO_NORMAL skbs */
	int			rx_count; /* length of rx_list */
	unsigned int		napi_id;
	unsigned int		napi_id; /* protected by netdev_lock */
	struct hrtimer		timer;
	struct task_struct	*thread;
	unsigned long		gro_flush_timeout;
@@ -570,16 +570,11 @@ static inline bool napi_complete(struct napi_struct *n)

int dev_set_threaded(struct net_device *dev, bool threaded);

/**
 *	napi_disable - prevent NAPI from scheduling
 *	@n: NAPI context
 *
 * Stop NAPI from being scheduled on this context.
 * Waits till any outstanding processing completes.
 */
void napi_disable(struct napi_struct *n);
void napi_disable_locked(struct napi_struct *n);

void napi_enable(struct napi_struct *n);
void napi_enable_locked(struct napi_struct *n);

/**
 *	napi_synchronize - wait until NAPI is not running
Loading