Commit f1078ab1 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-hold-netdev-instance-lock-during-ndo-operations'



Stanislav Fomichev says:

====================
net: Hold netdev instance lock during ndo operations

As the gradual purging of rtnl continues, start grabbing netdev
instance lock in more places so we can get to the state where
most paths are working without rtnl. Start with requiring the
drivers that use shaper api (and later queue mgmt api) to work
with both rtnl and netdev instance lock. Eventually we might
attempt to drop rtnl. This mostly affects iavf, gve, bnxt and
netdev sim (as the drivers that implement shaper/queue mgmt)
so those drivers are converted in the process.

call_netdevice_notifiers locking is very inconsistent and might need
a separate follow up. Some notified events are covered by the
instance lock, some are not, which might complicate the driver
expectations.

Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
====================

Link: https://patch.msgid.link/20250305163732.2766420-1-sdf@fomichev.me


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents f130a0cc 004b5008
Loading
Loading
Loading
Loading
+52 −13
Original line number Diff line number Diff line
@@ -210,49 +210,55 @@ packets is preferred.
struct net_device synchronization rules
=======================================
ndo_open:
	Synchronization: rtnl_lock() semaphore.
	Synchronization: rtnl_lock() semaphore. In addition, netdev instance
	lock if the driver implements queue management or shaper API.
	Context: process

ndo_stop:
	Synchronization: rtnl_lock() semaphore.
	Synchronization: rtnl_lock() semaphore. In addition, netdev instance
	lock if the driver implements queue management or shaper API.
	Context: process
	Note: netif_running() is guaranteed false

ndo_do_ioctl:
	Synchronization: rtnl_lock() semaphore.
	Context: process

	This is only called by network subsystems internally,
	not by user space calling ioctl as it was in before
	linux-5.14.

ndo_siocbond:
        Synchronization: rtnl_lock() semaphore.
	Synchronization: rtnl_lock() semaphore. In addition, netdev instance
	lock if the driver implements queue management or shaper API.
        Context: process

	Used by the bonding driver for the SIOCBOND family of
	ioctl commands.

ndo_siocwandev:
	Synchronization: rtnl_lock() semaphore.
	Synchronization: rtnl_lock() semaphore. In addition, netdev instance
	lock if the driver implements queue management or shaper API.
	Context: process

	Used by the drivers/net/wan framework to handle
	the SIOCWANDEV ioctl with the if_settings structure.

ndo_siocdevprivate:
	Synchronization: rtnl_lock() semaphore.
	Synchronization: rtnl_lock() semaphore. In addition, netdev instance
	lock if the driver implements queue management or shaper API.
	Context: process

	This is used to implement SIOCDEVPRIVATE ioctl helpers.
	These should not be added to new drivers, so don't use.

ndo_eth_ioctl:
	Synchronization: rtnl_lock() semaphore.
	Synchronization: rtnl_lock() semaphore. In addition, netdev instance
	lock if the driver implements queue management or shaper API.
	Context: process

