]> git.baikalelectronics.ru Git - kernel.git/commitdiff
s390/qeth: keep track of wanted TX queues
authorJulian Wiedmann <jwi@linux.ibm.com>
Thu, 1 Oct 2020 17:11:30 +0000 (19:11 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 2 Oct 2020 23:22:49 +0000 (16:22 -0700)
When re-initializing a device, we can hit a situation where
qeth_osa_set_output_queues() detects that it supports more or less
HW TX queues than before. Right now we adjust dev->real_num_tx_queues
from right there, but
1. it's getting more & more complicated to cover all cases, and
2. we can't re-enable the actually expected number of TX queues later
because we lost the needed information.

So keep track of the wanted TX queues (on initial setup, and whenever
its changed via .set_channels), and later use that information when
re-enabling the netdevice.

Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_ethtool.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c

index f321eabefbe467833ca082b012d37fe783e16c6a..f1c9a694873e4c70a0d9a1e4662979cc95198a50 100644 (file)
@@ -538,7 +538,7 @@ struct qeth_qdio_info {
        int in_buf_size;
 
        /* output */
-       int no_out_queues;
+       unsigned int no_out_queues;
        struct qeth_qdio_out_q *out_qs[QETH_MAX_OUT_QUEUES];
        struct qdio_outbuf_state *out_bufstates;
 
@@ -788,6 +788,7 @@ struct qeth_switch_info {
 
 struct qeth_priv {
        unsigned int rx_copybreak;
+       unsigned int tx_wanted_queues;
        u32 brport_hw_features;
        u32 brport_features;
 };
@@ -873,6 +874,13 @@ struct qeth_trap_id {
 /*some helper functions*/
 #define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "")
 
+static inline unsigned int qeth_tx_actual_queues(struct qeth_card *card)
+{
+       struct qeth_priv *priv = netdev_priv(card->dev);
+
+       return min(priv->tx_wanted_queues, card->qdio.no_out_queues);
+}
+
 static inline u16 qeth_iqd_translate_txq(struct net_device *dev, u16 txq)
 {
        if (txq == QETH_IQD_MCAST_TXQ)
@@ -1087,7 +1095,6 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...);
 int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
 int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
 int qeth_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long);
-int qeth_setup_netdev(struct qeth_card *card);
 int qeth_set_features(struct net_device *, netdev_features_t);
 void qeth_enable_hw_features(struct net_device *dev);
 netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t);
index fc2c3db9259f51b9f1455bcbabfa0feb17fde630..b61078b27562b81692ad0d365eb21004031279e2 100644 (file)
@@ -1511,23 +1511,12 @@ static void qeth_drain_output_queues(struct qeth_card *card)
        }
 }
 
-static int qeth_osa_set_output_queues(struct qeth_card *card, bool single)
+static void qeth_osa_set_output_queues(struct qeth_card *card, bool single)
 {
        unsigned int max = single ? 1 : card->dev->num_tx_queues;
-       unsigned int count;
-       int rc;
-
-       count = IS_VM_NIC(card) ? min(max, card->dev->real_num_tx_queues) : max;
-
-       rtnl_lock();
-       rc = netif_set_real_num_tx_queues(card->dev, count);
-       rtnl_unlock();
-
-       if (rc)
-               return rc;
 
        if (card->qdio.no_out_queues == max)
-               return 0;
+               return;
 
        if (atomic_read(&card->qdio.state) != QETH_QDIO_UNINITIALIZED)
                qeth_free_qdio_queues(card);
@@ -1536,14 +1525,12 @@ static int qeth_osa_set_output_queues(struct qeth_card *card, bool single)
                dev_info(&card->gdev->dev, "Priority Queueing not supported\n");
 
        card->qdio.no_out_queues = max;
-       return 0;
 }
 
 static int qeth_update_from_chp_desc(struct qeth_card *card)
 {
        struct ccw_device *ccwdev;
        struct channel_path_desc_fmt0 *chp_dsc;
-       int rc = 0;
 
        QETH_CARD_TEXT(card, 2, "chp_desc");
 
@@ -1556,12 +1543,12 @@ static int qeth_update_from_chp_desc(struct qeth_card *card)
 
        if (IS_OSD(card) || IS_OSX(card))
                /* CHPP field bit 6 == 1 -> single queue */
-               rc = qeth_osa_set_output_queues(card, chp_dsc->chpp & 0x02);
+               qeth_osa_set_output_queues(card, chp_dsc->chpp & 0x02);
 
        kfree(chp_dsc);
        QETH_CARD_TEXT_(card, 2, "nr:%x", card->qdio.no_out_queues);
        QETH_CARD_TEXT_(card, 2, "lvl:%02x", card->info.func_level);
-       return rc;
+       return 0;
 }
 
 static void qeth_init_qdio_info(struct qeth_card *card)
