cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

leds.c (6392B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3
      4  Broadcom B43 wireless driver
      5  LED control
      6
      7  Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
      8  Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
      9  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
     10  Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
     11  Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
     12
     13
     14*/
     15
     16#include "b43legacy.h"
     17#include "leds.h"
     18#include "rfkill.h"
     19
     20
     21static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index,
     22			    bool activelow)
     23{
     24	struct b43legacy_wl *wl = dev->wl;
     25	unsigned long flags;
     26	u16 ctl;
     27
     28	spin_lock_irqsave(&wl->leds_lock, flags);
     29	ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
     30	if (activelow)
     31		ctl &= ~(1 << led_index);
     32	else
     33		ctl |= (1 << led_index);
     34	b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
     35	spin_unlock_irqrestore(&wl->leds_lock, flags);
     36}
     37
     38static void b43legacy_led_turn_off(struct b43legacy_wldev *dev, u8 led_index,
     39			     bool activelow)
     40{
     41	struct b43legacy_wl *wl = dev->wl;
     42	unsigned long flags;
     43	u16 ctl;
     44
     45	spin_lock_irqsave(&wl->leds_lock, flags);
     46	ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
     47	if (activelow)
     48		ctl |= (1 << led_index);
     49	else
     50		ctl &= ~(1 << led_index);
     51	b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
     52	spin_unlock_irqrestore(&wl->leds_lock, flags);
     53}
     54
     55/* Callback from the LED subsystem. */
     56static void b43legacy_led_brightness_set(struct led_classdev *led_dev,
     57				   enum led_brightness brightness)
     58{
     59	struct b43legacy_led *led = container_of(led_dev, struct b43legacy_led,
     60				    led_dev);
     61	struct b43legacy_wldev *dev = led->dev;
     62	bool radio_enabled;
     63
     64	/* Checking the radio-enabled status here is slightly racy,
     65	 * but we want to avoid the locking overhead and we don't care
     66	 * whether the LED has the wrong state for a second. */
     67	radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
     68
     69	if (brightness == LED_OFF || !radio_enabled)
     70		b43legacy_led_turn_off(dev, led->index, led->activelow);
     71	else
     72		b43legacy_led_turn_on(dev, led->index, led->activelow);
     73}
     74
     75static int b43legacy_register_led(struct b43legacy_wldev *dev,
     76				  struct b43legacy_led *led,
     77				  const char *name,
     78				  const char *default_trigger,
     79				  u8 led_index, bool activelow)
     80{
     81	int err;
     82
     83	b43legacy_led_turn_off(dev, led_index, activelow);
     84	if (led->dev)
     85		return -EEXIST;
     86	if (!default_trigger)
     87		return -EINVAL;
     88	led->dev = dev;
     89	led->index = led_index;
     90	led->activelow = activelow;
     91	strlcpy(led->name, name, sizeof(led->name));
     92
     93	led->led_dev.name = led->name;
     94	led->led_dev.default_trigger = default_trigger;
     95	led->led_dev.brightness_set = b43legacy_led_brightness_set;
     96
     97	err = led_classdev_register(dev->dev->dev, &led->led_dev);
     98	if (err) {
     99		b43legacywarn(dev->wl, "LEDs: Failed to register %s\n", name);
    100		led->dev = NULL;
    101		return err;
    102	}
    103	return 0;
    104}
    105
    106static void b43legacy_unregister_led(struct b43legacy_led *led)
    107{
    108	if (!led->dev)
    109		return;
    110	led_classdev_unregister(&led->led_dev);
    111	b43legacy_led_turn_off(led->dev, led->index, led->activelow);
    112	led->dev = NULL;
    113}
    114
    115static void b43legacy_map_led(struct b43legacy_wldev *dev,
    116			u8 led_index,
    117			enum b43legacy_led_behaviour behaviour,
    118			bool activelow)
    119{
    120	struct ieee80211_hw *hw = dev->wl->hw;
    121	char name[B43legacy_LED_MAX_NAME_LEN + 1];
    122
    123	/* Map the b43 specific LED behaviour value to the
    124	 * generic LED triggers. */
    125	switch (behaviour) {
    126	case B43legacy_LED_INACTIVE:
    127		break;
    128	case B43legacy_LED_OFF:
    129		b43legacy_led_turn_off(dev, led_index, activelow);
    130		break;
    131	case B43legacy_LED_ON:
    132		b43legacy_led_turn_on(dev, led_index, activelow);
    133		break;
    134	case B43legacy_LED_ACTIVITY:
    135	case B43legacy_LED_TRANSFER:
    136	case B43legacy_LED_APTRANSFER:
    137		snprintf(name, sizeof(name),
    138			 "b43legacy-%s::tx", wiphy_name(hw->wiphy));
    139		b43legacy_register_led(dev, &dev->led_tx, name,
    140				 ieee80211_get_tx_led_name(hw),
    141				 led_index, activelow);
    142		snprintf(name, sizeof(name),
    143			 "b43legacy-%s::rx", wiphy_name(hw->wiphy));
    144		b43legacy_register_led(dev, &dev->led_rx, name,
    145				 ieee80211_get_rx_led_name(hw),
    146				 led_index, activelow);
    147		break;
    148	case B43legacy_LED_RADIO_ALL:
    149	case B43legacy_LED_RADIO_A:
    150	case B43legacy_LED_RADIO_B:
    151	case B43legacy_LED_MODE_BG:
    152		snprintf(name, sizeof(name),
    153			 "b43legacy-%s::radio", wiphy_name(hw->wiphy));
    154		b43legacy_register_led(dev, &dev->led_radio, name,
    155				 ieee80211_get_radio_led_name(hw),
    156				 led_index, activelow);
    157		/* Sync the RF-kill LED state with radio and switch states. */
    158		if (dev->phy.radio_on && b43legacy_is_hw_radio_enabled(dev))
    159			b43legacy_led_turn_on(dev, led_index, activelow);
    160		break;
    161	case B43legacy_LED_WEIRD:
    162	case B43legacy_LED_ASSOC:
    163		snprintf(name, sizeof(name),
    164			 "b43legacy-%s::assoc", wiphy_name(hw->wiphy));
    165		b43legacy_register_led(dev, &dev->led_assoc, name,
    166				 ieee80211_get_assoc_led_name(hw),
    167				 led_index, activelow);
    168		break;
    169	default:
    170		b43legacywarn(dev->wl, "LEDs: Unknown behaviour 0x%02X\n",
    171			behaviour);
    172		break;
    173	}
    174}
    175
    176void b43legacy_leds_init(struct b43legacy_wldev *dev)
    177{
    178	struct ssb_bus *bus = dev->dev->bus;
    179	u8 sprom[4];
    180	int i;
    181	enum b43legacy_led_behaviour behaviour;
    182	bool activelow;
    183
    184	sprom[0] = bus->sprom.gpio0;
    185	sprom[1] = bus->sprom.gpio1;
    186	sprom[2] = bus->sprom.gpio2;
    187	sprom[3] = bus->sprom.gpio3;
    188
    189	for (i = 0; i < 4; i++) {
    190		if (sprom[i] == 0xFF) {
    191			/* There is no LED information in the SPROM
    192			 * for this LED. Hardcode it here. */
    193			activelow = false;
    194			switch (i) {
    195			case 0:
    196				behaviour = B43legacy_LED_ACTIVITY;
    197				activelow = true;
    198				if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
    199					behaviour = B43legacy_LED_RADIO_ALL;
    200				break;
    201			case 1:
    202				behaviour = B43legacy_LED_RADIO_B;
    203				if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
    204					behaviour = B43legacy_LED_ASSOC;
    205				break;
    206			case 2:
    207				behaviour = B43legacy_LED_RADIO_A;
    208				break;
    209			case 3:
    210				behaviour = B43legacy_LED_OFF;
    211				break;
    212			default:
    213				B43legacy_WARN_ON(1);
    214				return;
    215			}
    216		} else {
    217			behaviour = sprom[i] & B43legacy_LED_BEHAVIOUR;
    218			activelow = !!(sprom[i] & B43legacy_LED_ACTIVELOW);
    219		}
    220		b43legacy_map_led(dev, i, behaviour, activelow);
    221	}
    222}
    223
    224void b43legacy_leds_exit(struct b43legacy_wldev *dev)
    225{
    226	b43legacy_unregister_led(&dev->led_tx);
    227	b43legacy_unregister_led(&dev->led_rx);
    228	b43legacy_unregister_led(&dev->led_assoc);
    229	b43legacy_unregister_led(&dev->led_radio);
    230}