forked from Minki/linux
Merge branch 'netpoll-avoid-capture-effects-for-NAPI-drivers'
Eric Dumazet says: ==================== netpoll: avoid capture effects for NAPI drivers As diagnosed by Song Liu, ndo_poll_controller() can be very dangerous on loaded hosts, since the cpu calling ndo_poll_controller() might steal all NAPI contexts (for all RX/TX queues of the NIC). This capture, showing one ksoftirqd eating all cycles can last for unlimited amount of time, since one cpu is generally not able to drain all the queues under load. It seems that all networking drivers that do use NAPI for their TX completions, should not provide a ndo_poll_controller() : Most NAPI drivers have netpoll support already handled in core networking stack, since netpoll_poll_dev() uses poll_napi(dev) to iterate through registered NAPI contexts for a device. This patch series take care of the first round, we will handle other drivers in future rounds. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
841dfa4378
@ -971,16 +971,13 @@ static void bond_poll_controller(struct net_device *bond_dev)
|
||||
struct slave *slave = NULL;
|
||||
struct list_head *iter;
|
||||
struct ad_info ad_info;
|
||||
struct netpoll_info *ni;
|
||||
const struct net_device_ops *ops;
|
||||
|
||||
if (BOND_MODE(bond) == BOND_MODE_8023AD)
|
||||
if (bond_3ad_get_active_agg_info(bond, &ad_info))
|
||||
return;
|
||||
|
||||
bond_for_each_slave_rcu(bond, slave, iter) {
|
||||
ops = slave->dev->netdev_ops;
|
||||
if (!bond_slave_is_up(slave) || !ops->ndo_poll_controller)
|
||||
if (!bond_slave_is_up(slave))
|
||||
continue;
|
||||
|
||||
if (BOND_MODE(bond) == BOND_MODE_8023AD) {
|
||||
@ -992,11 +989,7 @@ static void bond_poll_controller(struct net_device *bond_dev)
|
||||
continue;
|
||||
}
|
||||
|
||||
ni = rcu_dereference_bh(slave->dev->npinfo);
|
||||
if (down_trylock(&ni->dev_lock))
|
||||
continue;
|
||||
ops->ndo_poll_controller(slave->dev);
|
||||
up(&ni->dev_lock);
|
||||
netpoll_poll_dev(slave->dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12894,19 +12894,6 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
static void poll_bnx2x(struct net_device *dev)
|
||||
{
|
||||
struct bnx2x *bp = netdev_priv(dev);
|
||||
int i;
|
||||
|
||||
for_each_eth_queue(bp, i) {
|
||||
struct bnx2x_fastpath *fp = &bp->fp[i];
|
||||
napi_schedule(&bnx2x_fp(bp, fp->index, napi));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int bnx2x_validate_addr(struct net_device *dev)
|
||||
{
|
||||
struct bnx2x *bp = netdev_priv(dev);
|
||||
@ -13113,9 +13100,6 @@ static const struct net_device_ops bnx2x_netdev_ops = {
|
||||
.ndo_tx_timeout = bnx2x_tx_timeout,
|
||||
.ndo_vlan_rx_add_vid = bnx2x_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = bnx2x_vlan_rx_kill_vid,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = poll_bnx2x,
|
||||
#endif
|
||||
.ndo_setup_tc = __bnx2x_setup_tc,
|
||||
#ifdef CONFIG_BNX2X_SRIOV
|
||||
.ndo_set_vf_mac = bnx2x_set_vf_mac,
|
||||
|
@ -7672,21 +7672,6 @@ static void bnxt_tx_timeout(struct net_device *dev)
|
||||
bnxt_queue_sp_work(bp);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
static void bnxt_poll_controller(struct net_device *dev)
|
||||
{
|
||||
struct bnxt *bp = netdev_priv(dev);
|
||||
int i;
|
||||
|
||||
/* Only process tx rings/combined rings in netpoll mode. */
|
||||
for (i = 0; i < bp->tx_nr_rings; i++) {
|
||||
struct bnxt_tx_ring_info *txr = &bp->tx_ring[i];
|
||||
|
||||
napi_schedule(&txr->bnapi->napi);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void bnxt_timer(struct timer_list *t)
|
||||
{
|
||||
struct bnxt *bp = from_timer(bp, t, timer);
|
||||
@ -8519,9 +8504,6 @@ static const struct net_device_ops bnxt_netdev_ops = {
|
||||
.ndo_set_vf_link_state = bnxt_set_vf_link_state,
|
||||
.ndo_set_vf_spoofchk = bnxt_set_vf_spoofchk,
|
||||
.ndo_set_vf_trust = bnxt_set_vf_trust,
|
||||
#endif
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = bnxt_poll_controller,
|
||||
#endif
|
||||
.ndo_setup_tc = bnxt_setup_tc,
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
|
@ -504,9 +504,6 @@ void fm10k_update_stats(struct fm10k_intfc *interface);
|
||||
void fm10k_service_event_schedule(struct fm10k_intfc *interface);
|
||||
void fm10k_macvlan_schedule(struct fm10k_intfc *interface);
|
||||
void fm10k_update_rx_drop_en(struct fm10k_intfc *interface);
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
void fm10k_netpoll(struct net_device *netdev);
|
||||
#endif
|
||||
|
||||
/* Netdev */
|
||||
struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info);
|
||||
|
@ -1648,9 +1648,6 @@ static const struct net_device_ops fm10k_netdev_ops = {
|
||||
.ndo_udp_tunnel_del = fm10k_udp_tunnel_del,
|
||||
.ndo_dfwd_add_station = fm10k_dfwd_add_station,
|
||||
.ndo_dfwd_del_station = fm10k_dfwd_del_station,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = fm10k_netpoll,
|
||||
#endif
|
||||
.ndo_features_check = fm10k_features_check,
|
||||
};
|
||||
|
||||
|
@ -1210,28 +1210,6 @@ static irqreturn_t fm10k_msix_mbx_vf(int __always_unused irq, void *data)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
/**
|
||||
* fm10k_netpoll - A Polling 'interrupt' handler
|
||||
* @netdev: network interface device structure
|
||||
*
|
||||
* This is used by netconsole to send skbs without having to re-enable
|
||||
* interrupts. It's not called while the normal interrupt routine is executing.
|
||||
**/
|
||||
void fm10k_netpoll(struct net_device *netdev)
|
||||
{
|
||||
struct fm10k_intfc *interface = netdev_priv(netdev);
|
||||
int i;
|
||||
|
||||
/* if interface is down do nothing */
|
||||
if (test_bit(__FM10K_DOWN, interface->state))
|
||||
return;
|
||||
|
||||
for (i = 0; i < interface->num_q_vectors; i++)
|
||||
fm10k_msix_clean_rings(0, interface->q_vector[i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
#define FM10K_ERR_MSG(type) case (type): error = #type; break
|
||||
static void fm10k_handle_fault(struct fm10k_intfc *interface, int type,
|
||||
struct fm10k_fault *fault)
|
||||
|
@ -396,29 +396,6 @@ static void i40evf_map_rings_to_vectors(struct i40evf_adapter *adapter)
|
||||
adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
/**
|
||||
* i40evf_netpoll - A Polling 'interrupt' handler
|
||||
* @netdev: network interface device structure
|
||||
*
|
||||
* This is used by netconsole to send skbs without having to re-enable
|
||||
* interrupts. It's not called while the normal interrupt routine is executing.
|
||||
**/
|
||||
static void i40evf_netpoll(struct net_device *netdev)
|
||||
{
|
||||
struct i40evf_adapter *adapter = netdev_priv(netdev);
|
||||
int q_vectors = adapter->num_msix_vectors - NONQ_VECS;
|
||||
int i;
|
||||
|
||||
/* if interface is down do nothing */
|
||||
if (test_bit(__I40E_VSI_DOWN, adapter->vsi.state))
|
||||
return;
|
||||
|
||||
for (i = 0; i < q_vectors; i++)
|
||||
i40evf_msix_clean_rings(0, &adapter->q_vectors[i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* i40evf_irq_affinity_notify - Callback for affinity changes
|
||||
* @notify: context as to what irq was changed
|
||||
@ -3229,9 +3206,6 @@ static const struct net_device_ops i40evf_netdev_ops = {
|
||||
.ndo_features_check = i40evf_features_check,
|
||||
.ndo_fix_features = i40evf_fix_features,
|
||||
.ndo_set_features = i40evf_set_features,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = i40evf_netpoll,
|
||||
#endif
|
||||
.ndo_setup_tc = i40evf_setup_tc,
|
||||
};
|
||||
|
||||
|
@ -4806,30 +4806,6 @@ void ice_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
|
||||
stats->rx_length_errors = vsi_stats->rx_length_errors;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
/**
|
||||
* ice_netpoll - polling "interrupt" handler
|
||||
* @netdev: network interface device structure
|
||||
*
|
||||
* Used by netconsole to send skbs without having to re-enable interrupts.
|
||||
* This is not called in the normal interrupt path.
|
||||
*/
|
||||
static void ice_netpoll(struct net_device *netdev)
|
||||
{
|
||||
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||
struct ice_vsi *vsi = np->vsi;
|
||||
struct ice_pf *pf = vsi->back;
|
||||
int i;
|
||||
|
||||
if (test_bit(__ICE_DOWN, vsi->state) ||
|
||||
!test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
|
||||
return;
|
||||
|
||||
for (i = 0; i < vsi->num_q_vectors; i++)
|
||||
ice_msix_clean_rings(0, vsi->q_vectors[i]);
|
||||
}
|
||||
#endif /* CONFIG_NET_POLL_CONTROLLER */
|
||||
|
||||
/**
|
||||
* ice_napi_disable_all - Disable NAPI for all q_vectors in the VSI
|
||||
* @vsi: VSI having NAPI disabled
|
||||
@ -5497,9 +5473,6 @@ static const struct net_device_ops ice_netdev_ops = {
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_change_mtu = ice_change_mtu,
|
||||
.ndo_get_stats64 = ice_get_stats64,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = ice_netpoll,
|
||||
#endif /* CONFIG_NET_POLL_CONTROLLER */
|
||||
.ndo_vlan_rx_add_vid = ice_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = ice_vlan_rx_kill_vid,
|
||||
.ndo_set_features = ice_set_features,
|
||||
|
@ -205,10 +205,6 @@ static struct notifier_block dca_notifier = {
|
||||
.priority = 0
|
||||
};
|
||||
#endif
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
/* for netdump / net console */
|
||||
static void igb_netpoll(struct net_device *);
|
||||
#endif
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
static unsigned int max_vfs;
|
||||
module_param(max_vfs, uint, 0);
|
||||
@ -2881,9 +2877,6 @@ static const struct net_device_ops igb_netdev_ops = {
|
||||
.ndo_set_vf_spoofchk = igb_ndo_set_vf_spoofchk,
|
||||
.ndo_set_vf_trust = igb_ndo_set_vf_trust,
|
||||
.ndo_get_vf_config = igb_ndo_get_vf_config,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = igb_netpoll,
|
||||
#endif
|
||||
.ndo_fix_features = igb_fix_features,
|
||||
.ndo_set_features = igb_set_features,
|
||||
.ndo_fdb_add = igb_ndo_fdb_add,
|
||||
@ -9053,29 +9046,6 @@ static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
/* Polling 'interrupt' - used by things like netconsole to send skbs
|
||||
* without having to re-enable interrupts. It's not called while
|
||||
* the interrupt routine is executing.
|
||||
*/
|
||||
static void igb_netpoll(struct net_device *netdev)
|
||||
{
|
||||
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
struct igb_q_vector *q_vector;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < adapter->num_q_vectors; i++) {
|
||||
q_vector = adapter->q_vector[i];
|
||||
if (adapter->flags & IGB_FLAG_HAS_MSIX)
|
||||
wr32(E1000_EIMC, q_vector->eims_value);
|
||||
else
|
||||
igb_irq_disable(adapter);
|
||||
napi_schedule(&q_vector->napi);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_NET_POLL_CONTROLLER */
|
||||
|
||||
/**
|
||||
* igb_io_error_detected - called when PCI error is detected
|
||||
* @pdev: Pointer to PCI device
|
||||
|
@ -81,11 +81,6 @@ static int ixgb_vlan_rx_kill_vid(struct net_device *netdev,
|
||||
__be16 proto, u16 vid);
|
||||
static void ixgb_restore_vlan(struct ixgb_adapter *adapter);
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
/* for netdump / net console */
|
||||
static void ixgb_netpoll(struct net_device *dev);
|
||||
#endif
|
||||
|
||||
static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev,
|
||||
enum pci_channel_state state);
|
||||
static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev);
|
||||
@ -348,9 +343,6 @@ static const struct net_device_ops ixgb_netdev_ops = {
|
||||
.ndo_tx_timeout = ixgb_tx_timeout,
|
||||
.ndo_vlan_rx_add_vid = ixgb_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = ixgb_vlan_rx_kill_vid,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = ixgb_netpoll,
|
||||
#endif
|
||||
.ndo_fix_features = ixgb_fix_features,
|
||||
.ndo_set_features = ixgb_set_features,
|
||||
};
|
||||
@ -2195,23 +2187,6 @@ ixgb_restore_vlan(struct ixgb_adapter *adapter)
|
||||
ixgb_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
/*
|
||||
* Polling 'interrupt' - used by things like netconsole to send skbs
|
||||
* without having to re-enable interrupts. It's not called while
|
||||
* the interrupt routine is executing.
|
||||
*/
|
||||
|
||||
static void ixgb_netpoll(struct net_device *dev)
|
||||
{
|
||||
struct ixgb_adapter *adapter = netdev_priv(dev);
|
||||
|
||||
disable_irq(adapter->pdev->irq);
|
||||
ixgb_intr(adapter->pdev->irq, dev);
|
||||
enable_irq(adapter->pdev->irq);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ixgb_io_error_detected - called when PCI error is detected
|
||||
* @pdev: pointer to pci device with error
|
||||
|
@ -8768,28 +8768,6 @@ static int ixgbe_del_sanmac_netdev(struct net_device *dev)
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
/*
|
||||
* Polling 'interrupt' - used by things like netconsole to send skbs
|
||||
* without having to re-enable interrupts. It's not called while
|
||||
* the interrupt routine is executing.
|
||||
*/
|
||||
static void ixgbe_netpoll(struct net_device *netdev)
|
||||
{
|
||||
struct ixgbe_adapter *adapter = netdev_priv(netdev);
|
||||
int i;
|
||||
|
||||
/* if interface is down do nothing */
|
||||
if (test_bit(__IXGBE_DOWN, &adapter->state))
|
||||
return;
|
||||
|
||||
/* loop through and schedule all active queues */
|
||||
for (i = 0; i < adapter->num_q_vectors; i++)
|
||||
ixgbe_msix_clean_rings(0, adapter->q_vector[i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void ixgbe_get_ring_stats64(struct rtnl_link_stats64 *stats,
|
||||
struct ixgbe_ring *ring)
|
||||
{
|
||||
@ -10251,9 +10229,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
|
||||
.ndo_get_vf_config = ixgbe_ndo_get_vf_config,
|
||||
.ndo_get_stats64 = ixgbe_get_stats64,
|
||||
.ndo_setup_tc = __ixgbe_setup_tc,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = ixgbe_netpoll,
|
||||
#endif
|
||||
#ifdef IXGBE_FCOE
|
||||
.ndo_select_queue = ixgbe_select_queue,
|
||||
.ndo_fcoe_ddp_setup = ixgbe_fcoe_ddp_get,
|
||||
|
@ -4233,24 +4233,6 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
/* Polling 'interrupt' - used by things like netconsole to send skbs
|
||||
* without having to re-enable interrupts. It's not called while
|
||||
* the interrupt routine is executing.
|
||||
*/
|
||||
static void ixgbevf_netpoll(struct net_device *netdev)
|
||||
{
|
||||
struct ixgbevf_adapter *adapter = netdev_priv(netdev);
|
||||
int i;
|
||||
|
||||
/* if interface is down do nothing */
|
||||
if (test_bit(__IXGBEVF_DOWN, &adapter->state))
|
||||
return;
|
||||
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||
ixgbevf_msix_clean_rings(0, adapter->q_vector[i]);
|
||||
}
|
||||
#endif /* CONFIG_NET_POLL_CONTROLLER */
|
||||
|
||||
static int ixgbevf_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||
@ -4482,9 +4464,6 @@ static const struct net_device_ops ixgbevf_netdev_ops = {
|
||||
.ndo_tx_timeout = ixgbevf_tx_timeout,
|
||||
.ndo_vlan_rx_add_vid = ixgbevf_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = ixgbevf_vlan_rx_kill_vid,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = ixgbevf_netpoll,
|
||||
#endif
|
||||
.ndo_features_check = ixgbevf_features_check,
|
||||
.ndo_bpf = ixgbevf_xdp,
|
||||
};
|
||||
|
@ -1286,20 +1286,6 @@ out:
|
||||
mutex_unlock(&mdev->state_lock);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
static void mlx4_en_netpoll(struct net_device *dev)
|
||||
{
|
||||
struct mlx4_en_priv *priv = netdev_priv(dev);
|
||||
struct mlx4_en_cq *cq;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->tx_ring_num[TX]; i++) {
|
||||
cq = priv->tx_cq[TX][i];
|
||||
napi_schedule(&cq->napi);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int mlx4_en_set_rss_steer_rules(struct mlx4_en_priv *priv)
|
||||
{
|
||||
u64 reg_id;
|
||||
@ -2946,9 +2932,6 @@ static const struct net_device_ops mlx4_netdev_ops = {
|
||||
.ndo_tx_timeout = mlx4_en_tx_timeout,
|
||||
.ndo_vlan_rx_add_vid = mlx4_en_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = mlx4_en_vlan_rx_kill_vid,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = mlx4_en_netpoll,
|
||||
#endif
|
||||
.ndo_set_features = mlx4_en_set_features,
|
||||
.ndo_fix_features = mlx4_en_fix_features,
|
||||
.ndo_setup_tc = __mlx4_en_setup_tc,
|
||||
@ -2983,9 +2966,6 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
|
||||
.ndo_set_vf_link_state = mlx4_en_set_vf_link_state,
|
||||
.ndo_get_vf_stats = mlx4_en_get_vf_stats,
|
||||
.ndo_get_vf_config = mlx4_en_get_vf_config,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = mlx4_en_netpoll,
|
||||
#endif
|
||||
.ndo_set_features = mlx4_en_set_features,
|
||||
.ndo_fix_features = mlx4_en_fix_features,
|
||||
.ndo_setup_tc = __mlx4_en_setup_tc,
|
||||
|
@ -4315,22 +4315,6 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
/* Fake "interrupt" called by netpoll (eg netconsole) to send skbs without
|
||||
* reenabling interrupts.
|
||||
*/
|
||||
static void mlx5e_netpoll(struct net_device *dev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(dev);
|
||||
struct mlx5e_channels *chs = &priv->channels;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < chs->num; i++)
|
||||
napi_schedule(&chs->c[i]->napi);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct net_device_ops mlx5e_netdev_ops = {
|
||||
.ndo_open = mlx5e_open,
|
||||
.ndo_stop = mlx5e_close,
|
||||
@ -4356,9 +4340,6 @@ static const struct net_device_ops mlx5e_netdev_ops = {
|
||||
#ifdef CONFIG_MLX5_EN_ARFS
|
||||
.ndo_rx_flow_steer = mlx5e_rx_flow_steer,
|
||||
#endif
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = mlx5e_netpoll,
|
||||
#endif
|
||||
#ifdef CONFIG_MLX5_ESWITCH
|
||||
/* SRIOV E-Switch NDOs */
|
||||
.ndo_set_vf_mac = mlx5e_set_vf_mac,
|
||||
|
@ -3146,21 +3146,6 @@ nfp_net_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
|
||||
return nfp_net_reconfig_mbox(nn, NFP_NET_CFG_MBOX_CMD_CTAG_FILTER_KILL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
static void nfp_net_netpoll(struct net_device *netdev)
|
||||
{
|
||||
struct nfp_net *nn = netdev_priv(netdev);
|
||||
int i;
|
||||
|
||||
/* nfp_net's NAPIs are statically allocated so even if there is a race
|
||||
* with reconfig path this will simply try to schedule some disabled
|
||||
* NAPI instances.
|
||||
*/
|
||||
for (i = 0; i < nn->dp.num_stack_tx_rings; i++)
|
||||
napi_schedule_irqoff(&nn->r_vecs[i].napi);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void nfp_net_stat64(struct net_device *netdev,
|
||||
struct rtnl_link_stats64 *stats)
|
||||
{
|
||||
@ -3519,9 +3504,6 @@ const struct net_device_ops nfp_net_netdev_ops = {
|
||||
.ndo_get_stats64 = nfp_net_stat64,
|
||||
.ndo_vlan_rx_add_vid = nfp_net_vlan_rx_add_vid,
|
||||
.ndo_vlan_rx_kill_vid = nfp_net_vlan_rx_kill_vid,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = nfp_net_netpoll,
|
||||
#endif
|
||||
.ndo_set_vf_mac = nfp_app_set_vf_mac,
|
||||
.ndo_set_vf_vlan = nfp_app_set_vf_vlan,
|
||||
.ndo_set_vf_spoofchk = nfp_app_set_vf_spoofchk,
|
||||
|
@ -1153,43 +1153,6 @@ static netdev_features_t tun_net_fix_features(struct net_device *dev,
|
||||
|
||||
return (features & tun->set_features) | (features & ~TUN_USER_FEATURES);
|
||||
}
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
static void tun_poll_controller(struct net_device *dev)
|
||||
{
|
||||
/*
|
||||
* Tun only receives frames when:
|
||||
* 1) the char device endpoint gets data from user space
|
||||
* 2) the tun socket gets a sendmsg call from user space
|
||||
* If NAPI is not enabled, since both of those are synchronous
|
||||
* operations, we are guaranteed never to have pending data when we poll
|
||||
* for it so there is nothing to do here but return.
|
||||
* We need this though so netpoll recognizes us as an interface that
|
||||
* supports polling, which enables bridge devices in virt setups to
|
||||
* still use netconsole
|
||||
* If NAPI is enabled, however, we need to schedule polling for all
|
||||
* queues unless we are using napi_gro_frags(), which we call in
|
||||
* process context and not in NAPI context.
|
||||
*/
|
||||
struct tun_struct *tun = netdev_priv(dev);
|
||||
|
||||
if (tun->flags & IFF_NAPI) {
|
||||
struct tun_file *tfile;
|
||||
int i;
|
||||
|
||||
if (tun_napi_frags_enabled(tun))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
for (i = 0; i < tun->numqueues; i++) {
|
||||
tfile = rcu_dereference(tun->tfiles[i]);
|
||||
if (tfile->napi_enabled)
|
||||
napi_schedule(&tfile->napi);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void tun_set_headroom(struct net_device *dev, int new_hr)
|
||||
{
|
||||
@ -1283,9 +1246,6 @@ static const struct net_device_ops tun_netdev_ops = {
|
||||
.ndo_start_xmit = tun_net_xmit,
|
||||
.ndo_fix_features = tun_net_fix_features,
|
||||
.ndo_select_queue = tun_select_queue,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = tun_poll_controller,
|
||||
#endif
|
||||
.ndo_set_rx_headroom = tun_set_headroom,
|
||||
.ndo_get_stats64 = tun_net_get_stats64,
|
||||
};
|
||||
@ -1365,9 +1325,6 @@ static const struct net_device_ops tap_netdev_ops = {
|
||||
.ndo_set_mac_address = eth_mac_addr,
|
||||
.ndo_validate_addr = eth_validate_addr,
|
||||
.ndo_select_queue = tun_select_queue,
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
.ndo_poll_controller = tun_poll_controller,
|
||||
#endif
|
||||
.ndo_features_check = passthru_features_check,
|
||||
.ndo_set_rx_headroom = tun_set_headroom,
|
||||
.ndo_get_stats64 = tun_net_get_stats64,
|
||||
|
@ -49,8 +49,9 @@ struct netpoll_info {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_NETPOLL
|
||||
extern void netpoll_poll_disable(struct net_device *dev);
|
||||
extern void netpoll_poll_enable(struct net_device *dev);
|
||||
void netpoll_poll_dev(struct net_device *dev);
|
||||
void netpoll_poll_disable(struct net_device *dev);
|
||||
void netpoll_poll_enable(struct net_device *dev);
|
||||
#else
|
||||
static inline void netpoll_poll_disable(struct net_device *dev) { return; }
|
||||
static inline void netpoll_poll_enable(struct net_device *dev) { return; }
|
||||
|
@ -187,16 +187,16 @@ static void poll_napi(struct net_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void netpoll_poll_dev(struct net_device *dev)
|
||||
void netpoll_poll_dev(struct net_device *dev)
|
||||
{
|
||||
const struct net_device_ops *ops;
|
||||
struct netpoll_info *ni = rcu_dereference_bh(dev->npinfo);
|
||||
const struct net_device_ops *ops;
|
||||
|
||||
/* Don't do any rx activity if the dev_lock mutex is held
|
||||
* the dev_open/close paths use this to block netpoll activity
|
||||
* while changing device state
|
||||
*/
|
||||
if (down_trylock(&ni->dev_lock))
|
||||
if (!ni || down_trylock(&ni->dev_lock))
|
||||
return;
|
||||
|
||||
if (!netif_running(dev)) {
|
||||
@ -205,13 +205,8 @@ static void netpoll_poll_dev(struct net_device *dev)
|
||||
}
|
||||
|
||||
ops = dev->netdev_ops;
|
||||
if (!ops->ndo_poll_controller) {
|
||||
up(&ni->dev_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Process pending work on NIC */
|
||||
ops->ndo_poll_controller(dev);
|
||||
if (ops->ndo_poll_controller)
|
||||
ops->ndo_poll_controller(dev);
|
||||
|
||||
poll_napi(dev);
|
||||
|
||||
@ -219,6 +214,7 @@ static void netpoll_poll_dev(struct net_device *dev)
|
||||
|
||||
zap_completion_queue();
|
||||
}
|
||||
EXPORT_SYMBOL(netpoll_poll_dev);
|
||||
|
||||
void netpoll_poll_disable(struct net_device *dev)
|
||||
{
|
||||
@ -613,8 +609,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
|
||||
strlcpy(np->dev_name, ndev->name, IFNAMSIZ);
|
||||
INIT_WORK(&np->cleanup_work, netpoll_async_cleanup);
|
||||
|
||||
if ((ndev->priv_flags & IFF_DISABLE_NETPOLL) ||
|
||||
!ndev->netdev_ops->ndo_poll_controller) {
|
||||
if (ndev->priv_flags & IFF_DISABLE_NETPOLL) {
|
||||
np_err(np, "%s doesn't support polling, aborting\n",
|
||||
np->dev_name);
|
||||
err = -ENOTSUPP;
|
||||
|
Loading…
Reference in New Issue
Block a user