@@ -5316,6 +5303,20 @@ static int qeth_set_online(struct qeth_card *card)
 
        qeth_print_status_message(card);
 
+       if (card->dev->reg_state != NETREG_REGISTERED) {
+               struct qeth_priv *priv = netdev_priv(card->dev);
+
+               if (IS_IQD(card))
+                       priv->tx_wanted_queues = QETH_IQD_MIN_TXQ;
+               else if (IS_VM_NIC(card))
+                       priv->tx_wanted_queues = 1;
+               else
+                       priv->tx_wanted_queues = card->dev->num_tx_queues;
+
+               /* no need for locking / error handling at this early stage: */
+               qeth_set_real_num_tx_queues(card, qeth_tx_actual_queues(card));
+       }
+
        rc = card->discipline->set_online(card, carrier_ok);
        if (rc)
                goto err_online;
@@ -6250,8 +6251,16 @@ static struct net_device *qeth_alloc_netdev(struct qeth_card *card)
        SET_NETDEV_DEV(dev, &card->gdev->dev);
        netif_carrier_off(dev);
 
-       dev->ethtool_ops = IS_OSN(card) ? &qeth_osn_ethtool_ops :
-                                         &qeth_ethtool_ops;
+       if (IS_OSN(card)) {
+               dev->ethtool_ops = &qeth_osn_ethtool_ops;
+       } else {
+               dev->ethtool_ops = &qeth_ethtool_ops;
+               dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+               dev->hw_features |= NETIF_F_SG;
+               dev->vlan_features |= NETIF_F_SG;
+               if (IS_IQD(card))
+                       dev->features |= NETIF_F_SG;
+       }
 
        return dev;
 }
@@ -6267,28 +6276,6 @@ struct net_device *qeth_clone_netdev(struct net_device *orig)
        return clone;
 }
 
-int qeth_setup_netdev(struct qeth_card *card)
-{
-       struct net_device *dev = card->dev;
-       unsigned int num_tx_queues;
-
-       dev->priv_flags &= ~IFF_TX_SKB_SHARING;
-       dev->hw_features |= NETIF_F_SG;
-       dev->vlan_features |= NETIF_F_SG;
-
-       if (IS_IQD(card)) {
-               dev->features |= NETIF_F_SG;
-               num_tx_queues = QETH_IQD_MIN_TXQ;
-       } else if (IS_VM_NIC(card)) {
-               num_tx_queues = 1;
-       } else {
-               num_tx_queues = dev->real_num_tx_queues;
-       }
-
-       return qeth_set_real_num_tx_queues(card, num_tx_queues);
-}
-EXPORT_SYMBOL_GPL(qeth_setup_netdev);
-
 static int qeth_core_probe_device(struct ccwgroup_device *gdev)
 {
        struct qeth_card *card;
@@ -6959,6 +6946,7 @@ int qeth_set_real_num_tx_queues(struct qeth_card *card, unsigned int count)
 
        return rc;
 }
+EXPORT_SYMBOL_GPL(qeth_set_real_num_tx_queues);
 
 u16 qeth_iqd_select_queue(struct net_device *dev, struct sk_buff *skb,
                          u8 cast_type, struct net_device *sb_dev)
