net-sysfs: warn if new queue objects are being created during device unregistration
[platform/kernel/linux-starfive.git] / net / core / net-sysfs.c
index b2e49eb..53ea262 100644 (file)
@@ -175,6 +175,14 @@ static int change_carrier(struct net_device *dev, unsigned long new_carrier)
 static ssize_t carrier_store(struct device *dev, struct device_attribute *attr,
                             const char *buf, size_t len)
 {
+       struct net_device *netdev = to_net_dev(dev);
+
+       /* The check is also done in change_carrier; this helps returning early
+        * without hitting the trylock/restart in netdev_store.
+        */
+       if (!netdev->netdev_ops->ndo_change_carrier)
+               return -EOPNOTSUPP;
+
        return netdev_store(dev, attr, buf, len, change_carrier);
 }
 
@@ -196,6 +204,12 @@ static ssize_t speed_show(struct device *dev,
        struct net_device *netdev = to_net_dev(dev);
        int ret = -EINVAL;
 
+       /* The check is also done in __ethtool_get_link_ksettings; this helps
+        * returning early without hitting the trylock/restart below.
+        */
+       if (!netdev->ethtool_ops->get_link_ksettings)
+               return ret;
+
        if (!rtnl_trylock())
                return restart_syscall();
 
@@ -216,6 +230,12 @@ static ssize_t duplex_show(struct device *dev,
        struct net_device *netdev = to_net_dev(dev);
        int ret = -EINVAL;
 
+       /* The check is also done in __ethtool_get_link_ksettings; this helps
+        * returning early without hitting the trylock/restart below.
+        */
+       if (!netdev->ethtool_ops->get_link_ksettings)
+               return ret;
+
        if (!rtnl_trylock())
                return restart_syscall();
 
@@ -478,6 +498,12 @@ static ssize_t phys_port_id_show(struct device *dev,
        struct net_device *netdev = to_net_dev(dev);
        ssize_t ret = -EINVAL;
 
+       /* The check is also done in dev_get_phys_port_id; this helps returning
+        * early without hitting the trylock/restart below.
+        */
+       if (!netdev->netdev_ops->ndo_get_phys_port_id)
+               return -EOPNOTSUPP;
+
        if (!rtnl_trylock())
                return restart_syscall();
 
@@ -500,6 +526,13 @@ static ssize_t phys_port_name_show(struct device *dev,
        struct net_device *netdev = to_net_dev(dev);
        ssize_t ret = -EINVAL;
 
+       /* The checks are also done in dev_get_phys_port_name; this helps
+        * returning early without hitting the trylock/restart below.
+        */
+       if (!netdev->netdev_ops->ndo_get_phys_port_name &&
+           !netdev->netdev_ops->ndo_get_devlink_port)
+               return -EOPNOTSUPP;
+
        if (!rtnl_trylock())
                return restart_syscall();
 
@@ -522,6 +555,14 @@ static ssize_t phys_switch_id_show(struct device *dev,
        struct net_device *netdev = to_net_dev(dev);
        ssize_t ret = -EINVAL;
 
+       /* The checks are also done in dev_get_phys_port_name; this helps
+        * returning early without hitting the trylock/restart below. This works
+        * because recurse is false when calling dev_get_port_parent_id.
+        */
+       if (!netdev->netdev_ops->ndo_get_port_parent_id &&
+           !netdev->netdev_ops->ndo_get_devlink_port)
+               return -EOPNOTSUPP;
+
        if (!rtnl_trylock())
                return restart_syscall();
 
@@ -963,7 +1004,7 @@ static void rx_queue_release(struct kobject *kobj)
 #endif
 
        memset(kobj, 0, sizeof(*kobj));
-       dev_put(queue->dev);
+       dev_put_track(queue->dev, &queue->dev_tracker);
 }
 
 static const void *rx_queue_namespace(struct kobject *kobj)
@@ -1003,7 +1044,7 @@ static int rx_queue_add_kobject(struct net_device *dev, int index)
        /* Kobject_put later will trigger rx_queue_release call which
         * decreases dev refcount: Take that reference here
         */
-       dev_hold(queue->dev);
+       dev_hold_track(queue->dev, &queue->dev_tracker, GFP_KERNEL);
 
        kobj->kset = dev->queues_kset;
        error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL,
@@ -1152,11 +1193,7 @@ static const struct sysfs_ops netdev_queue_sysfs_ops = {
 
 static ssize_t tx_timeout_show(struct netdev_queue *queue, char *buf)
 {
-       unsigned long trans_timeout;
-
-       spin_lock_irq(&queue->_xmit_lock);
-       trans_timeout = queue->trans_timeout;
-       spin_unlock_irq(&queue->_xmit_lock);
+       unsigned long trans_timeout = atomic_long_read(&queue->trans_timeout);
 
        return sprintf(buf, fmt_ulong, trans_timeout);
 }
@@ -1226,6 +1263,12 @@ static ssize_t tx_maxrate_store(struct netdev_queue *queue,
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
 
+       /* The check is also done later; this helps returning early without
+        * hitting the trylock/restart below.
+        */
+       if (!dev->netdev_ops->ndo_set_tx_maxrate)
+               return -EOPNOTSUPP;
+
        err = kstrtou32(buf, 10, &rate);
        if (err < 0)
                return err;
@@ -1397,7 +1440,7 @@ static ssize_t xps_queue_show(struct net_device *dev, unsigned int index,
 
                for (i = map->len; i--;) {
                        if (map->queues[i] == index) {
-                               set_bit(j, mask);
+                               __set_bit(j, mask);
                                break;
                        }
                }
@@ -1564,7 +1607,7 @@ static void netdev_queue_release(struct kobject *kobj)
        struct netdev_queue *queue = to_netdev_queue(kobj);
 
        memset(kobj, 0, sizeof(*kobj));
-       dev_put(queue->dev);
+       dev_put_track(queue->dev, &queue->dev_tracker);
 }
 
 static const void *netdev_queue_namespace(struct kobject *kobj)
@@ -1604,7 +1647,7 @@ static int netdev_queue_add_kobject(struct net_device *dev, int index)
        /* Kobject_put later will trigger netdev_queue_release call
         * which decreases dev refcount: Take that reference here
         */
-       dev_hold(queue->dev);
+       dev_hold_track(queue->dev, &queue->dev_tracker, GFP_KERNEL);
 
        kobj->kset = dev->queues_kset;
        error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL,
@@ -1651,6 +1694,13 @@ netdev_queue_update_kobjects(struct net_device *dev, int old_num, int new_num)
        int i;
        int error = 0;
 
+       /* Tx queue kobjects are allowed to be updated when a device is being
+        * unregistered, but solely to remove queues from qdiscs. Any path
+        * adding queues should be fixed.
+        */
+       WARN(dev->reg_state == NETREG_UNREGISTERING && new_num > old_num,
+            "New queues can't be registered after device unregistration.");
+
        for (i = old_num; i < new_num; i++) {
                error = netdev_queue_add_kobject(dev, i);
                if (error) {
@@ -1765,6 +1815,9 @@ static void remove_queue_kobjects(struct net_device *dev)
 
        net_rx_queue_update_kobjects(dev, real_rx, 0);
        netdev_queue_update_kobjects(dev, real_tx, 0);
+
+       dev->real_num_rx_queues = 0;
+       dev->real_num_tx_queues = 0;
 #ifdef CONFIG_SYSFS
        kset_unregister(dev->queues_kset);
 #endif
@@ -1869,7 +1922,7 @@ static struct class net_class __ro_after_init = {
        .get_ownership = net_get_ownership,
 };
 
-#ifdef CONFIG_OF_NET
+#ifdef CONFIG_OF
 static int of_dev_node_match(struct device *dev, const void *data)
 {
        for (; dev; dev = dev->parent) {