blob: 591f7e756f03a3b82e1eefe86f1691989577f588 [file] [log] [blame]
developerb31fa0a2023-09-19 06:32:06 +08001From f73e9179da805301affa628de794046ef8ef2ff0 Mon Sep 17 00:00:00 2001
2From: Evelyn Tsai <evelyn.tsai@mediatek.com>
3Date: Sun, 17 Sep 2023 12:28:35 +0800
4Subject: [PATCH 1/4] netifd: revert: commit can't work for Kernel5.4
5
6Revert "make_ethtool_modes_h.sh: apply anti-bashism"
7This reverts commit 1a07f1dff32b3af49e39533e33e8964b59535662.
8Revert "system-linux: switch to new ETHTOOL_xLINKSETTINGS API"
9This reverts commit f429bd94f99e55548bf4fa8156c165017ce3c41c.
10---
11 CMakeLists.txt | 8 -
12 device.c | 35 ----
13 device.h | 15 --
14 make_ethtool_modes_h.sh | 66 -------
15 system-linux.c | 404 +++++++++-------------------------------
16 5 files changed, 87 insertions(+), 441 deletions(-)
17 delete mode 100755 make_ethtool_modes_h.sh
18
19diff --git a/CMakeLists.txt b/CMakeLists.txt
20index 8064485..5ad8695 100644
21--- a/CMakeLists.txt
22+++ b/CMakeLists.txt
23@@ -49,13 +49,6 @@ IF (NOT DEFINED LIBNL_LIBS)
24 ENDIF()
25 ENDIF()
26
27-ADD_CUSTOM_COMMAND(
28- OUTPUT ethtool-modes.h
29- COMMAND ./make_ethtool_modes_h.sh ${CMAKE_C_COMPILER} > ./ethtool-modes.h
30- DEPENDS ./make_ethtool_modes_h.sh
31-)
32-ADD_CUSTOM_TARGET(ethtool-modes-h DEPENDS ethtool-modes.h)
33-
34 IF("${CMAKE_SYSTEM_NAME}" MATCHES "Linux" AND NOT DUMMY_MODE)
35 SET(SOURCES ${SOURCES} system-linux.c)
36 SET(LIBS ${LIBS} ${LIBNL_LIBS})
37@@ -79,4 +72,3 @@ TARGET_LINK_LIBRARIES(netifd ${LIBS})
38 INSTALL(TARGETS netifd
39 RUNTIME DESTINATION sbin
40 )
41-ADD_DEPENDENCIES(netifd ethtool-modes-h)
42diff --git a/device.c b/device.c
43index 2417556..92c814c 100644
44--- a/device.c
45+++ b/device.c
46@@ -64,11 +64,6 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = {
47 [DEV_ATTR_SPEED] = { .name = "speed", .type = BLOBMSG_TYPE_INT32 },
48 [DEV_ATTR_DUPLEX] = { .name = "duplex", .type = BLOBMSG_TYPE_BOOL },
49 [DEV_ATTR_VLAN] = { .name = "vlan", .type = BLOBMSG_TYPE_ARRAY },
50- [DEV_ATTR_PAUSE] = { .name = "pause", .type = BLOBMSG_TYPE_BOOL },
51- [DEV_ATTR_ASYM_PAUSE] = { .name = "asym_pause", .type = BLOBMSG_TYPE_BOOL },
52- [DEV_ATTR_RXPAUSE] = { .name = "rxpause", .type = BLOBMSG_TYPE_BOOL },
53- [DEV_ATTR_TXPAUSE] = { .name = "txpause", .type = BLOBMSG_TYPE_BOOL },
54- [DEV_ATTR_AUTONEG] = { .name = "autoneg", .type = BLOBMSG_TYPE_BOOL },
55 };
56
57 const struct uci_blob_param_list device_attr_list = {
58@@ -286,11 +281,6 @@ device_merge_settings(struct device *dev, struct device_settings *n)
59 n->auth = s->flags & DEV_OPT_AUTH ? s->auth : os->auth;
60 n->speed = s->flags & DEV_OPT_SPEED ? s->speed : os->speed;
61 n->duplex = s->flags & DEV_OPT_DUPLEX ? s->duplex : os->duplex;
62- n->pause = s->flags & DEV_OPT_PAUSE ? s->pause : os->pause;
63- n->asym_pause = s->flags & DEV_OPT_ASYM_PAUSE ? s->asym_pause : os->asym_pause;
64- n->rxpause = s->flags & DEV_OPT_RXPAUSE ? s->rxpause : os->rxpause;
65- n->txpause = s->flags & DEV_OPT_TXPAUSE ? s->txpause : os->txpause;
66- n->autoneg = s->flags & DEV_OPT_AUTONEG ? s->autoneg : os->autoneg;
67 n->flags = s->flags | os->flags | os->valid_flags;
68 }
69
70@@ -515,31 +505,6 @@ device_init_settings(struct device *dev, struct blob_attr **tb)
71 s->duplex = blobmsg_get_bool(cur);
72 s->flags |= DEV_OPT_DUPLEX;
73 }
74-
75- if ((cur = tb[DEV_ATTR_PAUSE])) {
76- s->pause = blobmsg_get_bool(cur);
77- s->flags |= DEV_OPT_PAUSE;
78- }
79-
80- if ((cur = tb[DEV_ATTR_ASYM_PAUSE])) {
81- s->asym_pause = blobmsg_get_bool(cur);
82- s->flags |= DEV_OPT_ASYM_PAUSE;
83- }
84-
85- if ((cur = tb[DEV_ATTR_RXPAUSE])) {
86- s->rxpause = blobmsg_get_bool(cur);
87- s->flags |= DEV_OPT_RXPAUSE;
88- }
89-
90- if ((cur = tb[DEV_ATTR_TXPAUSE])) {
91- s->txpause = blobmsg_get_bool(cur);
92- s->flags |= DEV_OPT_TXPAUSE;
93- }
94-
95- if ((cur = tb[DEV_ATTR_AUTONEG])) {
96- s->autoneg = blobmsg_get_bool(cur);
97- s->flags |= DEV_OPT_AUTONEG;
98- }
99 device_set_extra_vlans(dev, tb[DEV_ATTR_VLAN]);
100 device_set_disabled(dev, disabled);
101 }
102diff --git a/device.h b/device.h
103index 14d7486..aa4da18 100644
104--- a/device.h
105+++ b/device.h
106@@ -63,11 +63,6 @@ enum {
107 DEV_ATTR_SPEED,
108 DEV_ATTR_DUPLEX,
109 DEV_ATTR_VLAN,
110- DEV_ATTR_PAUSE,
111- DEV_ATTR_ASYM_PAUSE,
112- DEV_ATTR_RXPAUSE,
113- DEV_ATTR_TXPAUSE,
114- DEV_ATTR_AUTONEG,
115 __DEV_ATTR_MAX,
116 };
117
118@@ -132,11 +127,6 @@ enum {
119 DEV_OPT_ARP_ACCEPT = (1ULL << 29),
120 DEV_OPT_SPEED = (1ULL << 30),
121 DEV_OPT_DUPLEX = (1ULL << 31),
122- DEV_OPT_PAUSE = (1ULL << 32),
123- DEV_OPT_ASYM_PAUSE = (1ULL << 33),
124- DEV_OPT_RXPAUSE = (1ULL << 34),
125- DEV_OPT_TXPAUSE = (1ULL << 35),
126- DEV_OPT_AUTONEG = (1ULL << 36),
127 };
128
129 /* events broadcasted to all users of a device */
130@@ -214,11 +204,6 @@ struct device_settings {
131 bool auth;
132 unsigned int speed;
133 bool duplex;
134- bool pause;
135- bool asym_pause;
136- bool rxpause;
137- bool txpause;
138- bool autoneg;
139 };
140
141 struct device_vlan_range {
142diff --git a/make_ethtool_modes_h.sh b/make_ethtool_modes_h.sh
143deleted file mode 100755
144index 7f5ac7b..0000000
145--- a/make_ethtool_modes_h.sh
146+++ /dev/null
147@@ -1,66 +0,0 @@
148-#!/bin/sh
149-
150-CC="$1"
151-[ -n "$TARGET_CC_NOCACHE" ] && CC="$TARGET_CC_NOCACHE"
152-
153-cat <<EOF
154-#include <linux/ethtool.h>
155-
156-#define ETHTOOL_MODE_FULL(_speed, _mode) { \\
157- .speed = (_speed), \\
158- .bit_half = -1, \\
159- .bit_full = ETHTOOL_LINK_MODE_ ## _speed ## base ## _mode ## _Full_BIT, \\
160- .name = #_speed "base" #_mode, \\
161-}
162-
163-#define ETHTOOL_MODE_HALF(_speed, _mode) { \\
164- .speed = (_speed), \\
165- .bit_half = ETHTOOL_LINK_MODE_ ## _speed ## base ## _mode ## _Half_BIT, \\
166- .bit_full = -1, \\
167- .name = #_speed "base" #_mode, \\
168-}
169-
170-#define ETHTOOL_MODE_BOTH(_speed, _mode) { \\
171- .speed = (_speed), \\
172- .bit_half = ETHTOOL_LINK_MODE_ ## _speed ## base ## _mode ## _Half_BIT, \\
173- .bit_full = ETHTOOL_LINK_MODE_ ## _speed ## base ## _mode ## _Full_BIT, \\
174- .name = #_speed "base" #_mode, \\
175-}
176-
177-static const struct {
178- unsigned int speed;
179- int bit_half;
180- int bit_full;
181- const char *name;
182-} ethtool_modes[] = {
183-EOF
184-
185-echo "#include <linux/ethtool.h>" | "$CC" -E - | \
186- grep "ETHTOOL_LINK_MODE_[0-9]*base[A-Za-z0-9]*_...._BIT.*" | \
187- sed -r 's/.*ETHTOOL_LINK_MODE_([0-9]*)base([A-Za-z0-9]*)_(....)_BIT.*/\1 \2 \3/' | \
188- sort -u | LC_ALL=C sort -r -g | ( gothalf=0 ; while read -r speed mode duplex; do
189- if [ "$duplex" = "Half" ]; then
190- if [ "$gothalf" = "1" ]; then
191- printf "%s" "$speed \tETHTOOL_MODE_HALF($p_speed, $p_mode),\n"
192- fi
193- gothalf=1
194- elif [ "$duplex" = "Full" ]; then
195- if [ "$gothalf" = "1" ]; then
196- if [ "$p_speed" = "$speed" ] && [ "$p_mode" = "$mode" ]; then
197- printf "%d \t%s\n" "$speed" "ETHTOOL_MODE_BOTH($speed, $mode),"
198- else
199- printf "%d \t%s\n" "$p_speed" "ETHTOOL_MODE_HALF($p_speed, $p_mode),"
200- printf "%d \t%s\n" "$speed" "ETHTOOL_MODE_FULL($speed, $mode),"
201- fi
202- gothalf=0
203- else
204- printf "%d \t%s\n" "$speed" "ETHTOOL_MODE_FULL($speed, $mode),"
205- fi
206- else
207- continue
208- fi
209- p_speed="$speed"
210- p_mode="$mode"
211- done ; [ "$gothalf" = "1" ] && printf "%d \t%s\n" "$p_speed" "ETHTOOL_MODE_HALF($p_speed, $p_mode)," ) | \
212- LC_ALL=C sort -g | sed -r 's/[0-9]* (.*)/\1/'
213-echo "};"
214diff --git a/system-linux.c b/system-linux.c
215index e437377..0760e73 100644
216--- a/system-linux.c
217+++ b/system-linux.c
218@@ -48,8 +48,6 @@
219
220 #include <sched.h>
221
222-#include "ethtool-modes.h"
223-
224 #ifndef RTN_FAILED_POLICY
225 #define RTN_FAILED_POLICY 12
226 #endif
227@@ -1704,149 +1702,54 @@ int system_vlandev_del(struct device *vlandev)
228 return system_link_del(vlandev->ifname);
229 }
230
231-static void ethtool_link_mode_clear_bit(__s8 nwords, int nr, __u32 *mask)
232-{
233- if (nr < 0)
234- return;
235-
236- if (nr >= (nwords * 32))
237- return;
238-
239- mask[nr / 32] &= ~(1U << (nr % 32));
240-}
241-
242-static bool ethtool_link_mode_test_bit(__s8 nwords, int nr, const __u32 *mask)
243-{
244- if (nr < 0)
245- return false;
246-
247- if (nr >= (nwords * 32))
248- return false;
249-
250- return !!(mask[nr / 32] & (1U << (nr % 32)));
251-}
252-
253-static void
254-system_set_ethtool_pause(struct device *dev, struct device_settings *s)
255-{
256- struct ethtool_pauseparam pp;
257- struct ifreq ifr = {
258- .ifr_data = (caddr_t)&pp,
259- };
260-
261- strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
262- memset(&pp, 0, sizeof(pp));
263- pp.cmd = ETHTOOL_GPAUSEPARAM;
264- if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr))
265- return;
266-
267- if (s->flags & DEV_OPT_RXPAUSE || s->flags & DEV_OPT_TXPAUSE) {
268- pp.autoneg = AUTONEG_DISABLE;
269-
270- if (s->flags & DEV_OPT_PAUSE) {
271- if (s->flags & DEV_OPT_RXPAUSE)
272- pp.rx_pause = s->rxpause && s->pause;
273- else
274- pp.rx_pause = s->pause;
275-
276- if (s->flags & DEV_OPT_TXPAUSE)
277- pp.tx_pause = s->txpause && s->pause;
278- else
279- pp.tx_pause = s->pause;
280- } else {
281- if (s->flags & DEV_OPT_RXPAUSE)
282- pp.rx_pause = s->rxpause;
283-
284- if (s->flags & DEV_OPT_TXPAUSE)
285- pp.tx_pause = s->txpause;
286- }
287-
288- if (s->flags & DEV_OPT_ASYM_PAUSE &&
289- !s->asym_pause && (pp.rx_pause != pp.tx_pause))
290- pp.rx_pause = pp.tx_pause = false;
291- } else {
292- pp.autoneg = AUTONEG_ENABLE;
293- /* Pause and Asym_Pause advertising bits will be set via
294- * ETHTOOL_SLINKSETTINGS in system_set_ethtool_settings()
295- */
296- }
297-
298- pp.cmd = ETHTOOL_SPAUSEPARAM;
299- ioctl(sock_ioctl, SIOCETHTOOL, &ifr);
300-}
301-
302 static void
303 system_set_ethtool_settings(struct device *dev, struct device_settings *s)
304 {
305- struct {
306- struct ethtool_link_settings req;
307- __u32 link_mode_data[3 * 127];
308- } ecmd;
309+ struct ethtool_cmd ecmd = {
310+ .cmd = ETHTOOL_GSET,
311+ };
312 struct ifreq ifr = {
313 .ifr_data = (caddr_t)&ecmd,
314 };
315+ static const struct {
316+ unsigned int speed;
317+ uint8_t bit_half;
318+ uint8_t bit_full;
319+ } speed_mask[] = {
320+ { 10, ETHTOOL_LINK_MODE_10baseT_Half_BIT, ETHTOOL_LINK_MODE_10baseT_Full_BIT },
321+ { 100, ETHTOOL_LINK_MODE_100baseT_Half_BIT, ETHTOOL_LINK_MODE_100baseT_Full_BIT },
322+ { 1000, ETHTOOL_LINK_MODE_1000baseT_Half_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT },
323+ };
324+ uint32_t adv;
325 size_t i;
326- __s8 nwords;
327- __u32 *supported, *advertising;
328
329- system_set_ethtool_pause(dev, s);
330-
331- memset(&ecmd, 0, sizeof(ecmd));
332- ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
333 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
334
335- if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) < 0 ||
336- ecmd.req.link_mode_masks_nwords >= 0 ||
337- ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
338- return;
339-
340- ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
341-
342- if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) < 0 ||
343- ecmd.req.link_mode_masks_nwords <= 0 ||
344- ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
345+ if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) != 0)
346 return;
347
348- nwords = ecmd.req.link_mode_masks_nwords;
349- supported = &ecmd.link_mode_data[0];
350- advertising = &ecmd.link_mode_data[nwords];
351- memcpy(advertising, supported, sizeof(__u32) * nwords);
352-
353- for (i = 0; i < ARRAY_SIZE(ethtool_modes); i++) {
354+ adv = ecmd.supported;
355+ for (i = 0; i < ARRAY_SIZE(speed_mask); i++) {
356 if (s->flags & DEV_OPT_DUPLEX) {
357- if (s->duplex)
358- ethtool_link_mode_clear_bit(nwords, ethtool_modes[i].bit_half, advertising);
359- else
360- ethtool_link_mode_clear_bit(nwords, ethtool_modes[i].bit_full, advertising);
361+ int bit = s->duplex ? speed_mask[i].bit_half : speed_mask[i].bit_full;
362+ adv &= ~(1 << bit);
363 }
364+
365 if (!(s->flags & DEV_OPT_SPEED) ||
366- s->speed == ethtool_modes[i].speed)
367+ s->speed == speed_mask[i].speed)
368 continue;
369
370- ethtool_link_mode_clear_bit(nwords, ethtool_modes[i].bit_full, advertising);
371- ethtool_link_mode_clear_bit(nwords, ethtool_modes[i].bit_half, advertising);
372+ adv &= ~(1 << speed_mask[i].bit_full);
373+ adv &= ~(1 << speed_mask[i].bit_half);
374 }
375
376- if (s->flags & DEV_OPT_PAUSE)
377- if (!s->pause)
378- ethtool_link_mode_clear_bit(nwords, ETHTOOL_LINK_MODE_Pause_BIT, advertising);
379
380- if (s->flags & DEV_OPT_ASYM_PAUSE)
381- if (!s->asym_pause)
382- ethtool_link_mode_clear_bit(nwords, ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising);
383-
384- if (s->flags & DEV_OPT_AUTONEG) {
385- ecmd.req.autoneg = s->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
386- if (!s->autoneg) {
387- if (s->flags & DEV_OPT_SPEED)
388- ecmd.req.speed = s->speed;
389-
390- if (s->flags & DEV_OPT_DUPLEX)
391- ecmd.req.duplex = s->duplex ? DUPLEX_FULL : DUPLEX_HALF;
392- }
393- }
394+ if (ecmd.autoneg && ecmd.advertising == adv)
395+ return;
396
397- ecmd.req.cmd = ETHTOOL_SLINKSETTINGS;
398+ ecmd.autoneg = 1;
399+ ecmd.advertising = adv;
400+ ecmd.cmd = ETHTOOL_SSET;
401 ioctl(sock_ioctl, SIOCETHTOOL, &ifr);
402 }
403
404@@ -2429,6 +2332,45 @@ read_uint64_file(int dir_fd, const char *file, uint64_t *val)
405 return ret;
406 }
407
408+/* Assume advertised flags == supported flags */
409+static const struct {
410+ uint32_t mask;
411+ const char *name;
412+} ethtool_link_modes[] = {
413+ { ADVERTISED_10baseT_Half, "10baseT-H" },
414+ { ADVERTISED_10baseT_Full, "10baseT-F" },
415+ { ADVERTISED_100baseT_Half, "100baseT-H" },
416+ { ADVERTISED_100baseT_Full, "100baseT-F" },
417+ { ADVERTISED_1000baseT_Half, "1000baseT-H" },
418+ { ADVERTISED_1000baseT_Full, "1000baseT-F" },
419+ { ADVERTISED_1000baseKX_Full, "1000baseKX-F" },
420+ { ADVERTISED_2500baseX_Full, "2500baseX-F" },
421+ { ADVERTISED_10000baseT_Full, "10000baseT-F" },
422+ { ADVERTISED_10000baseKX4_Full, "10000baseKX4-F" },
423+ { ADVERTISED_10000baseKR_Full, "10000baseKR-F" },
424+ { ADVERTISED_20000baseMLD2_Full, "20000baseMLD2-F" },
425+ { ADVERTISED_20000baseKR2_Full, "20000baseKR2-F" },
426+ { ADVERTISED_40000baseKR4_Full, "40000baseKR4-F" },
427+ { ADVERTISED_40000baseCR4_Full, "40000baseCR4-F" },
428+ { ADVERTISED_40000baseSR4_Full, "40000baseSR4-F" },
429+ { ADVERTISED_40000baseLR4_Full, "40000baseLR4-F" },
430+#ifdef ADVERTISED_56000baseKR4_Full
431+ { ADVERTISED_56000baseKR4_Full, "56000baseKR4-F" },
432+ { ADVERTISED_56000baseCR4_Full, "56000baseCR4-F" },
433+ { ADVERTISED_56000baseSR4_Full, "56000baseSR4-F" },
434+ { ADVERTISED_56000baseLR4_Full, "56000baseLR4-F" },
435+#endif
436+};
437+
438+static void system_add_link_modes(struct blob_buf *b, __u32 mask)
439+{
440+ size_t i;
441+ for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
442+ if (mask & ethtool_link_modes[i].mask)
443+ blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
444+ }
445+}
446+
447 bool
448 system_if_force_external(const char *ifname)
449 {
450@@ -2603,213 +2545,41 @@ ethtool_feature_value(const char *ifname, const char *keyname)
451 return active;
452 }
453
454-static void
455-system_add_link_mode_name(struct blob_buf *b, int i, bool half)
456-{
457- char *buf;
458-
459- /* allocate string buffer large enough for the mode name and a suffix
460- * "-F" or "-H" indicating full duplex or half duplex.
461- */
462- buf = blobmsg_alloc_string_buffer(b, NULL, strlen(ethtool_modes[i].name) + 3);
463- if (!buf)
464- return;
465-
466- strcpy(buf, ethtool_modes[i].name);
467- if (half)
468- strcat(buf, "-H");
469- else
470- strcat(buf, "-F");
471-
472- blobmsg_add_string_buffer(b);
473-}
474-
475-static void
476-system_add_link_modes(__s8 nwords, struct blob_buf *b, __u32 *mask)
477-{
478- size_t i;
479-
480- for (i = 0; i < ARRAY_SIZE(ethtool_modes); i++) {
481- if (ethtool_link_mode_test_bit(nwords, ethtool_modes[i].bit_half, mask))
482- system_add_link_mode_name(b, i, true);
483-
484- if (ethtool_link_mode_test_bit(nwords, ethtool_modes[i].bit_full, mask))
485- system_add_link_mode_name(b, i, false);
486- }
487-}
488-
489-static void
490-system_add_pause_modes(__s8 nwords, struct blob_buf *b, __u32 *mask)
491-{
492- if (ethtool_link_mode_test_bit(nwords, ETHTOOL_LINK_MODE_Pause_BIT, mask))
493- blobmsg_add_string(b, NULL, "pause");
494-
495- if (ethtool_link_mode_test_bit(nwords, ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask))
496- blobmsg_add_string(b, NULL, "asym_pause");
497-}
498-
499-
500-static void
501-system_add_ethtool_pause_an(struct blob_buf *b, __s8 nwords,
502- __u32 *advertising, __u32 *lp_advertising)
503-{
504- bool an_rx = false, an_tx = false;
505- void *d;
506-
507- d = blobmsg_open_array(b, "negotiated");
508-
509- /* Work out negotiated pause frame usage per
510- * IEEE 802.3-2005 table 28B-3.
511- */
512- if (ethtool_link_mode_test_bit(nwords,
513- ETHTOOL_LINK_MODE_Pause_BIT,
514- advertising) &&
515- ethtool_link_mode_test_bit(nwords,
516- ETHTOOL_LINK_MODE_Pause_BIT,
517- lp_advertising)) {
518- an_tx = true;
519- an_rx = true;
520- } else if (ethtool_link_mode_test_bit(nwords,
521- ETHTOOL_LINK_MODE_Asym_Pause_BIT,
522- advertising) &&
523- ethtool_link_mode_test_bit(nwords,
524- ETHTOOL_LINK_MODE_Asym_Pause_BIT,
525- lp_advertising)) {
526- if (ethtool_link_mode_test_bit(nwords,
527- ETHTOOL_LINK_MODE_Pause_BIT,
528- advertising))
529- an_rx = true;
530- else if (ethtool_link_mode_test_bit(nwords,
531- ETHTOOL_LINK_MODE_Pause_BIT,
532- lp_advertising))
533- an_tx = true;
534- }
535- if (an_tx)
536- blobmsg_add_string(b, NULL, "rx");
537-
538- if (an_rx)
539- blobmsg_add_string(b, NULL, "tx");
540-
541- blobmsg_close_array(b, d);
542-}
543-
544-static void
545-system_get_ethtool_pause(struct device *dev, bool *rx_pause, bool *tx_pause, bool *pause_autoneg)
546-{
547- struct ethtool_pauseparam pp;
548- struct ifreq ifr = {
549- .ifr_data = (caddr_t)&pp,
550- };
551-
552- strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
553- memset(&pp, 0, sizeof(pp));
554- pp.cmd = ETHTOOL_GPAUSEPARAM;
555-
556- /* may fail */
557- if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == -1) {
558- *pause_autoneg = true;
559- return;
560- }
561-
562- *rx_pause = pp.rx_pause;
563- *tx_pause = pp.tx_pause;
564- *pause_autoneg = pp.autoneg;
565-}
566-
567 int
568 system_if_dump_info(struct device *dev, struct blob_buf *b)
569 {
570- __u32 *supported, *advertising, *lp_advertising;
571- bool rx_pause, tx_pause, pause_autoneg;
572- struct {
573- struct ethtool_link_settings req;
574- __u32 link_mode_data[3 * 127];
575- } ecmd;
576- struct ifreq ifr = {
577- .ifr_data = (caddr_t)&ecmd,
578- };
579- __s8 nwords;
580- void *c, *d;
581+ struct ethtool_cmd ecmd;
582+ struct ifreq ifr;
583 char *s;
584-
585- system_get_ethtool_pause(dev, &rx_pause, &tx_pause, &pause_autoneg);
586+ void *c;
587
588 memset(&ecmd, 0, sizeof(ecmd));
589- ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
590+ memset(&ifr, 0, sizeof(ifr));
591 strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
592+ ifr.ifr_data = (caddr_t) &ecmd;
593+ ecmd.cmd = ETHTOOL_GSET;
594
595- if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) < 0 ||
596- ecmd.req.link_mode_masks_nwords >= 0 ||
597- ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
598- return -EOPNOTSUPP;
599-
600- ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords;
601-
602- if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) < 0 ||
603- ecmd.req.link_mode_masks_nwords <= 0 ||
604- ecmd.req.cmd != ETHTOOL_GLINKSETTINGS)
605- return -EIO;
606-
607- nwords = ecmd.req.link_mode_masks_nwords;
608- supported = &ecmd.link_mode_data[0];
609- advertising = &ecmd.link_mode_data[nwords];
610- lp_advertising = &ecmd.link_mode_data[2 * nwords];
611-
612- c = blobmsg_open_array(b, "link-advertising");
613- system_add_link_modes(nwords, b, advertising);
614- blobmsg_close_array(b, c);
615-
616- c = blobmsg_open_array(b, "link-partner-advertising");
617- system_add_link_modes(nwords, b, lp_advertising);
618- blobmsg_close_array(b, c);
619-
620- c = blobmsg_open_array(b, "link-supported");
621- system_add_link_modes(nwords, b, supported);
622- blobmsg_close_array(b, c);
623-
624- if (ethtool_validate_speed(ecmd.req.speed) &&
625- (ecmd.req.speed != (__u32)SPEED_UNKNOWN) &&
626- (ecmd.req.speed != 0)) {
627- s = blobmsg_alloc_string_buffer(b, "speed", 10);
628- snprintf(s, 8, "%d%c", ecmd.req.speed,
629- ecmd.req.duplex == DUPLEX_HALF ? 'H' : 'F');
630- blobmsg_add_string_buffer(b);
631- }
632- blobmsg_add_u8(b, "autoneg", !!ecmd.req.autoneg);
633+ if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
634+ c = blobmsg_open_array(b, "link-advertising");
635+ system_add_link_modes(b, ecmd.advertising);
636+ blobmsg_close_array(b, c);
637
638- c = blobmsg_open_table(b, "flow-control");
639- blobmsg_add_u8(b, "autoneg", pause_autoneg);
640+ c = blobmsg_open_array(b, "link-partner-advertising");
641+ system_add_link_modes(b, ecmd.lp_advertising);
642+ blobmsg_close_array(b, c);
643
644- d = blobmsg_open_array(b, "supported");
645- system_add_pause_modes(nwords, b, supported);
646- blobmsg_close_array(b, d);
647+ c = blobmsg_open_array(b, "link-supported");
648+ system_add_link_modes(b, ecmd.supported);
649+ blobmsg_close_array(b, c);
650
651- if (pause_autoneg) {
652- d = blobmsg_open_array(b, "link-advertising");
653- system_add_pause_modes(nwords, b, advertising);
654- blobmsg_close_array(b, d);
655- }
656-
657- d = blobmsg_open_array(b, "link-partner-advertising");
658- system_add_pause_modes(nwords, b, lp_advertising);
659- blobmsg_close_array(b, d);
660-
661- if (pause_autoneg) {
662- system_add_ethtool_pause_an(b, nwords, advertising,
663- lp_advertising);
664- } else {
665- d = blobmsg_open_array(b, "selected");
666- if (rx_pause)
667- blobmsg_add_string(b, NULL, "rx");
668-
669- if (tx_pause)
670- blobmsg_add_string(b, NULL, "tx");
671+ s = blobmsg_alloc_string_buffer(b, "speed", 8);
672+ snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
673+ ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
674+ blobmsg_add_string_buffer(b);
675
676- blobmsg_close_array(b, d);
677+ blobmsg_add_u8(b, "autoneg", !!ecmd.autoneg);
678 }
679
680- blobmsg_close_table(b, c);
681-
682 blobmsg_add_u8(b, "hw-tc-offload",
683 ethtool_feature_value(dev->ifname, "hw-tc-offload"));
684
685--
6862.18.0
687