ndo_get_stats:
	Synchronization: rtnl_lock() semaphore, or RCU.
	Synchronization: RCU (can be called concurrently with the stats
	update path).
	Context: atomic (can't sleep under RCU)

ndo_start_xmit:
@@ -284,6 +290,10 @@ ndo_set_rx_mode:
	Synchronization: netif_addr_lock spinlock.
	Context: BHs disabled

Most ndo callbacks not specified in the list above are running
under ``rtnl_lock``. In addition, netdev instance lock is taken as well if
the driver implements queue management or shaper API.

struct napi_struct synchronization rules
========================================
napi->poll:
@@ -298,6 +308,35 @@ napi->poll:
		 softirq
		 will be called with interrupts disabled by netconsole.

struct netdev_queue_mgmt_ops synchronization rules
==================================================

All queue management ndo callbacks are holding netdev instance lock.

RTNL and netdev instance lock
=============================

Historically, all networking control operations were protected by a single
global lock known as ``rtnl_lock``. There is an ongoing effort to replace this
global lock with separate locks for each network namespace. Additionally,
properties of individual netdev are increasingly protected by per-netdev locks.

For device drivers that implement shaping or queue management APIs, all control
operations will be performed under the netdev instance lock. Currently, this
instance lock is acquired within the context of ``rtnl_lock``. The drivers
can also explicitly request instance lock to be acquired via
``request_ops_lock``. In the future, there will be an option for individual
drivers to opt out of using ``rtnl_lock`` and instead perform their control
operations directly under the netdev instance lock.

Devices drivers are encouraged to rely on the instance lock where possible.

For the (mostly software) drivers that need to interact with the core stack,
there are two sets of interfaces: ``dev_xxx`` and ``netif_xxx`` (e.g.,
``dev_set_mtu`` and ``netif_set_mtu``). The ``dev_xxx`` functions handle
acquiring the instance lock themselves, while the ``netif_xxx`` functions
assume that the driver has already acquired the instance lock.

NETDEV_INTERNAL symbol namespace
================================

+9 −7
Original line number Diff line number Diff line
@@ -855,7 +855,6 @@ static int bond_check_dev_link(struct bonding *bond,
			       struct net_device *slave_dev, int reporting)
{
	const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
	int (*ioctl)(struct net_device *, struct ifreq *, int);
	struct ifreq ifr;
	struct mii_ioctl_data *mii;

@@ -871,8 +870,7 @@ static int bond_check_dev_link(struct bonding *bond,
			BMSR_LSTATUS : 0;

	/* Ethtool can't be used, fallback to MII ioctls. */
	ioctl = slave_ops->ndo_eth_ioctl;
	if (ioctl) {
	if (slave_ops->ndo_eth_ioctl) {
		/* TODO: set pointer to correct ioctl on a per team member
		 *       bases to make this more efficient. that is, once
		 *       we determine the correct ioctl, we will always
@@ -888,9 +886,10 @@ static int bond_check_dev_link(struct bonding *bond,
		/* Yes, the mii is overlaid on the ifreq.ifr_ifru */
		strscpy_pad(ifr.ifr_name, slave_dev->name, IFNAMSIZ);
		mii = if_mii(&ifr);
		if (ioctl(slave_dev, &ifr, SIOCGMIIPHY) == 0) {

		if (dev_eth_ioctl(slave_dev, &ifr, SIOCGMIIPHY) == 0) {
			mii->reg_num = MII_BMSR;
			if (ioctl(slave_dev, &ifr, SIOCGMIIREG) == 0)
			if (dev_eth_ioctl(slave_dev, &ifr, SIOCGMIIREG) == 0)
				return mii->val_out & BMSR_LSTATUS;
		}
	}
@@ -2645,10 +2644,13 @@ static int __bond_release_one(struct net_device *bond_dev,
		dev_set_mac_address(slave_dev, (struct sockaddr *)&ss, NULL);
	}

	if (unregister)
	if (unregister) {
		netdev_lock_ops(slave_dev);
		__dev_set_mtu(slave_dev, slave->original_mtu);
	else
		netdev_unlock_ops(slave_dev);
	} else {
		dev_set_mtu(slave_dev, slave->original_mtu);
	}

	if (!netif_is_bond_master(slave_dev))
		slave_dev->priv_flags &= ~IFF_BONDING;
+69 −64
Original line number Diff line number Diff line
@@ -5246,8 +5246,10 @@ static void bnxt_free_ntp_fltrs(struct bnxt *bp, bool all)
{
	int i;

	/* Under rtnl_lock and all our NAPIs have been disabled.  It's
	 * safe to delete the hash table.
	netdev_assert_locked(bp->dev);

	/* Under netdev instance lock and all our NAPIs have been disabled.
	 * It's safe to delete the hash table.
	 */
	for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++) {
		struct hlist_head *head;
@@ -11508,7 +11510,7 @@ static int bnxt_request_irq(struct bnxt *bp)
		if (rc)
			break;

		netif_napi_set_irq(&bp->bnapi[i]->napi, irq->vector);
		netif_napi_set_irq_locked(&bp->bnapi[i]->napi, irq->vector);
		irq->requested = 1;

		if (zalloc_cpumask_var(&irq->cpu_mask, GFP_KERNEL)) {
@@ -11557,9 +11559,9 @@ static void bnxt_del_napi(struct bnxt *bp)
	for (i = 0; i < bp->cp_nr_rings; i++) {
		struct bnxt_napi *bnapi = bp->bnapi[i];

		__netif_napi_del(&bnapi->napi);
		__netif_napi_del_locked(&bnapi->napi);
	}
	/* We called __netif_napi_del(), we need
	/* We called __netif_napi_del_locked(), we need
	 * to respect an RCU grace period before freeing napi structures.
	 */
	synchronize_net();
@@ -11578,12 +11580,12 @@ static void bnxt_init_napi(struct bnxt *bp)
		cp_nr_rings--;
	for (i = 0; i < cp_nr_rings; i++) {
		bnapi = bp->bnapi[i];
		netif_napi_add_config(bp->dev, &bnapi->napi, poll_fn,
		netif_napi_add_config_locked(bp->dev, &bnapi->napi, poll_fn,
					     bnapi->index);
	}
	if (BNXT_CHIP_TYPE_NITRO_A0(bp)) {
		bnapi = bp->bnapi[cp_nr_rings];
		netif_napi_add(bp->dev, &bnapi->napi, bnxt_poll_nitroa0);
		netif_napi_add_locked(bp->dev, &bnapi->napi, bnxt_poll_nitroa0);
	}
}

@@ -11604,7 +11606,7 @@ static void bnxt_disable_napi(struct bnxt *bp)
			cpr->sw_stats->tx.tx_resets++;
		if (bnapi->in_reset)
			cpr->sw_stats->rx.rx_resets++;
		napi_disable(&bnapi->napi);
		napi_disable_locked(&bnapi->napi);
	}
}

@@ -11626,7 +11628,7 @@ static void bnxt_enable_napi(struct bnxt *bp)
			INIT_WORK(&cpr->dim.work, bnxt_dim_work);
			cpr->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
		}
		napi_enable(&bnapi->napi);
		napi_enable_locked(&bnapi->napi);
	}
}

@@ -12789,7 +12791,6 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
	return rc;
}

/* rtnl_lock held */
int bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
{
	int rc = 0;
@@ -12805,9 +12806,9 @@ int bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
	return rc;
}

/* rtnl_lock held, open the NIC half way by allocating all resources, but
 * NAPI, IRQ, and TX are not enabled.  This is mainly used for offline
 * self tests.
/* netdev instance lock held, open the NIC half way by allocating all
 * resources, but NAPI, IRQ, and TX are not enabled.  This is mainly used
 * for offline self tests.
 */
int bnxt_half_open_nic(struct bnxt *bp)
{
@@ -12842,8 +12843,8 @@ int bnxt_half_open_nic(struct bnxt *bp)
	return rc;
}

/* rtnl_lock held, this call can only be made after a previous successful
 * call to bnxt_half_open_nic().
/* netdev instance lock held, this call can only be made after a previous
 * successful call to bnxt_half_open_nic().
 */
void bnxt_half_close_nic(struct bnxt *bp)
{
@@ -12952,10 +12953,11 @@ void bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
	if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
		/* If we get here, it means firmware reset is in progress
		 * while we are trying to close.  We can safely proceed with
		 * the close because we are holding rtnl_lock().  Some firmware
		 * messages may fail as we proceed to close.  We set the
		 * ABORT_ERR flag here so that the FW reset thread will later
		 * abort when it gets the rtnl_lock() and sees the flag.
		 * the close because we are holding netdev instance lock.
		 * Some firmware messages may fail as we proceed to close.
		 * We set the ABORT_ERR flag here so that the FW reset thread
		 * will later abort when it gets the netdev instance lock
		 * and sees the flag.
		 */
		netdev_warn(bp->dev, "FW reset in progress during close, FW reset will be aborted\n");
		set_bit(BNXT_STATE_ABORT_ERR, &bp->state);
@@ -13046,7 +13048,7 @@ static int bnxt_hwrm_port_phy_write(struct bnxt *bp, u16 phy_addr, u16 reg,
	return hwrm_req_send(bp, req);
}

/* rtnl_lock held */
/* netdev instance lock held */
static int bnxt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
	struct mii_ioctl_data *mdio = if_mii(ifr);
@@ -13965,30 +13967,31 @@ static void bnxt_timer(struct timer_list *t)
	mod_timer(&bp->timer, jiffies + bp->current_interval);
}

static void bnxt_rtnl_lock_sp(struct bnxt *bp)
static void bnxt_lock_sp(struct bnxt *bp)
{
	/* We are called from bnxt_sp_task which has BNXT_STATE_IN_SP_TASK
	 * set.  If the device is being closed, bnxt_close() may be holding
	 * rtnl() and waiting for BNXT_STATE_IN_SP_TASK to clear.  So we
	 * must clear BNXT_STATE_IN_SP_TASK before holding rtnl().
	 * netdev instance lock and waiting for BNXT_STATE_IN_SP_TASK to clear.
	 * So we must clear BNXT_STATE_IN_SP_TASK before holding netdev
	 * instance lock.
	 */
	clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
	rtnl_lock();
	netdev_lock(bp->dev);
}

static void bnxt_rtnl_unlock_sp(struct bnxt *bp)
static void bnxt_unlock_sp(struct bnxt *bp)
{
	set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
	rtnl_unlock();
	netdev_unlock(bp->dev);
}

/* Only called from bnxt_sp_task() */
static void bnxt_reset(struct bnxt *bp, bool silent)
{
	bnxt_rtnl_lock_sp(bp);
	bnxt_lock_sp(bp);
	if (test_bit(BNXT_STATE_OPEN, &bp->state))
		bnxt_reset_task(bp, silent);
	bnxt_rtnl_unlock_sp(bp);
	bnxt_unlock_sp(bp);
}

/* Only called from bnxt_sp_task() */
@@ -13996,9 +13999,9 @@ static void bnxt_rx_ring_reset(struct bnxt *bp)
{
	int i;

	bnxt_rtnl_lock_sp(bp);
	bnxt_lock_sp(bp);
	if (!test_bit(BNXT_STATE_OPEN, &bp->state)) {
		bnxt_rtnl_unlock_sp(bp);
		bnxt_unlock_sp(bp);
		return;
	}
	/* Disable and flush TPA before resetting the RX ring */
@@ -14037,7 +14040,7 @@ static void bnxt_rx_ring_reset(struct bnxt *bp)
	}
	if (bp->flags & BNXT_FLAG_TPA)
		bnxt_set_tpa(bp, true);
	bnxt_rtnl_unlock_sp(bp);
	bnxt_unlock_sp(bp);
}

