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

led.c (3898B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Common code for mac80211 Prism54 drivers
      4 *
      5 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
      6 * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de>
      7 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
      8 *
      9 * Based on:
     10 * - the islsm (softmac prism54) driver, which is:
     11 *   Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
     12 * - stlc45xx driver
     13 *   Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
     14 */
     15
     16#include <linux/firmware.h>
     17#include <linux/etherdevice.h>
     18
     19#include <net/mac80211.h>
     20#ifdef CONFIG_P54_LEDS
     21#include <linux/leds.h>
     22#endif /* CONFIG_P54_LEDS */
     23
     24#include "p54.h"
     25#include "lmac.h"
     26
     27static void p54_update_leds(struct work_struct *work)
     28{
     29	struct p54_common *priv = container_of(work, struct p54_common,
     30					       led_work.work);
     31	int err, i, tmp, blink_delay = 400;
     32	bool rerun = false;
     33
     34	/* Don't toggle the LED, when the device is down. */
     35	if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
     36		return ;
     37
     38	for (i = 0; i < ARRAY_SIZE(priv->leds); i++)
     39		if (priv->leds[i].toggled) {
     40			priv->softled_state |= BIT(i);
     41
     42			tmp = 70 + 200 / (priv->leds[i].toggled);
     43			if (tmp < blink_delay)
     44				blink_delay = tmp;
     45
     46			if (priv->leds[i].led_dev.brightness == LED_OFF)
     47				rerun = true;
     48
     49			priv->leds[i].toggled =
     50				!!priv->leds[i].led_dev.brightness;
     51		} else
     52			priv->softled_state &= ~BIT(i);
     53
     54	err = p54_set_leds(priv);
     55	if (err && net_ratelimit())
     56		wiphy_err(priv->hw->wiphy,
     57			  "failed to update LEDs (%d).\n", err);
     58
     59	if (rerun)
     60		ieee80211_queue_delayed_work(priv->hw, &priv->led_work,
     61			msecs_to_jiffies(blink_delay));
     62}
     63
     64static void p54_led_brightness_set(struct led_classdev *led_dev,
     65				   enum led_brightness brightness)
     66{
     67	struct p54_led_dev *led = container_of(led_dev, struct p54_led_dev,
     68					       led_dev);
     69	struct ieee80211_hw *dev = led->hw_dev;
     70	struct p54_common *priv = dev->priv;
     71
     72	if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
     73		return ;
     74
     75	if ((brightness) && (led->registered)) {
     76		led->toggled++;
     77		ieee80211_queue_delayed_work(priv->hw, &priv->led_work, HZ/10);
     78	}
     79}
     80
     81static int p54_register_led(struct p54_common *priv,
     82			    unsigned int led_index,
     83			    char *name, const char *trigger)
     84{
     85	struct p54_led_dev *led = &priv->leds[led_index];
     86	int err;
     87
     88	if (led->registered)
     89		return -EEXIST;
     90
     91	snprintf(led->name, sizeof(led->name), "p54-%s::%s",
     92		 wiphy_name(priv->hw->wiphy), name);
     93	led->hw_dev = priv->hw;
     94	led->index = led_index;
     95	led->led_dev.name = led->name;
     96	led->led_dev.default_trigger = trigger;
     97	led->led_dev.brightness_set = p54_led_brightness_set;
     98
     99	err = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_dev);
    100	if (err)
    101		wiphy_err(priv->hw->wiphy,
    102			  "Failed to register %s LED.\n", name);
    103	else
    104		led->registered = 1;
    105
    106	return err;
    107}
    108
    109int p54_init_leds(struct p54_common *priv)
    110{
    111	int err;
    112
    113	/*
    114	 * TODO:
    115	 * Figure out if the EEPROM contains some hints about the number
    116	 * of available/programmable LEDs of the device.
    117	 */
    118
    119	INIT_DELAYED_WORK(&priv->led_work, p54_update_leds);
    120
    121	err = p54_register_led(priv, 0, "assoc",
    122			       ieee80211_get_assoc_led_name(priv->hw));
    123	if (err)
    124		return err;
    125
    126	err = p54_register_led(priv, 1, "tx",
    127			       ieee80211_get_tx_led_name(priv->hw));
    128	if (err)
    129		return err;
    130
    131	err = p54_register_led(priv, 2, "rx",
    132			       ieee80211_get_rx_led_name(priv->hw));
    133	if (err)
    134		return err;
    135
    136	err = p54_register_led(priv, 3, "radio",
    137			       ieee80211_get_radio_led_name(priv->hw));
    138	if (err)
    139		return err;
    140
    141	err = p54_set_leds(priv);
    142	return err;
    143}
    144
    145void p54_unregister_leds(struct p54_common *priv)
    146{
    147	int i;
    148
    149	for (i = 0; i < ARRAY_SIZE(priv->leds); i++) {
    150		if (priv->leds[i].registered) {
    151			priv->leds[i].registered = false;
    152			priv->leds[i].toggled = 0;
    153			led_classdev_unregister(&priv->leds[i].led_dev);
    154		}
    155	}
    156
    157	cancel_delayed_work_sync(&priv->led_work);
    158}