Skip to content

Commit f15176b

Browse files
linuswdavem330
authored andcommitted
net: dsa: rtl8366rb: Fix compilation problem
When the kernel is compiled without LED framework support the rtl8366rb fails to build like this: rtl8366rb.o: in function `rtl8366rb_setup_led': rtl8366rb.c:953:(.text.unlikely.rtl8366rb_setup_led+0xe8): undefined reference to `led_init_default_state_get' rtl8366rb.c:980:(.text.unlikely.rtl8366rb_setup_led+0x240): undefined reference to `devm_led_classdev_register_ext' As this is constantly coming up in different randconfig builds, bite the bullet and create a separate file for the offending code, split out a header with all stuff needed both in the core driver and the leds code. Add a new bool Kconfig option for the LED compile target, such that it depends on LEDS_CLASS=y || LEDS_CLASS=RTL8366RB which make LED support always available when LEDS_CLASS is compiled into the kernel and enforce that if the LEDS_CLASS is a module, then the RTL8366RB driver needs to be a module as well so that modprobe can resolve the dependencies. Fixes: 32d6170 ("net: dsa: realtek: add LED drivers for rtl8366rb") Reported-by: kernel test robot <[email protected]> Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/ Signed-off-by: Linus Walleij <[email protected]> Reviewed-by: Vladimir Oltean <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 28b0473 commit f15176b

File tree

5 files changed

+299
-252
lines changed

5 files changed

+299
-252
lines changed

drivers/net/dsa/realtek/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,10 @@ config NET_DSA_REALTEK_RTL8366RB
4343
help
4444
Select to enable support for Realtek RTL8366RB.
4545

46+
config NET_DSA_REALTEK_RTL8366RB_LEDS
47+
bool "Support RTL8366RB LED control"
48+
depends on (LEDS_CLASS=y || LEDS_CLASS=NET_DSA_REALTEK_RTL8366RB)
49+
depends on NET_DSA_REALTEK_RTL8366RB
50+
default NET_DSA_REALTEK_RTL8366RB
51+
4652
endif

drivers/net/dsa/realtek/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,7 @@ endif
1212