static void bnxt_fw_fatal_close(struct bnxt *bp)
@@ -14093,7 +14096,7 @@ static bool is_bnxt_fw_ok(struct bnxt *bp)
	return false;
}

/* rtnl_lock is acquired before calling this function */
/* netdev instance lock is acquired before calling this function */
static void bnxt_force_fw_reset(struct bnxt *bp)
{
	struct bnxt_fw_health *fw_health = bp->fw_health;
@@ -14136,9 +14139,9 @@ void bnxt_fw_exception(struct bnxt *bp)
	netdev_warn(bp->dev, "Detected firmware fatal condition, initiating reset\n");
	set_bit(BNXT_STATE_FW_FATAL_COND, &bp->state);
	bnxt_ulp_stop(bp);
	bnxt_rtnl_lock_sp(bp);
	bnxt_lock_sp(bp);
	bnxt_force_fw_reset(bp);
	bnxt_rtnl_unlock_sp(bp);
	bnxt_unlock_sp(bp);
}

/* Returns the number of registered VFs, or 1 if VF configuration is pending, or
@@ -14168,7 +14171,7 @@ static int bnxt_get_registered_vfs(struct bnxt *bp)
void bnxt_fw_reset(struct bnxt *bp)
{
	bnxt_ulp_stop(bp);
	bnxt_rtnl_lock_sp(bp);
	bnxt_lock_sp(bp);
	if (test_bit(BNXT_STATE_OPEN, &bp->state) &&
	    !test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
		struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
@@ -14214,7 +14217,7 @@ void bnxt_fw_reset(struct bnxt *bp)
		bnxt_queue_fw_reset_work(bp, tmo);
	}
fw_reset_exit:
	bnxt_rtnl_unlock_sp(bp);
	bnxt_unlock_sp(bp);
}

static void bnxt_chk_missed_irq(struct bnxt *bp)
@@ -14413,7 +14416,7 @@ static void bnxt_sp_task(struct work_struct *work)
static void _bnxt_get_max_rings(struct bnxt *bp, int *max_rx, int *max_tx,
				int *max_cp);

/* Under rtnl_lock */
/* Under netdev instance lock */
int bnxt_check_rings(struct bnxt *bp, int tx, int rx, bool sh, int tcs,
		     int tx_xdp)
{
@@ -14841,10 +14844,10 @@ static void bnxt_fw_reset_task(struct work_struct *work)
			return;
		}
		bp->fw_reset_timestamp = jiffies;
		rtnl_lock();
		netdev_lock(bp->dev);
		if (test_bit(BNXT_STATE_ABORT_ERR, &bp->state)) {
			bnxt_fw_reset_abort(bp, rc);
			rtnl_unlock();
			netdev_unlock(bp->dev);
			goto ulp_start;
		}
		bnxt_fw_reset_close(bp);
