602-v5.12-net-add-sysfs-attribute-to-control-napi-threaded-mod.patch 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. From: Wei Wang <[email protected]>
  2. Date: Mon, 8 Feb 2021 11:34:10 -0800
  3. Subject: [PATCH] net: add sysfs attribute to control napi threaded mode
  4. This patch adds a new sysfs attribute to the network device class.
  5. Said attribute provides a per-device control to enable/disable the
  6. threaded mode for all the napi instances of the given network device,
  7. without the need for a device up/down.
  8. User sets it to 1 or 0 to enable or disable threaded mode.
  9. Note: when switching between threaded and the current softirq based mode
  10. for a napi instance, it will not immediately take effect if the napi is
  11. currently being polled. The mode switch will happen for the next time
  12. napi_schedule() is called.
  13. Co-developed-by: Paolo Abeni <[email protected]>
  14. Signed-off-by: Paolo Abeni <[email protected]>
  15. Co-developed-by: Hannes Frederic Sowa <[email protected]>
  16. Signed-off-by: Hannes Frederic Sowa <[email protected]>
  17. Co-developed-by: Felix Fietkau <[email protected]>
  18. Signed-off-by: Felix Fietkau <[email protected]>
  19. Signed-off-by: Wei Wang <[email protected]>
  20. Reviewed-by: Alexander Duyck <[email protected]>
  21. Signed-off-by: David S. Miller <[email protected]>
  22. ---
  23. --- a/Documentation/ABI/testing/sysfs-class-net
  24. +++ b/Documentation/ABI/testing/sysfs-class-net
  25. @@ -337,3 +337,18 @@ Contact: [email protected]
  26. Description:
  27. 32-bit unsigned integer counting the number of times the link has
  28. been down
  29. +
  30. +What: /sys/class/net/<iface>/threaded
  31. +Date: Jan 2021
  32. +KernelVersion: 5.12
  33. +Contact: [email protected]
  34. +Description:
  35. + Boolean value to control the threaded mode per device. User could
  36. + set this value to enable/disable threaded mode for all napi
  37. + belonging to this device, without the need to do device up/down.
  38. +
  39. + Possible values:
  40. + == ==================================
  41. + 0 threaded mode disabled for this dev
  42. + 1 threaded mode enabled for this dev
  43. + == ==================================
  44. --- a/include/linux/netdevice.h
  45. +++ b/include/linux/netdevice.h
  46. @@ -491,6 +491,8 @@ static inline bool napi_complete(struct
  47. return napi_complete_done(n, 0);
  48. }
  49. +int dev_set_threaded(struct net_device *dev, bool threaded);
  50. +
  51. /**
  52. * napi_disable - prevent NAPI from scheduling
  53. * @n: NAPI context
  54. --- a/net/core/dev.c
  55. +++ b/net/core/dev.c
  56. @@ -4280,8 +4280,9 @@ static inline void ____napi_schedule(str
  57. if (test_bit(NAPI_STATE_THREADED, &napi->state)) {
  58. /* Paired with smp_mb__before_atomic() in
  59. - * napi_enable(). Use READ_ONCE() to guarantee
  60. - * a complete read on napi->thread. Only call
  61. + * napi_enable()/dev_set_threaded().
  62. + * Use READ_ONCE() to guarantee a complete
  63. + * read on napi->thread. Only call
  64. * wake_up_process() when it's not NULL.
  65. */
  66. thread = READ_ONCE(napi->thread);
  67. @@ -6716,6 +6717,49 @@ static void init_gro_hash(struct napi_st
  68. napi->gro_bitmask = 0;
  69. }
  70. +int dev_set_threaded(struct net_device *dev, bool threaded)
  71. +{
  72. + struct napi_struct *napi;
  73. + int err = 0;
  74. +
  75. + if (dev->threaded == threaded)
  76. + return 0;
  77. +
  78. + if (threaded) {
  79. + list_for_each_entry(napi, &dev->napi_list, dev_list) {
  80. + if (!napi->thread) {
  81. + err = napi_kthread_create(napi);
  82. + if (err) {
  83. + threaded = false;
  84. + break;
  85. + }
  86. + }
  87. + }
  88. + }
  89. +
  90. + dev->threaded = threaded;
  91. +
  92. + /* Make sure kthread is created before THREADED bit
  93. + * is set.
  94. + */
  95. + smp_mb__before_atomic();
  96. +
  97. + /* Setting/unsetting threaded mode on a napi might not immediately
  98. + * take effect, if the current napi instance is actively being
  99. + * polled. In this case, the switch between threaded mode and
  100. + * softirq mode will happen in the next round of napi_schedule().
  101. + * This should not cause hiccups/stalls to the live traffic.
  102. + */
  103. + list_for_each_entry(napi, &dev->napi_list, dev_list) {
  104. + if (threaded)
  105. + set_bit(NAPI_STATE_THREADED, &napi->state);
  106. + else
  107. + clear_bit(NAPI_STATE_THREADED, &napi->state);
  108. + }
  109. +
  110. + return err;
  111. +}
  112. +
  113. void netif_napi_add(struct net_device *dev, struct napi_struct *napi,
  114. int (*poll)(struct napi_struct *, int), int weight)
  115. {
  116. --- a/net/core/net-sysfs.c
  117. +++ b/net/core/net-sysfs.c
  118. @@ -538,6 +538,45 @@ static ssize_t phys_switch_id_show(struc
  119. }
  120. static DEVICE_ATTR_RO(phys_switch_id);
  121. +static ssize_t threaded_show(struct device *dev,
  122. + struct device_attribute *attr, char *buf)
  123. +{
  124. + struct net_device *netdev = to_net_dev(dev);
  125. + ssize_t ret = -EINVAL;
  126. +
  127. + if (!rtnl_trylock())
  128. + return restart_syscall();
  129. +
  130. + if (dev_isalive(netdev))
  131. + ret = sprintf(buf, fmt_dec, netdev->threaded);
  132. +
  133. + rtnl_unlock();
  134. + return ret;
  135. +}
  136. +
  137. +static int modify_napi_threaded(struct net_device *dev, unsigned long val)
  138. +{
  139. + int ret;
  140. +
  141. + if (list_empty(&dev->napi_list))
  142. + return -EOPNOTSUPP;
  143. +
  144. + if (val != 0 && val != 1)
  145. + return -EOPNOTSUPP;
  146. +
  147. + ret = dev_set_threaded(dev, val);
  148. +
  149. + return ret;
  150. +}
  151. +
  152. +static ssize_t threaded_store(struct device *dev,
  153. + struct device_attribute *attr,
  154. + const char *buf, size_t len)
  155. +{
  156. + return netdev_store(dev, attr, buf, len, modify_napi_threaded);
  157. +}
  158. +static DEVICE_ATTR_RW(threaded);
  159. +
  160. static struct attribute *net_class_attrs[] __ro_after_init = {
  161. &dev_attr_netdev_group.attr,
  162. &dev_attr_type.attr,
  163. @@ -570,6 +609,7 @@ static struct attribute *net_class_attrs
  164. &dev_attr_proto_down.attr,
  165. &dev_attr_carrier_up_count.attr,
  166. &dev_attr_carrier_down_count.attr,
  167. + &dev_attr_threaded.attr,
  168. NULL,
  169. };
  170. ATTRIBUTE_GROUPS(net_class);