xref: /linux/drivers/net/ethernet/intel/igc/igc_leds.c (revision 3a07362fab1653d3aca31a9155c8cc776138fd02)
1ea578703SKurt Kanzenbach // SPDX-License-Identifier: GPL-2.0
2ea578703SKurt Kanzenbach /* Copyright (C) 2024 Linutronix GmbH */
3ea578703SKurt Kanzenbach 
4ea578703SKurt Kanzenbach #include <linux/bits.h>
5ea578703SKurt Kanzenbach #include <linux/leds.h>
6ea578703SKurt Kanzenbach #include <linux/netdevice.h>
7ea578703SKurt Kanzenbach #include <linux/pm_runtime.h>
8ea578703SKurt Kanzenbach #include <uapi/linux/uleds.h>
9ea578703SKurt Kanzenbach 
10ea578703SKurt Kanzenbach #include "igc.h"
11ea578703SKurt Kanzenbach 
12ea578703SKurt Kanzenbach #define IGC_NUM_LEDS			3
13ea578703SKurt Kanzenbach 
14ea578703SKurt Kanzenbach #define IGC_LEDCTL_LED0_MODE_SHIFT	0
15ea578703SKurt Kanzenbach #define IGC_LEDCTL_LED0_MODE_MASK	GENMASK(3, 0)
16ea578703SKurt Kanzenbach #define IGC_LEDCTL_LED0_BLINK		BIT(7)
17ea578703SKurt Kanzenbach #define IGC_LEDCTL_LED1_MODE_SHIFT	8
18ea578703SKurt Kanzenbach #define IGC_LEDCTL_LED1_MODE_MASK	GENMASK(11, 8)
19ea578703SKurt Kanzenbach #define IGC_LEDCTL_LED1_BLINK		BIT(15)
20ea578703SKurt Kanzenbach #define IGC_LEDCTL_LED2_MODE_SHIFT	16
21ea578703SKurt Kanzenbach #define IGC_LEDCTL_LED2_MODE_MASK	GENMASK(19, 16)
22ea578703SKurt Kanzenbach #define IGC_LEDCTL_LED2_BLINK		BIT(23)
23ea578703SKurt Kanzenbach 
24ea578703SKurt Kanzenbach #define IGC_LEDCTL_MODE_ON		0x00
25ea578703SKurt Kanzenbach #define IGC_LEDCTL_MODE_OFF		0x01
26ea578703SKurt Kanzenbach #define IGC_LEDCTL_MODE_LINK_10		0x05
27ea578703SKurt Kanzenbach #define IGC_LEDCTL_MODE_LINK_100	0x06
28ea578703SKurt Kanzenbach #define IGC_LEDCTL_MODE_LINK_1000	0x07
29ea578703SKurt Kanzenbach #define IGC_LEDCTL_MODE_LINK_2500	0x08
30ea578703SKurt Kanzenbach #define IGC_LEDCTL_MODE_ACTIVITY	0x0b
31ea578703SKurt Kanzenbach 
32ea578703SKurt Kanzenbach #define IGC_SUPPORTED_MODES						 \
33ea578703SKurt Kanzenbach 	(BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK_1000) | \
34ea578703SKurt Kanzenbach 	 BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK_10) |	 \
35ea578703SKurt Kanzenbach 	 BIT(TRIGGER_NETDEV_RX) | BIT(TRIGGER_NETDEV_TX))
36ea578703SKurt Kanzenbach 
37ea578703SKurt Kanzenbach #define IGC_ACTIVITY_MODES					\
38ea578703SKurt Kanzenbach 	(BIT(TRIGGER_NETDEV_RX) | BIT(TRIGGER_NETDEV_TX))
39ea578703SKurt Kanzenbach 
40ea578703SKurt Kanzenbach struct igc_led_classdev {
41ea578703SKurt Kanzenbach 	struct net_device *netdev;
42ea578703SKurt Kanzenbach 	struct led_classdev led;
43ea578703SKurt Kanzenbach 	int index;
44ea578703SKurt Kanzenbach };
45ea578703SKurt Kanzenbach 
46ea578703SKurt Kanzenbach #define lcdev_to_igc_ldev(lcdev)				\
47ea578703SKurt Kanzenbach 	container_of(lcdev, struct igc_led_classdev, led)
48ea578703SKurt Kanzenbach 
igc_led_select(struct igc_adapter * adapter,int led,u32 * mask,u32 * shift,u32 * blink)49ea578703SKurt Kanzenbach static void igc_led_select(struct igc_adapter *adapter, int led,
50ea578703SKurt Kanzenbach 			   u32 *mask, u32 *shift, u32 *blink)
51ea578703SKurt Kanzenbach {
52ea578703SKurt Kanzenbach 	switch (led) {
53ea578703SKurt Kanzenbach 	case 0:
54ea578703SKurt Kanzenbach 		*mask  = IGC_LEDCTL_LED0_MODE_MASK;
55ea578703SKurt Kanzenbach 		*shift = IGC_LEDCTL_LED0_MODE_SHIFT;
56ea578703SKurt Kanzenbach 		*blink = IGC_LEDCTL_LED0_BLINK;
57ea578703SKurt Kanzenbach 		break;
58ea578703SKurt Kanzenbach 	case 1:
59ea578703SKurt Kanzenbach 		*mask  = IGC_LEDCTL_LED1_MODE_MASK;
60ea578703SKurt Kanzenbach 		*shift = IGC_LEDCTL_LED1_MODE_SHIFT;
61ea578703SKurt Kanzenbach 		*blink = IGC_LEDCTL_LED1_BLINK;
62ea578703SKurt Kanzenbach 		break;
63ea578703SKurt Kanzenbach 	case 2:
64ea578703SKurt Kanzenbach 		*mask  = IGC_LEDCTL_LED2_MODE_MASK;
65ea578703SKurt Kanzenbach 		*shift = IGC_LEDCTL_LED2_MODE_SHIFT;
66ea578703SKurt Kanzenbach 		*blink = IGC_LEDCTL_LED2_BLINK;
67ea578703SKurt Kanzenbach 		break;
68ea578703SKurt Kanzenbach 	default:
69ea578703SKurt Kanzenbach 		*mask = *shift = *blink = 0;
70ea578703SKurt Kanzenbach 		netdev_err(adapter->netdev, "Unknown LED %d selected!\n", led);
71ea578703SKurt Kanzenbach 	}
72ea578703SKurt Kanzenbach }
73ea578703SKurt Kanzenbach 
igc_led_set(struct igc_adapter * adapter,int led,u32 mode,bool blink)74ea578703SKurt Kanzenbach static void igc_led_set(struct igc_adapter *adapter, int led, u32 mode,
75ea578703SKurt Kanzenbach 			bool blink)
76ea578703SKurt Kanzenbach {
77ea578703SKurt Kanzenbach 	u32 shift, mask, blink_bit, ledctl;
78ea578703SKurt Kanzenbach 	struct igc_hw *hw = &adapter->hw;
79ea578703SKurt Kanzenbach 
80ea578703SKurt Kanzenbach 	igc_led_select(adapter, led, &mask, &shift, &blink_bit);
81ea578703SKurt Kanzenbach 
82ea578703SKurt Kanzenbach 	pm_runtime_get_sync(&adapter->pdev->dev);
83ea578703SKurt Kanzenbach 	mutex_lock(&adapter->led_mutex);
84ea578703SKurt Kanzenbach 
85ea578703SKurt Kanzenbach 	/* Set mode */
86ea578703SKurt Kanzenbach 	ledctl = rd32(IGC_LEDCTL);
87ea578703SKurt Kanzenbach 	ledctl &= ~mask;
88ea578703SKurt Kanzenbach 	ledctl |= mode << shift;
89ea578703SKurt Kanzenbach 
90ea578703SKurt Kanzenbach 	/* Configure blinking */
91ea578703SKurt Kanzenbach 	if (blink)
92ea578703SKurt Kanzenbach 		ledctl |= blink_bit;
93ea578703SKurt Kanzenbach 	else
94ea578703SKurt Kanzenbach 		ledctl &= ~blink_bit;
95ea578703SKurt Kanzenbach 	wr32(IGC_LEDCTL, ledctl);
96ea578703SKurt Kanzenbach 
97ea578703SKurt Kanzenbach 	mutex_unlock(&adapter->led_mutex);
98ea578703SKurt Kanzenbach 	pm_runtime_put(&adapter->pdev->dev);
99ea578703SKurt Kanzenbach }
100ea578703SKurt Kanzenbach 
igc_led_get(struct igc_adapter * adapter,int led)101ea578703SKurt Kanzenbach static u32 igc_led_get(struct igc_adapter *adapter, int led)
102ea578703SKurt Kanzenbach {
103ea578703SKurt Kanzenbach 	u32 shift, mask, blink_bit, ledctl;
104ea578703SKurt Kanzenbach 	struct igc_hw *hw = &adapter->hw;
105ea578703SKurt Kanzenbach 
106ea578703SKurt Kanzenbach 	igc_led_select(adapter, led, &mask, &shift, &blink_bit);
107ea578703SKurt Kanzenbach 
108ea578703SKurt Kanzenbach 	pm_runtime_get_sync(&adapter->pdev->dev);
109ea578703SKurt Kanzenbach 	mutex_lock(&adapter->led_mutex);
110ea578703SKurt Kanzenbach 	ledctl = rd32(IGC_LEDCTL);
111ea578703SKurt Kanzenbach 	mutex_unlock(&adapter->led_mutex);
112ea578703SKurt Kanzenbach 	pm_runtime_put(&adapter->pdev->dev);
113ea578703SKurt Kanzenbach 
114ea578703SKurt Kanzenbach 	return (ledctl & mask) >> shift;
115ea578703SKurt Kanzenbach }
116ea578703SKurt Kanzenbach 
igc_led_brightness_set_blocking(struct led_classdev * led_cdev,enum led_brightness brightness)117ea578703SKurt Kanzenbach static int igc_led_brightness_set_blocking(struct led_classdev *led_cdev,
118ea578703SKurt Kanzenbach 					   enum led_brightness brightness)
119ea578703SKurt Kanzenbach {
120ea578703SKurt Kanzenbach 	struct igc_led_classdev *ldev = lcdev_to_igc_ldev(led_cdev);
121ea578703SKurt Kanzenbach 	struct igc_adapter *adapter = netdev_priv(ldev->netdev);
122ea578703SKurt Kanzenbach 	u32 mode;
123ea578703SKurt Kanzenbach 
124ea578703SKurt Kanzenbach 	if (brightness)
125ea578703SKurt Kanzenbach 		mode = IGC_LEDCTL_MODE_ON;
126ea578703SKurt Kanzenbach 	else
127ea578703SKurt Kanzenbach 		mode = IGC_LEDCTL_MODE_OFF;
128ea578703SKurt Kanzenbach 
129ea578703SKurt Kanzenbach 	netdev_dbg(adapter->netdev, "Set brightness for LED %d to mode %u!\n",
130ea578703SKurt Kanzenbach 		   ldev->index, mode);
131ea578703SKurt Kanzenbach 
132ea578703SKurt Kanzenbach 	igc_led_set(adapter, ldev->index, mode, false);
133ea578703SKurt Kanzenbach 
134ea578703SKurt Kanzenbach 	return 0;
135ea578703SKurt Kanzenbach }
136ea578703SKurt Kanzenbach 
igc_led_hw_control_is_supported(struct led_classdev * led_cdev,unsigned long flags)137ea578703SKurt Kanzenbach static int igc_led_hw_control_is_supported(struct led_classdev *led_cdev,
138ea578703SKurt Kanzenbach 					   unsigned long flags)
139ea578703SKurt Kanzenbach {
140ea578703SKurt Kanzenbach 	if (flags & ~IGC_SUPPORTED_MODES)
141ea578703SKurt Kanzenbach 		return -EOPNOTSUPP;
142ea578703SKurt Kanzenbach 
143ea578703SKurt Kanzenbach 	/* If Tx and Rx selected, activity can be offloaded unless some other
144ea578703SKurt Kanzenbach 	 * mode is selected as well.
145ea578703SKurt Kanzenbach 	 */
146ea578703SKurt Kanzenbach 	if ((flags & BIT(TRIGGER_NETDEV_TX)) &&
147ea578703SKurt Kanzenbach 	    (flags & BIT(TRIGGER_NETDEV_RX)) &&
148ea578703SKurt Kanzenbach 	    !(flags & ~IGC_ACTIVITY_MODES))
149ea578703SKurt Kanzenbach 		return 0;
150ea578703SKurt Kanzenbach 
151ea578703SKurt Kanzenbach 	/* Single Rx or Tx activity is not supported. */
152ea578703SKurt Kanzenbach 	if (flags & IGC_ACTIVITY_MODES)
153ea578703SKurt Kanzenbach 		return -EOPNOTSUPP;
154ea578703SKurt Kanzenbach 
155ea578703SKurt Kanzenbach 	/* Only one mode can be active at a given time. */
156ea578703SKurt Kanzenbach 	if (flags & (flags - 1))
157ea578703SKurt Kanzenbach 		return -EOPNOTSUPP;
158ea578703SKurt Kanzenbach 
159ea578703SKurt Kanzenbach 	return 0;
160ea578703SKurt Kanzenbach }
161ea578703SKurt Kanzenbach 
igc_led_hw_control_set(struct led_classdev * led_cdev,unsigned long flags)162ea578703SKurt Kanzenbach static int igc_led_hw_control_set(struct led_classdev *led_cdev,
163ea578703SKurt Kanzenbach 				  unsigned long flags)
164ea578703SKurt Kanzenbach {
165ea578703SKurt Kanzenbach 	struct igc_led_classdev *ldev = lcdev_to_igc_ldev(led_cdev);
166ea578703SKurt Kanzenbach 	struct igc_adapter *adapter = netdev_priv(ldev->netdev);
167ea578703SKurt Kanzenbach 	u32 mode = IGC_LEDCTL_MODE_OFF;
168ea578703SKurt Kanzenbach 	bool blink = false;
169ea578703SKurt Kanzenbach 
170ea578703SKurt Kanzenbach 	if (flags & BIT(TRIGGER_NETDEV_LINK_10))
171ea578703SKurt Kanzenbach 		mode = IGC_LEDCTL_MODE_LINK_10;
172ea578703SKurt Kanzenbach 	if (flags & BIT(TRIGGER_NETDEV_LINK_100))
173ea578703SKurt Kanzenbach 		mode = IGC_LEDCTL_MODE_LINK_100;
174ea578703SKurt Kanzenbach 	if (flags & BIT(TRIGGER_NETDEV_LINK_1000))
175ea578703SKurt Kanzenbach 		mode = IGC_LEDCTL_MODE_LINK_1000;
176ea578703SKurt Kanzenbach 	if (flags & BIT(TRIGGER_NETDEV_LINK_2500))
177ea578703SKurt Kanzenbach 		mode = IGC_LEDCTL_MODE_LINK_2500;
178ea578703SKurt Kanzenbach 	if ((flags & BIT(TRIGGER_NETDEV_TX)) &&
179ea578703SKurt Kanzenbach 	    (flags & BIT(TRIGGER_NETDEV_RX)))
180ea578703SKurt Kanzenbach 		mode = IGC_LEDCTL_MODE_ACTIVITY;
181ea578703SKurt Kanzenbach 
182ea578703SKurt Kanzenbach 	netdev_dbg(adapter->netdev, "Set HW control for LED %d to mode %u!\n",
183ea578703SKurt Kanzenbach 		   ldev->index, mode);
184ea578703SKurt Kanzenbach 
185ea578703SKurt Kanzenbach 	/* blink is recommended for activity */
186ea578703SKurt Kanzenbach 	if (mode == IGC_LEDCTL_MODE_ACTIVITY)
187ea578703SKurt Kanzenbach 		blink = true;
188ea578703SKurt Kanzenbach 
189ea578703SKurt Kanzenbach 	igc_led_set(adapter, ldev->index, mode, blink);
190ea578703SKurt Kanzenbach 
191ea578703SKurt Kanzenbach 	return 0;
192ea578703SKurt Kanzenbach }
193ea578703SKurt Kanzenbach 
igc_led_hw_control_get(struct led_classdev * led_cdev,unsigned long * flags)194ea578703SKurt Kanzenbach static int igc_led_hw_control_get(struct led_classdev *led_cdev,
195ea578703SKurt Kanzenbach 				  unsigned long *flags)
196ea578703SKurt Kanzenbach {
197ea578703SKurt Kanzenbach 	struct igc_led_classdev *ldev = lcdev_to_igc_ldev(led_cdev);
198ea578703SKurt Kanzenbach 	struct igc_adapter *adapter = netdev_priv(ldev->netdev);
199ea578703SKurt Kanzenbach 	u32 mode;
200ea578703SKurt Kanzenbach 
201ea578703SKurt Kanzenbach 	mode = igc_led_get(adapter, ldev->index);
202ea578703SKurt Kanzenbach 
203ea578703SKurt Kanzenbach 	switch (mode) {
204ea578703SKurt Kanzenbach 	case IGC_LEDCTL_MODE_ACTIVITY:
205ea578703SKurt Kanzenbach 		*flags = BIT(TRIGGER_NETDEV_TX) | BIT(TRIGGER_NETDEV_RX);
206ea578703SKurt Kanzenbach 		break;
207ea578703SKurt Kanzenbach 	case IGC_LEDCTL_MODE_LINK_10:
208ea578703SKurt Kanzenbach 		*flags = BIT(TRIGGER_NETDEV_LINK_10);
209ea578703SKurt Kanzenbach 		break;
210ea578703SKurt Kanzenbach 	case IGC_LEDCTL_MODE_LINK_100:
211ea578703SKurt Kanzenbach 		*flags = BIT(TRIGGER_NETDEV_LINK_100);
212ea578703SKurt Kanzenbach 		break;
213ea578703SKurt Kanzenbach 	case IGC_LEDCTL_MODE_LINK_1000:
214ea578703SKurt Kanzenbach 		*flags = BIT(TRIGGER_NETDEV_LINK_1000);
215ea578703SKurt Kanzenbach 		break;
216ea578703SKurt Kanzenbach 	case IGC_LEDCTL_MODE_LINK_2500:
217ea578703SKurt Kanzenbach 		*flags = BIT(TRIGGER_NETDEV_LINK_2500);
218ea578703SKurt Kanzenbach 		break;
219ea578703SKurt Kanzenbach 	}
220ea578703SKurt Kanzenbach 
221ea578703SKurt Kanzenbach 	return 0;
222ea578703SKurt Kanzenbach }
223ea578703SKurt Kanzenbach 
igc_led_hw_control_get_device(struct led_classdev * led_cdev)224ea578703SKurt Kanzenbach static struct device *igc_led_hw_control_get_device(struct led_classdev *led_cdev)
225ea578703SKurt Kanzenbach {
226ea578703SKurt Kanzenbach 	struct igc_led_classdev *ldev = lcdev_to_igc_ldev(led_cdev);
227ea578703SKurt Kanzenbach 
228ea578703SKurt Kanzenbach 	return &ldev->netdev->dev;
229ea578703SKurt Kanzenbach }
230ea578703SKurt Kanzenbach 
igc_led_get_name(struct igc_adapter * adapter,int index,char * buf,size_t buf_len)231ea578703SKurt Kanzenbach static void igc_led_get_name(struct igc_adapter *adapter, int index, char *buf,
232ea578703SKurt Kanzenbach 			     size_t buf_len)
233ea578703SKurt Kanzenbach {
234ea578703SKurt Kanzenbach 	snprintf(buf, buf_len, "igc-%x%x-led%d",
235ea578703SKurt Kanzenbach 		 pci_domain_nr(adapter->pdev->bus),
236ea578703SKurt Kanzenbach 		 pci_dev_id(adapter->pdev), index);
237ea578703SKurt Kanzenbach }
238ea578703SKurt Kanzenbach 
igc_setup_ldev(struct igc_led_classdev * ldev,struct net_device * netdev,int index)239*c04d1b9eSLukas Wunner static int igc_setup_ldev(struct igc_led_classdev *ldev,
240ea578703SKurt Kanzenbach 			  struct net_device *netdev, int index)
241ea578703SKurt Kanzenbach {
242ea578703SKurt Kanzenbach 	struct igc_adapter *adapter = netdev_priv(netdev);
243ea578703SKurt Kanzenbach 	struct led_classdev *led_cdev = &ldev->led;
244ea578703SKurt Kanzenbach 	char led_name[LED_MAX_NAME_SIZE];
245ea578703SKurt Kanzenbach 
246ea578703SKurt Kanzenbach 	ldev->netdev = netdev;
247ea578703SKurt Kanzenbach 	ldev->index = index;
248ea578703SKurt Kanzenbach 
249ea578703SKurt Kanzenbach 	igc_led_get_name(adapter, index, led_name, LED_MAX_NAME_SIZE);
250ea578703SKurt Kanzenbach 	led_cdev->name = led_name;
251ea578703SKurt Kanzenbach 	led_cdev->flags |= LED_RETAIN_AT_SHUTDOWN;
252ea578703SKurt Kanzenbach 	led_cdev->max_brightness = 1;
253ea578703SKurt Kanzenbach 	led_cdev->brightness_set_blocking = igc_led_brightness_set_blocking;
254ea578703SKurt Kanzenbach 	led_cdev->hw_control_trigger = "netdev";
255ea578703SKurt Kanzenbach 	led_cdev->hw_control_is_supported = igc_led_hw_control_is_supported;
256ea578703SKurt Kanzenbach 	led_cdev->hw_control_set = igc_led_hw_control_set;
257ea578703SKurt Kanzenbach 	led_cdev->hw_control_get = igc_led_hw_control_get;
258ea578703SKurt Kanzenbach 	led_cdev->hw_control_get_device = igc_led_hw_control_get_device;
259ea578703SKurt Kanzenbach 
260*c04d1b9eSLukas Wunner 	return led_classdev_register(&netdev->dev, led_cdev);
261ea578703SKurt Kanzenbach }
262ea578703SKurt Kanzenbach 
igc_led_setup(struct igc_adapter * adapter)263ea578703SKurt Kanzenbach int igc_led_setup(struct igc_adapter *adapter)
264ea578703SKurt Kanzenbach {
265ea578703SKurt Kanzenbach 	struct net_device *netdev = adapter->netdev;
266ea578703SKurt Kanzenbach 	struct igc_led_classdev *leds;
267*c04d1b9eSLukas Wunner 	int i, err;
268ea578703SKurt Kanzenbach 
269ea578703SKurt Kanzenbach 	mutex_init(&adapter->led_mutex);
270ea578703SKurt Kanzenbach 
271*c04d1b9eSLukas Wunner 	leds = kcalloc(IGC_NUM_LEDS, sizeof(*leds), GFP_KERNEL);
272ea578703SKurt Kanzenbach 	if (!leds)
273ea578703SKurt Kanzenbach 		return -ENOMEM;
274ea578703SKurt Kanzenbach 
275*c04d1b9eSLukas Wunner 	for (i = 0; i < IGC_NUM_LEDS; i++) {
276*c04d1b9eSLukas Wunner 		err = igc_setup_ldev(leds + i, netdev, i);
277*c04d1b9eSLukas Wunner 		if (err)
278*c04d1b9eSLukas Wunner 			goto err;
279*c04d1b9eSLukas Wunner 	}
280*c04d1b9eSLukas Wunner 
281*c04d1b9eSLukas Wunner 	adapter->leds = leds;
282ea578703SKurt Kanzenbach 
283ea578703SKurt Kanzenbach 	return 0;
284*c04d1b9eSLukas Wunner 
285*c04d1b9eSLukas Wunner err:
286*c04d1b9eSLukas Wunner 	for (i--; i >= 0; i--)
287*c04d1b9eSLukas Wunner 		led_classdev_unregister(&((leds + i)->led));
288*c04d1b9eSLukas Wunner 
289*c04d1b9eSLukas Wunner 	kfree(leds);
290*c04d1b9eSLukas Wunner 	return err;
291*c04d1b9eSLukas Wunner }
292*c04d1b9eSLukas Wunner 
igc_led_free(struct igc_adapter * adapter)293*c04d1b9eSLukas Wunner void igc_led_free(struct igc_adapter *adapter)
294*c04d1b9eSLukas Wunner {
295*c04d1b9eSLukas Wunner 	struct igc_led_classdev *leds = adapter->leds;
296*c04d1b9eSLukas Wunner 	int i;
297*c04d1b9eSLukas Wunner 
298*c04d1b9eSLukas Wunner 	for (i = 0; i < IGC_NUM_LEDS; i++)
299*c04d1b9eSLukas Wunner 		led_classdev_unregister(&((leds + i)->led));
300*c04d1b9eSLukas Wunner 
301*c04d1b9eSLukas Wunner 	kfree(leds);
302ea578703SKurt Kanzenbach }
303