@@ -14855,7 +14858,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
			bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV;
			tmo = bp->fw_reset_min_dsecs * HZ / 10;
		}
		rtnl_unlock();
		netdev_unlock(bp->dev);
		bnxt_queue_fw_reset_work(bp, tmo);
		return;
	}
@@ -14929,7 +14932,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
		bp->fw_reset_state = BNXT_FW_RESET_STATE_OPENING;
		fallthrough;
	case BNXT_FW_RESET_STATE_OPENING:
		while (!rtnl_trylock()) {
		while (!netdev_trylock(bp->dev)) {
			bnxt_queue_fw_reset_work(bp, HZ / 10);
			return;
		}
@@ -14937,7 +14940,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
		if (rc) {
			netdev_err(bp->dev, "bnxt_open() failed during FW reset\n");
			bnxt_fw_reset_abort(bp, rc);
			rtnl_unlock();
			netdev_unlock(bp->dev);
			goto ulp_start;
		}

@@ -14956,13 +14959,13 @@ static void bnxt_fw_reset_task(struct work_struct *work)
			bnxt_dl_health_fw_recovery_done(bp);
			bnxt_dl_health_fw_status_update(bp, true);
		}
		rtnl_unlock();
		netdev_unlock(bp->dev);
		bnxt_ulp_start(bp, 0);
		bnxt_reenable_sriov(bp);
		rtnl_lock();
		netdev_lock(bp->dev);
		bnxt_vf_reps_alloc(bp);
		bnxt_vf_reps_open(bp);
		rtnl_unlock();
		netdev_unlock(bp->dev);
		break;
	}
	return;