index f870c5322bfe7431fc3cf063aaa293acb1894837..bc3ea0efb58b3f8bd144a48fb9b5f5f9f72ef627 100644 (file)
@@ -211,7 +211,9 @@ static void qeth_get_channels(struct net_device *dev,
 static int qeth_set_channels(struct net_device *dev,
                             struct ethtool_channels *channels)
 {
+       struct qeth_priv *priv = netdev_priv(dev);
        struct qeth_card *card = dev->ml_priv;
+       int rc;
 
        if (channels->rx_count == 0 || channels->tx_count == 0)
                return -EINVAL;
@@ -234,7 +236,11 @@ static int qeth_set_channels(struct net_device *dev,
                        return -EOPNOTSUPP;
        }
 
-       return qeth_set_real_num_tx_queues(card, channels->tx_count);
+       rc = qeth_set_real_num_tx_queues(card, channels->tx_count);
+       if (!rc)
+               priv->tx_wanted_queues = channels->tx_count;
+
+       return rc;
 }
 
 static int qeth_get_ts_info(struct net_device *dev,
index 1852d0a3c10a6ea946a1324655265b4b3bedc02a..290389fc7e793ee7edc8520cecc92a2260a5f1df 100644 (file)
@@ -894,18 +894,12 @@ static const struct net_device_ops qeth_osn_netdev_ops = {
 
 static int qeth_l2_setup_netdev(struct qeth_card *card)
 {
-       int rc;
-
        if (IS_OSN(card)) {
                card->dev->netdev_ops = &qeth_osn_netdev_ops;
                card->dev->flags |= IFF_NOARP;
                goto add_napi;
        }
 
-       rc = qeth_setup_netdev(card);
-       if (rc)
-               return rc;
-
        card->dev->needed_headroom = sizeof(struct qeth_hdr);
        card->dev->netdev_ops = &qeth_l2_netdev_ops;
        card->dev->priv_flags |= IFF_UNICAST_FLT;
@@ -2274,6 +2268,13 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok)
                        netif_carrier_on(dev);
        } else {
                rtnl_lock();
+               rc = qeth_set_real_num_tx_queues(card,
+                                                qeth_tx_actual_queues(card));
+               if (rc) {
+                       rtnl_unlock();
+                       goto err_set_queues;
+               }
+
                if (carrier_ok)
                        netif_carrier_on(dev);
                else
@@ -2291,6 +2292,7 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok)
        }
        return 0;
 
+err_set_queues:
 err_setup:
        qeth_set_allowed_threads(card, 0, 1);
        card->state = CARD_STATE_DOWN;
index a6f8878b55c6a9324cc8ef5cf01d23f9f94fe222..ea5f25857aff10795ad6c17c7528c54436df20ea 100644 (file)
@@ -1875,10 +1875,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
        unsigned int headroom;
        int rc;
 
-       rc = qeth_setup_netdev(card);
-       if (rc)
-               return rc;
-
        if (IS_OSD(card) || IS_OSX(card)) {
                card->dev->netdev_ops = &qeth_l3_osa_netdev_ops;
 
@@ -2022,6 +2018,13 @@ static int qeth_l3_set_online(struct qeth_card *card, bool carrier_ok)
                        netif_carrier_on(dev);
        } else {
                rtnl_lock();
+               rc = qeth_set_real_num_tx_queues(card,
+                                                qeth_tx_actual_queues(card));
+               if (rc) {
+                       rtnl_unlock();
+                       goto err_set_queues;
+               }
+
                if (carrier_ok)
                        netif_carrier_on(dev);
                else
@@ -2038,6 +2041,7 @@ static int qeth_l3_set_online(struct qeth_card *card, bool carrier_ok)
        }
        return 0;
 
+err_set_queues:
 err_setup:
        qeth_set_allowed_threads(card, 0, 1);
        card->state = CARD_STATE_DOWN;