summary refs log tree commit diff
path: root/drivers/s390/net/qeth_ethtool.c
diff options
context:
space:
mode:
authorJulian Wiedmann <jwi@linux.ibm.com>2020-03-18 13:54:49 +0100
committerDavid S. Miller <davem@davemloft.net>2020-03-18 16:33:35 -0700
commit66cddf101901a6cfcd21c840f0535e8f1c8c5186 (patch)
tree4da44babbd507b5797611e5e0957906d74c42d8d /drivers/s390/net/qeth_ethtool.c
parentfcc2df8b8777c960c8125bc157423c76415a5419 (diff)
downloadlinux-66cddf101901a6cfcd21c840f0535e8f1c8c5186.tar.gz
s390/qeth: allow configuration of TX queues for IQD devices
Similar to the support for z/VM NICs, but we need to take extra care
about the dedicated mcast queue:

1. netdev_pick_tx() is unaware of this limitation and might select the
   mcast txq. Catch this.
2. require at least _two_ TX queues - one for ucast, one for mcast.
3. when reducing the number of TX queues, there's a potential race
   where netdev_cap_txqueue() over-rules the selected txq index and
   falls back to index 0. This would place ucast traffic on the mcast
   queue, and result in TX errors.
   So for IQD, reject a reduction while the interface is running.

Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/s390/net/qeth_ethtool.c')
-rw-r--r--drivers/s390/net/qeth_ethtool.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c
index 19b9c8302d36..715ee0015847 100644
--- a/drivers/s390/net/qeth_ethtool.c
+++ b/drivers/s390/net/qeth_ethtool.c
@@ -180,14 +180,27 @@ static int qeth_set_channels(struct net_device *dev,
 {
 	struct qeth_card *card = dev->ml_priv;
 
-	if (IS_IQD(card) || !IS_VM_NIC(card))
-		return -EOPNOTSUPP;
-
 	if (channels->rx_count == 0 || channels->tx_count == 0)
 		return -EINVAL;
 	if (channels->tx_count > card->qdio.no_out_queues)
 		return -EINVAL;
 
+	if (IS_IQD(card)) {
+		if (channels->tx_count < QETH_IQD_MIN_TXQ)
+			return -EINVAL;
+
+		/* Reject downgrade while running. It could push displaced
+		 * ucast flows onto txq0, which is reserved for mcast.
+		 */
+		if (netif_running(dev) &&
+		    channels->tx_count < dev->real_num_tx_queues)
+			return -EPERM;
+	} else {
+		/* OSA still uses the legacy prio-queue mechanism: */
+		if (!IS_VM_NIC(card))
+			return -EOPNOTSUPP;
+	}
+
 	return netif_set_real_num_tx_queues(dev, channels->tx_count);
 }