@@ -14975,9 +14978,9 @@ static void bnxt_fw_reset_task(struct work_struct *work)
		netdev_err(bp->dev, "fw_health_status 0x%x\n", sts);
	}
fw_reset_abort:
	rtnl_lock();
	netdev_lock(bp->dev);
	bnxt_fw_reset_abort(bp, rc);
	rtnl_unlock();
	netdev_unlock(bp->dev);
ulp_start:
	bnxt_ulp_start(bp, rc);
}
@@ -15069,13 +15072,14 @@ static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev)
	return rc;
}

/* rtnl_lock held */
static int bnxt_change_mac_addr(struct net_device *dev, void *p)
{
	struct sockaddr *addr = p;
	struct bnxt *bp = netdev_priv(dev);
	int rc = 0;

	netdev_assert_locked(dev);

	if (!is_valid_ether_addr(addr->sa_data))
		return -EADDRNOTAVAIL;

@@ -15096,11 +15100,12 @@ static int bnxt_change_mac_addr(struct net_device *dev, void *p)
	return rc;
}

/* rtnl_lock held */
static int bnxt_change_mtu(struct net_device *dev, int new_mtu)
{
	struct bnxt *bp = netdev_priv(dev);

	netdev_assert_locked(dev);

	if (netif_running(dev))
		bnxt_close_nic(bp, true, false);

@@ -16257,7 +16262,7 @@ int bnxt_restore_pf_fw_resources(struct bnxt *bp)
{
	int rc;

	ASSERT_RTNL();
	netdev_ops_assert_locked(bp->dev);
	bnxt_hwrm_func_qcaps(bp);

	if (netif_running(bp->dev))
@@ -16657,7 +16662,7 @@ static void bnxt_shutdown(struct pci_dev *pdev)
	if (!dev)
		return;

	rtnl_lock();
	netdev_lock(dev);
	bp = netdev_priv(dev);
	if (!bp)
		goto shutdown_exit;
@@ -16675,7 +16680,7 @@ static void bnxt_shutdown(struct pci_dev *pdev)
	}

shutdown_exit:
	rtnl_unlock();
	netdev_unlock(dev);
}

