Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f13d1b48 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'netpoll-second-round-of-fixes'



Eric Dumazet says:

====================
netpoll: second round of fixes.

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.

First patch is a fix in poll_one_napi().

Then following patches take care of ten drivers.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 05c5e9ff 0c3b9d1b
Loading
Loading
Loading
Loading
+0 −22
Original line number Diff line number Diff line
@@ -2185,25 +2185,6 @@ static netdev_tx_t ena_start_xmit(struct sk_buff *skb, struct net_device *dev)
	return NETDEV_TX_OK;
}

#ifdef CONFIG_NET_POLL_CONTROLLER
static void ena_netpoll(struct net_device *netdev)
{
	struct ena_adapter *adapter = netdev_priv(netdev);
	int i;

	/* Dont schedule NAPI if the driver is in the middle of reset
	 * or netdev is down.
	 */

	if (!test_bit(ENA_FLAG_DEV_UP, &adapter->flags) ||
	    test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags))
		return;

	for (i = 0; i < adapter->num_queues; i++)
		napi_schedule(&adapter->ena_napi[i].napi);
}
#endif /* CONFIG_NET_POLL_CONTROLLER */

static u16 ena_select_queue(struct net_device *dev, struct sk_buff *skb,
			    struct net_device *sb_dev,
			    select_queue_fallback_t fallback)
@@ -2369,9 +2350,6 @@ static const struct net_device_ops ena_netdev_ops = {
	.ndo_change_mtu		= ena_change_mtu,
	.ndo_set_mac_address	= NULL,
	.ndo_validate_addr	= eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= ena_netpoll,
#endif /* CONFIG_NET_POLL_CONTROLLER */
};

static int ena_device_validate_params(struct ena_adapter *adapter,
+0 −18
Original line number Diff line number Diff line
@@ -1503,21 +1503,6 @@ static int hns_nic_do_ioctl(struct net_device *netdev, struct ifreq *ifr,
	return phy_mii_ioctl(phy_dev, ifr, cmd);
}

/* use only for netconsole to poll with the device without interrupt */
#ifdef CONFIG_NET_POLL_CONTROLLER
static void hns_nic_poll_controller(struct net_device *ndev)
{
	struct hns_nic_priv *priv = netdev_priv(ndev);
	unsigned long flags;
	int i;

	local_irq_save(flags);
	for (i = 0; i < priv->ae_handle->q_num * 2; i++)
		napi_schedule(&priv->ring_data[i].napi);
	local_irq_restore(flags);
}
#endif

static netdev_tx_t hns_nic_net_xmit(struct sk_buff *skb,
				    struct net_device *ndev)
{
@@ -1970,9 +1955,6 @@ static const struct net_device_ops hns_nic_netdev_ops = {
	.ndo_set_features = hns_nic_set_features,
	.ndo_fix_features = hns_nic_fix_features,
	.ndo_get_stats64 = hns_nic_get_stats64,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller = hns_nic_poll_controller,
#endif
	.ndo_set_rx_mode = hns_nic_set_rx_mode,
	.ndo_select_queue = hns_nic_select_queue,
};
+0 −20
Original line number Diff line number Diff line
@@ -789,23 +789,6 @@ static void hinic_get_stats64(struct net_device *netdev,
	stats->tx_errors  = nic_tx_stats->tx_dropped;
}

#ifdef CONFIG_NET_POLL_CONTROLLER
static void hinic_netpoll(struct net_device *netdev)
{
	struct hinic_dev *nic_dev = netdev_priv(netdev);
	int i, num_qps;

	num_qps = hinic_hwdev_num_qps(nic_dev->hwdev);
	for (i = 0; i < num_qps; i++) {
		struct hinic_txq *txq = &nic_dev->txqs[i];
		struct hinic_rxq *rxq = &nic_dev->rxqs[i];

		napi_schedule(&txq->napi);
		napi_schedule(&rxq->napi);
	}
}
#endif

static const struct net_device_ops hinic_netdev_ops = {
	.ndo_open = hinic_open,
	.ndo_stop = hinic_close,
@@ -818,9 +801,6 @@ static const struct net_device_ops hinic_netdev_ops = {
	.ndo_start_xmit = hinic_xmit_frame,
	.ndo_tx_timeout = hinic_tx_timeout,
	.ndo_get_stats64 = hinic_get_stats64,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller = hinic_netpoll,
#endif
};

static void netdev_features_init(struct net_device *netdev)
+0 −14
Original line number Diff line number Diff line
@@ -921,17 +921,6 @@ static int ehea_poll(struct napi_struct *napi, int budget)
	return rx;
}

#ifdef CONFIG_NET_POLL_CONTROLLER
static void ehea_netpoll(struct net_device *dev)
{
	struct ehea_port *port = netdev_priv(dev);
	int i;

	for (i = 0; i < port->num_def_qps; i++)
		napi_schedule(&port->port_res[i].napi);
}
#endif

static irqreturn_t ehea_recv_irq_handler(int irq, void *param)
{
	struct ehea_port_res *pr = param;
@@ -2953,9 +2942,6 @@ static const struct net_device_ops ehea_netdev_ops = {
	.ndo_open		= ehea_open,
	.ndo_stop		= ehea_stop,
	.ndo_start_xmit		= ehea_start_xmit,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= ehea_netpoll,
#endif
	.ndo_get_stats64	= ehea_get_stats64,
	.ndo_set_mac_address	= ehea_set_mac_addr,
	.ndo_validate_addr	= eth_validate_addr,
+0 −16
Original line number Diff line number Diff line
@@ -2207,19 +2207,6 @@ static int ibmvnic_poll(struct napi_struct *napi, int budget)
	return frames_processed;
}

#ifdef CONFIG_NET_POLL_CONTROLLER
static void ibmvnic_netpoll_controller(struct net_device *dev)
{
	struct ibmvnic_adapter *adapter = netdev_priv(dev);
	int i;

	replenish_pools(netdev_priv(dev));
	for (i = 0; i < adapter->req_rx_queues; i++)
		ibmvnic_interrupt_rx(adapter->rx_scrq[i]->irq,
				     adapter->rx_scrq[i]);
}
#endif

static int wait_for_reset(struct ibmvnic_adapter *adapter)
{
	int rc, ret;
@@ -2292,9 +2279,6 @@ static const struct net_device_ops ibmvnic_netdev_ops = {
	.ndo_set_mac_address	= ibmvnic_set_mac,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_tx_timeout		= ibmvnic_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= ibmvnic_netpoll_controller,
#endif
	.ndo_change_mtu		= ibmvnic_change_mtu,
	.ndo_features_check     = ibmvnic_features_check,
};
Loading