Linux Audio

Check our new training course

Linux BSP upgrade and security maintenance

Need help to get security updates for your Linux BSP?
Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* r8169_leds.c: Realtek 8169/8168/8101/8125 ethernet driver.
  3 *
  4 * Copyright (c) 2023 Heiner Kallweit <hkallweit1@gmail.com>
  5 *
  6 * See MAINTAINERS file for support contact information.
  7 */
  8
  9#include <linux/leds.h>
 10#include <linux/netdevice.h>
 11#include <uapi/linux/uleds.h>
 12
 13#include "r8169.h"
 14
 15#define RTL8168_LED_CTRL_OPTION2	BIT(15)
 16#define RTL8168_LED_CTRL_ACT		BIT(3)
 17#define RTL8168_LED_CTRL_LINK_1000	BIT(2)
 18#define RTL8168_LED_CTRL_LINK_100	BIT(1)
 19#define RTL8168_LED_CTRL_LINK_10	BIT(0)
 20
 21#define RTL8168_NUM_LEDS		3
 22
 23#define RTL8168_SUPPORTED_MODES \
 24	(BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK_100) | \
 25	 BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_RX) | \
 26	 BIT(TRIGGER_NETDEV_TX))
 27
 28struct r8169_led_classdev {
 29	struct led_classdev led;
 30	struct net_device *ndev;
 31	int index;
 32};
 33
 34#define lcdev_to_r8169_ldev(lcdev) container_of(lcdev, struct r8169_led_classdev, led)
 35
 36static int rtl8168_led_hw_control_is_supported(struct led_classdev *led_cdev,
 37					       unsigned long flags)
 38{
 39	struct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);
 40	struct rtl8169_private *tp = netdev_priv(ldev->ndev);
 41	int shift = ldev->index * 4;
 42	bool rx, tx;
 43
 44	if (flags & ~RTL8168_SUPPORTED_MODES)
 45		goto nosupp;
 46
 47	rx = flags & BIT(TRIGGER_NETDEV_RX);
 48	tx = flags & BIT(TRIGGER_NETDEV_TX);
 49	if (rx != tx)
 50		goto nosupp;
 51
 52	return 0;
 53
 54nosupp:
 55	/* Switch LED off to indicate that mode isn't supported */
 56	rtl8168_led_mod_ctrl(tp, 0x000f << shift, 0);
 57	return -EOPNOTSUPP;
 58}
 59
 60static int rtl8168_led_hw_control_set(struct led_classdev *led_cdev,
 61				      unsigned long flags)
 62{
 63	struct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);
 64	struct rtl8169_private *tp = netdev_priv(ldev->ndev);
 65	int shift = ldev->index * 4;
 66	u16 mode = 0;
 67
 68	if (flags & BIT(TRIGGER_NETDEV_LINK_10))
 69		mode |= RTL8168_LED_CTRL_LINK_10;
 70	if (flags & BIT(TRIGGER_NETDEV_LINK_100))
 71		mode |= RTL8168_LED_CTRL_LINK_100;
 72	if (flags & BIT(TRIGGER_NETDEV_LINK_1000))
 73		mode |= RTL8168_LED_CTRL_LINK_1000;
 74	if (flags & BIT(TRIGGER_NETDEV_TX))
 75		mode |= RTL8168_LED_CTRL_ACT;
 76
 77	return rtl8168_led_mod_ctrl(tp, 0x000f << shift, mode << shift);
 78}
 79
 80static int rtl8168_led_hw_control_get(struct led_classdev *led_cdev,
 81				      unsigned long *flags)
 82{
 83	struct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);
 84	struct rtl8169_private *tp = netdev_priv(ldev->ndev);
 85	int shift = ldev->index * 4;
 86	int mode;
 87
 88	mode = rtl8168_get_led_mode(tp);
 89	if (mode < 0)
 90		return mode;
 91
 92	if (mode & RTL8168_LED_CTRL_OPTION2) {
 93		rtl8168_led_mod_ctrl(tp, RTL8168_LED_CTRL_OPTION2, 0);
 94		netdev_notice(ldev->ndev, "Deactivating unsupported Option2 LED mode\n");
 95	}
 96
 97	mode = (mode >> shift) & 0x000f;
 98
 99	if (mode & RTL8168_LED_CTRL_ACT)
100		*flags |= BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX);
101
102	if (mode & RTL8168_LED_CTRL_LINK_10)
103		*flags |= BIT(TRIGGER_NETDEV_LINK_10);
104	if (mode & RTL8168_LED_CTRL_LINK_100)
105		*flags |= BIT(TRIGGER_NETDEV_LINK_100);
106	if (mode & RTL8168_LED_CTRL_LINK_1000)
107		*flags |= BIT(TRIGGER_NETDEV_LINK_1000);
108
109	return 0;
110}
111
112static struct device *
113	r8169_led_hw_control_get_device(struct led_classdev *led_cdev)
114{
115	struct r8169_led_classdev *ldev = lcdev_to_r8169_ldev(led_cdev);
116
117	return &ldev->ndev->dev;
118}
119
120static void rtl8168_setup_ldev(struct r8169_led_classdev *ldev,
121			       struct net_device *ndev, int index)
122{
123	struct rtl8169_private *tp = netdev_priv(ndev);
124	struct led_classdev *led_cdev = &ldev->led;
125	char led_name[LED_MAX_NAME_SIZE];
126
127	ldev->ndev = ndev;
128	ldev->index = index;
129
130	r8169_get_led_name(tp, index, led_name, LED_MAX_NAME_SIZE);
131	led_cdev->name = led_name;
132	led_cdev->default_trigger = "netdev";
133	led_cdev->hw_control_trigger = "netdev";
134	led_cdev->flags |= LED_RETAIN_AT_SHUTDOWN;
135	led_cdev->hw_control_is_supported = rtl8168_led_hw_control_is_supported;
136	led_cdev->hw_control_set = rtl8168_led_hw_control_set;
137	led_cdev->hw_control_get = rtl8168_led_hw_control_get;
138	led_cdev->hw_control_get_device = r8169_led_hw_control_get_device;
139
140	/* ignore errors */
141	devm_led_classdev_register(&ndev->dev, led_cdev);
142}
143
144void rtl8168_init_leds(struct net_device *ndev)
145{
146	/* bind resource mgmt to netdev */
147	struct device *dev = &ndev->dev;
148	struct r8169_led_classdev *leds;
149	int i;
150
151	leds = devm_kcalloc(dev, RTL8168_NUM_LEDS, sizeof(*leds), GFP_KERNEL);
152	if (!leds)
153		return;
154
155	for (i = 0; i < RTL8168_NUM_LEDS; i++)
156		rtl8168_setup_ldev(leds + i, ndev, i);
157}