1313
obj-$(CONFIG_NET_DSA_REALTEK_RTL8366RB) += rtl8366.o
1414
rtl8366-objs := rtl8366-core.o rtl8366rb.o
15+
ifdef CONFIG_NET_DSA_REALTEK_RTL8366RB_LEDS
16+
rtl8366-objs += rtl8366rb-leds.o
17+
endif
1518
obj-$(CONFIG_NET_DSA_REALTEK_RTL8365MB) += rtl8365mb.o
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/bitops.h>
4+
#include <linux/regmap.h>
5+
#include <net/dsa.h>
6+
#include "rtl83xx.h"
7+
#include "rtl8366rb.h"
8+
9+
static inline u32 rtl8366rb_led_group_port_mask(u8 led_group, u8 port)
10+
{
11+
switch (led_group) {
12+
case 0:
13+
return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
14+
case 1:
15+
return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
16+
case 2:
17+
return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
18+
case 3:
19+
return FIELD_PREP(RTL8366RB_LED_0_X_CTRL_MASK, BIT(port));
20+
default:
21+
return 0;
22+
}
23+
}
24+
25+
static int rb8366rb_get_port_led(struct rtl8366rb_led *led)
26+
{
27+
struct realtek_priv *priv = led->priv;
28+
u8 led_group = led->led_group;
29+
u8 port_num = led->port_num;
30+
int ret;
31+
u32 val;
32+
33+
ret = regmap_read(priv->map, RTL8366RB_LED_X_X_CTRL_REG(led_group),
34+
&val);
35+
if (ret) {
36+
dev_err(priv->dev, "error reading LED on port %d group %d\n",
37+
led_group, port_num);
38+
return ret;
39+
}
40+
41+
return !!(val & rtl8366rb_led_group_port_mask(led_group, port_num));
42+
}
43+
44+
static int rb8366rb_set_port_led(struct rtl8366rb_led *led, bool enable)
45+
{
46+
struct realtek_priv *priv = led->priv;
47+
u8 led_group = led->led_group;
48+
u8 port_num = led->port_num;
49+
int ret;
50+
51+
ret = regmap_update_bits(priv->map,
52+
RTL8366RB_LED_X_X_CTRL_REG(led_group),
53+
rtl8366rb_led_group_port_mask(led_group,
54+
port_num),
55+
enable ? 0xffff : 0);
56+
if (ret) {
57+
dev_err(priv->dev, "error updating LED on port %d group %d\n",
58+
led_group, port_num);
59+
return ret;
60+
}
61+
62+
/* Change the LED group to manual controlled LEDs if required */
63+
ret = rb8366rb_set_ledgroup_mode(priv, led_group,
64+
RTL8366RB_LEDGROUP_FORCE);
65+
66+
if (ret) {
67+
dev_err(priv->dev, "error updating LED GROUP group %d\n",
68+
led_group);
69+
return ret;
70+
}
71+
72+
return 0;
73+
}
74+
75+
static int
76+
rtl8366rb_cled_brightness_set_blocking(struct led_classdev *ldev,
77+
enum led_brightness brightness)
78+
{
79+
struct rtl8366rb_led *led = container_of(ldev, struct rtl8366rb_led,
80+
cdev);
81+
82+
return rb8366rb_set_port_led(led, brightness == LED_ON);
83+
}
84+
85+
static int rtl8366rb_setup_led(struct realtek_priv *priv, struct dsa_port *dp,
86+
struct fwnode_handle *led_fwnode)
87+
{
88+
struct rtl8366rb *rb = priv->chip_data;
89+
struct led_init_data init_data = { };
90+
enum led_default_state state;
91+
struct rtl8366rb_led *led;
92+
u32 led_group;
93+
int ret;
94+
95+
ret = fwnode_property_read_u32(led_fwnode, "reg", &led_group);
96+
if (ret)
97+
return ret;
98+
99+
if (led_group >= RTL8366RB_NUM_LEDGROUPS) {
100+
dev_warn(priv->dev, "Invalid LED reg %d defined for port %d",
101+
led_group, dp->index);
102+
return -EINVAL;
103+
}
104+
105+
led = &rb->leds[dp->index][led_group];
106+
led->port_num = dp->index;
107+
led->led_group = led_group;
108+
led->priv = priv;
109+
110+
state = led_init_default_state_get(led_fwnode);
111+
switch (state) {
112+
case LEDS_DEFSTATE_ON:
113+
led->cdev.brightness = 1;
114+
rb8366rb_set_port_led(led, 1);
115+
break;
116+
case LEDS_DEFSTATE_KEEP:
117+
led->cdev.brightness =
118+
rb8366rb_get_port_led(led);
119+
break;
120+
case LEDS_DEFSTATE_OFF:
121+
default:
122+
led->cdev.brightness = 0;
123+
rb8366rb_set_port_led(led, 0);
124+
}
125+
126+
led->cdev.max_brightness = 1;
127+
led->cdev.brightness_set_blocking =
128+
rtl8366rb_cled_brightness_set_blocking;
129+
init_data.fwnode = led_fwnode;
130+
init_data.devname_mandatory = true;
131+
132+
init_data.devicename = kasprintf(GFP_KERNEL, "Realtek-%d:0%d:%d",
133+
dp->ds->index, dp->index, led_group);
134+
if (!init_data.devicename)
135+
return -ENOMEM;
136+
137+
ret = devm_led_classdev_register_ext(priv->dev, &led->cdev, &init_data);
138+
if (ret) {
139+
dev_warn(priv->dev, "Failed to init LED %d for port %d",
140+
led_group, dp->index);
141+
return ret;
142+
}
143+
144+
return 0;
145+
}
146+
147+
int rtl8366rb_setup_leds(struct realtek_priv *priv)
148+
{
149+
struct dsa_switch *ds = &priv->ds;
150+
struct device_node *leds_np;
151+
struct dsa_port *dp;
152+
int ret = 0;
153+
154+
dsa_switch_for_each_port(dp, ds) {
155+
if (!dp->dn)
156+
continue;
157+
158+
leds_np = of_get_child_by_name(dp->dn, "leds");
159+
if (!leds_np) {
160+
dev_dbg(priv->dev, "No leds defined for port %d",
161+
dp->index);
162+
continue;
163+
}
164+
165+
for_each_child_of_node_scoped(leds_np, led_np) {
166+
ret = rtl8366rb_setup_led(priv, dp,
167+
of_fwnode_handle(led_np));
168+
if (ret)
169+
break;
170+
}
171+
172+
of_node_put(leds_np);
173+
if (ret)
174+
return ret;
175+
}
176+
return 0;
177+
}

0 commit comments

Comments
 (0)