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 (4997B)


      1/*
      2 * Atheros CARL9170 driver
      3 *
      4 * LED handling
      5 *
      6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
      7 * Copyright 2009, 2010, Christian Lamparer <chunkeey@googlemail.com>
      8 *
      9 * This program is free software; you can redistribute it and/or modify
     10 * it under the terms of the GNU General Public License as published by
     11 * the Free Software Foundation; either version 2 of the License, or
     12 * (at your option) any later version.
     13 *
     14 * This program is distributed in the hope that it will be useful,
     15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 * GNU General Public License for more details.
     18 *
     19 * You should have received a copy of the GNU General Public License
     20 * along with this program; see the file COPYING.  If not, see
     21 * http://www.gnu.org/licenses/.
     22 *
     23 * This file incorporates work covered by the following copyright and
     24 * permission notice:
     25 *    Copyright (c) 2007-2008 Atheros Communications, Inc.
     26 *
     27 *    Permission to use, copy, modify, and/or distribute this software for any
     28 *    purpose with or without fee is hereby granted, provided that the above
     29 *    copyright notice and this permission notice appear in all copies.
     30 *
     31 *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     32 *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     33 *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     34 *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     35 *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     36 *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     37 *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     38 */
     39
     40#include "carl9170.h"
     41#include "cmd.h"
     42
     43int carl9170_led_set_state(struct ar9170 *ar, const u32 led_state)
     44{
     45	return carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_DATA, led_state);
     46}
     47
     48int carl9170_led_init(struct ar9170 *ar)
     49{
     50	int err;
     51
     52	/* disable LEDs */
     53	/* GPIO [0/1 mode: output, 2/3: input] */
     54	err = carl9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3);
     55	if (err)
     56		goto out;
     57
     58	/* GPIO 0/1 value: off */
     59	err = carl9170_led_set_state(ar, 0);
     60
     61out:
     62	return err;
     63}
     64
     65#ifdef CONFIG_CARL9170_LEDS
     66static void carl9170_led_update(struct work_struct *work)
     67{
     68	struct ar9170 *ar = container_of(work, struct ar9170, led_work.work);
     69	int i, tmp = 300, blink_delay = 1000;
     70	u32 led_val = 0;
     71	bool rerun = false;
     72
     73	if (!IS_ACCEPTING_CMD(ar))
     74		return;
     75
     76	mutex_lock(&ar->mutex);
     77	for (i = 0; i < AR9170_NUM_LEDS; i++) {
     78		if (ar->leds[i].registered) {
     79			if (ar->leds[i].last_state ||
     80			    ar->leds[i].toggled) {
     81
     82				if (ar->leds[i].toggled)
     83					tmp = 70 + 200 / (ar->leds[i].toggled);
     84
     85				if (tmp < blink_delay)
     86					blink_delay = tmp;
     87
     88				led_val |= 1 << i;
     89				ar->leds[i].toggled = 0;
     90				rerun = true;
     91			}
     92		}
     93	}
     94
     95	carl9170_led_set_state(ar, led_val);
     96	mutex_unlock(&ar->mutex);
     97
     98	if (!rerun)
     99		return;
    100
    101	ieee80211_queue_delayed_work(ar->hw,
    102				     &ar->led_work,
    103				     msecs_to_jiffies(blink_delay));
    104}
    105
    106static void carl9170_led_set_brightness(struct led_classdev *led,
    107					enum led_brightness brightness)
    108{
    109	struct carl9170_led *arl = container_of(led, struct carl9170_led, l);
    110	struct ar9170 *ar = arl->ar;
    111
    112	if (!arl->registered)
    113		return;
    114
    115	if (arl->last_state != !!brightness) {
    116		arl->toggled++;
    117		arl->last_state = !!brightness;
    118	}
    119
    120	if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled))
    121		ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ / 10);
    122}
    123
    124static int carl9170_led_register_led(struct ar9170 *ar, int i, char *name,
    125				     const char *trigger)
    126{
    127	int err;
    128
    129	snprintf(ar->leds[i].name, sizeof(ar->leds[i].name),
    130		 "carl9170-%s::%s", wiphy_name(ar->hw->wiphy), name);
    131
    132	ar->leds[i].ar = ar;
    133	ar->leds[i].l.name = ar->leds[i].name;
    134	ar->leds[i].l.brightness_set = carl9170_led_set_brightness;
    135	ar->leds[i].l.brightness = 0;
    136	ar->leds[i].l.default_trigger = trigger;
    137
    138	err = led_classdev_register(wiphy_dev(ar->hw->wiphy),
    139				    &ar->leds[i].l);
    140	if (err) {
    141		wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n",
    142			ar->leds[i].name, err);
    143	} else {
    144		ar->leds[i].registered = true;
    145	}
    146
    147	return err;
    148}
    149
    150void carl9170_led_unregister(struct ar9170 *ar)
    151{
    152	int i;
    153
    154	for (i = 0; i < AR9170_NUM_LEDS; i++)
    155		if (ar->leds[i].registered) {
    156			led_classdev_unregister(&ar->leds[i].l);
    157			ar->leds[i].registered = false;
    158			ar->leds[i].toggled = 0;
    159		}
    160
    161	cancel_delayed_work_sync(&ar->led_work);
    162}
    163
    164int carl9170_led_register(struct ar9170 *ar)
    165{
    166	int err;
    167
    168	INIT_DELAYED_WORK(&ar->led_work, carl9170_led_update);
    169
    170	err = carl9170_led_register_led(ar, 0, "tx",
    171					ieee80211_get_tx_led_name(ar->hw));
    172	if (err)
    173		goto fail;
    174
    175	if (ar->features & CARL9170_ONE_LED)
    176		return 0;
    177
    178	err = carl9170_led_register_led(ar, 1, "assoc",
    179					ieee80211_get_assoc_led_name(ar->hw));
    180	if (err)
    181		goto fail;
    182
    183	return 0;
    184
    185fail:
    186	carl9170_led_unregister(ar);
    187	return err;
    188}
    189
    190#endif /* CONFIG_CARL9170_LEDS */