#ifdef CONFIG_PM_SLEEP
@@ -16687,7 +16692,7 @@ static int bnxt_suspend(struct device *device)

	bnxt_ulp_stop(bp);

	rtnl_lock();
	netdev_lock(dev);
	if (netif_running(dev)) {
		netif_device_detach(dev);
		rc = bnxt_close(dev);
@@ -16696,7 +16701,7 @@ static int bnxt_suspend(struct device *device)
	bnxt_ptp_clear(bp);
	pci_disable_device(bp->pdev);
	bnxt_free_ctx_mem(bp, false);
	rtnl_unlock();
	netdev_unlock(dev);
	return rc;
}

@@ -16706,7 +16711,7 @@ static int bnxt_resume(struct device *device)
	struct bnxt *bp = netdev_priv(dev);
	int rc = 0;

	rtnl_lock();
	netdev_lock(dev);
	rc = pci_enable_device(bp->pdev);
	if (rc) {
		netdev_err(dev, "Cannot re-enable PCI device during resume, err = %d\n",
@@ -16749,7 +16754,7 @@ static int bnxt_resume(struct device *device)
	}

resume_exit:
	rtnl_unlock();
	netdev_unlock(bp->dev);
	bnxt_ulp_start(bp, rc);
	if (!rc)
		bnxt_reenable_sriov(bp);
@@ -16784,7 +16789,7 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,

	bnxt_ulp_stop(bp);

	rtnl_lock();
	netdev_lock(netdev);
	netif_device_detach(netdev);

	if (test_and_set_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
@@ -16793,7 +16798,7 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
	}

	if (abort || state == pci_channel_io_perm_failure) {
		rtnl_unlock();
		netdev_unlock(netdev);
		return PCI_ERS_RESULT_DISCONNECT;
	}

@@ -16812,7 +16817,7 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
	if (pci_is_enabled(pdev))
		pci_disable_device(pdev);
	bnxt_free_ctx_mem(bp, false);
	rtnl_unlock();
	netdev_unlock(netdev);

	/* Request a slot slot reset. */
	return PCI_ERS_RESULT_NEED_RESET;
@@ -16842,7 +16847,7 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
	    test_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN, &bp->state))
		msleep(900);

	rtnl_lock();
	netdev_lock(netdev);

	if (pci_enable_device(pdev)) {
		dev_err(&pdev->dev,
@@ -16897,7 +16902,7 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
reset_exit:
	clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
	bnxt_clear_reservations(bp, true);
	rtnl_unlock();
	netdev_unlock(netdev);

	return result;
}
@@ -16916,7 +16921,7 @@ static void bnxt_io_resume(struct pci_dev *pdev)
	int err;

	netdev_info(bp->dev, "PCI Slot Resume\n");
	rtnl_lock();
	netdev_lock(netdev);

	err = bnxt_hwrm_func_qcaps(bp);
	if (!err) {
@@ -16929,7 +16934,7 @@ static void bnxt_io_resume(struct pci_dev *pdev)
	if (!err)
		netif_device_attach(netdev);

	rtnl_unlock();
	netdev_unlock(netdev);
	bnxt_ulp_start(bp, err);
	if (!err)
		bnxt_reenable_sriov(bp);
+9 −0
Original line number Diff line number Diff line
@@ -439,14 +439,17 @@ static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change,
	case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: {
		bnxt_ulp_stop(bp);
		rtnl_lock();
		netdev_lock(bp->dev);
		if (bnxt_sriov_cfg(bp)) {
			NL_SET_ERR_MSG_MOD(extack,
					   "reload is unsupported while VFs are allocated or being configured");
			netdev_unlock(bp->dev);
			rtnl_unlock();
			bnxt_ulp_start(bp, 0);
			return -EOPNOTSUPP;
		}
		if (bp->dev->reg_state == NETREG_UNREGISTERED) {
			netdev_unlock(bp->dev);
			rtnl_unlock();
			bnxt_ulp_start(bp, 0);
			return -ENODEV;
@@ -459,6 +462,7 @@ static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change,
			NL_SET_ERR_MSG_MOD(extack, "Failed to deregister");
			if (netif_running(bp->dev))
				dev_close(bp->dev);
			netdev_unlock(bp->dev);
			rtnl_unlock();
			break;
		}
@@ -479,7 +483,9 @@ static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change,
			return -EPERM;
		}
		rtnl_lock();
		netdev_lock(bp->dev);
		if (bp->dev->reg_state == NETREG_UNREGISTERED) {
			netdev_unlock(bp->dev);
			rtnl_unlock();
			return -ENODEV;
		}
@@ -493,6 +499,7 @@ static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change,
		if (rc) {
			NL_SET_ERR_MSG_MOD(extack, "Failed to activate firmware");
			clear_bit(BNXT_STATE_FW_ACTIVATE, &bp->state);
			netdev_unlock(bp->dev);
			rtnl_unlock();
		}
		break;
@@ -568,7 +575,9 @@ static int bnxt_dl_reload_up(struct devlink *dl, enum devlink_reload_action acti
		}
		*actions_performed |= BIT(action);
	} else if (netif_running(bp->dev)) {
		netdev_lock(bp->dev);
		dev_close(bp->dev);
		netdev_unlock(bp->dev);
	}
	rtnl_unlock();
	if (action == DEVLINK_RELOAD_ACTION_DRIVER_REINIT)
+6 −0
Original line number Diff line number Diff line
@@ -946,7 +946,9 @@ void bnxt_sriov_disable(struct bnxt *bp)

	/* Reclaim all resources for the PF. */
	rtnl_lock();
	netdev_lock(bp->dev);
	bnxt_restore_pf_fw_resources(bp);
	netdev_unlock(bp->dev);
	rtnl_unlock();
}

@@ -956,17 +958,21 @@ int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs)
	struct bnxt *bp = netdev_priv(dev);

	rtnl_lock();
	netdev_lock(dev);
	if (!netif_running(dev)) {
		netdev_warn(dev, "Reject SRIOV config request since if is down!\n");
		netdev_unlock(dev);
		rtnl_unlock();
		return 0;
	}
	if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
		netdev_warn(dev, "Reject SRIOV config request when FW reset is in progress\n");
		netdev_unlock(dev);
		rtnl_unlock();
		return 0;
	}
	bp->sriov_cfg = true;
	netdev_unlock(dev);
	rtnl_unlock();

	if (pci_vfs_assigned(bp->pdev)) {
Loading