LCOV - code coverage report
Current view: top level - net/mac80211 - led.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 16 189 8.5 %
Date: 2022-03-28 15:32:58 Functions: 2 24 8.3 %
Branches: 4 78 5.1 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * Copyright 2006, Johannes Berg <johannes@sipsolutions.net>
       4                 :            :  */
       5                 :            : 
       6                 :            : /* just for IFNAMSIZ */
       7                 :            : #include <linux/if.h>
       8                 :            : #include <linux/slab.h>
       9                 :            : #include <linux/export.h>
      10                 :            : #include "led.h"
      11                 :            : 
      12                 :          0 : void ieee80211_led_assoc(struct ieee80211_local *local, bool associated)
      13                 :            : {
      14         [ #  # ]:          0 :         if (!atomic_read(&local->assoc_led_active))
      15                 :            :                 return;
      16         [ #  # ]:          0 :         if (associated)
      17                 :          0 :                 led_trigger_event(&local->assoc_led, LED_FULL);
      18                 :            :         else
      19                 :          0 :                 led_trigger_event(&local->assoc_led, LED_OFF);
      20                 :            : }
      21                 :            : 
      22                 :          0 : void ieee80211_led_radio(struct ieee80211_local *local, bool enabled)
      23                 :            : {
      24         [ #  # ]:          0 :         if (!atomic_read(&local->radio_led_active))
      25                 :            :                 return;
      26         [ #  # ]:          0 :         if (enabled)
      27                 :          0 :                 led_trigger_event(&local->radio_led, LED_FULL);
      28                 :            :         else
      29                 :          0 :                 led_trigger_event(&local->radio_led, LED_OFF);
      30                 :            : }
      31                 :            : 
      32                 :         28 : void ieee80211_alloc_led_names(struct ieee80211_local *local)
      33                 :            : {
      34                 :         28 :         local->rx_led.name = kasprintf(GFP_KERNEL, "%srx",
      35         [ +  - ]:         28 :                                        wiphy_name(local->hw.wiphy));
      36                 :         28 :         local->tx_led.name = kasprintf(GFP_KERNEL, "%stx",
      37         [ +  - ]:         28 :                                        wiphy_name(local->hw.wiphy));
      38                 :         28 :         local->assoc_led.name = kasprintf(GFP_KERNEL, "%sassoc",
      39         [ +  - ]:         28 :                                           wiphy_name(local->hw.wiphy));
      40                 :         28 :         local->radio_led.name = kasprintf(GFP_KERNEL, "%sradio",
      41         [ +  - ]:         28 :                                           wiphy_name(local->hw.wiphy));
      42                 :         28 : }
      43                 :            : 
      44                 :          3 : void ieee80211_free_led_names(struct ieee80211_local *local)
      45                 :            : {
      46                 :          3 :         kfree(local->rx_led.name);
      47                 :          3 :         kfree(local->tx_led.name);
      48                 :          3 :         kfree(local->assoc_led.name);
      49                 :          3 :         kfree(local->radio_led.name);
      50                 :          3 : }
      51                 :            : 
      52                 :          0 : static int ieee80211_tx_led_activate(struct led_classdev *led_cdev)
      53                 :            : {
      54                 :          0 :         struct ieee80211_local *local = container_of(led_cdev->trigger,
      55                 :            :                                                      struct ieee80211_local,
      56                 :            :                                                      tx_led);
      57                 :            : 
      58                 :          0 :         atomic_inc(&local->tx_led_active);
      59                 :            : 
      60                 :          0 :         return 0;
      61                 :            : }
      62                 :            : 
      63                 :          0 : static void ieee80211_tx_led_deactivate(struct led_classdev *led_cdev)
      64                 :            : {
      65                 :          0 :         struct ieee80211_local *local = container_of(led_cdev->trigger,
      66                 :            :                                                      struct ieee80211_local,
      67                 :            :                                                      tx_led);
      68                 :            : 
      69                 :          0 :         atomic_dec(&local->tx_led_active);
      70                 :          0 : }
      71                 :            : 
      72                 :          0 : static int ieee80211_rx_led_activate(struct led_classdev *led_cdev)
      73                 :            : {
      74                 :          0 :         struct ieee80211_local *local = container_of(led_cdev->trigger,
      75                 :            :                                                      struct ieee80211_local,
      76                 :            :                                                      rx_led);
      77                 :            : 
      78                 :          0 :         atomic_inc(&local->rx_led_active);
      79                 :            : 
      80                 :          0 :         return 0;
      81                 :            : }
      82                 :            : 
      83                 :          0 : static void ieee80211_rx_led_deactivate(struct led_classdev *led_cdev)
      84                 :            : {
      85                 :          0 :         struct ieee80211_local *local = container_of(led_cdev->trigger,
      86                 :            :                                                      struct ieee80211_local,
      87                 :            :                                                      rx_led);
      88                 :            : 
      89                 :          0 :         atomic_dec(&local->rx_led_active);
      90                 :          0 : }
      91                 :            : 
      92                 :          0 : static int ieee80211_assoc_led_activate(struct led_classdev *led_cdev)
      93                 :            : {
      94                 :          0 :         struct ieee80211_local *local = container_of(led_cdev->trigger,
      95                 :            :                                                      struct ieee80211_local,
      96                 :            :                                                      assoc_led);
      97                 :            : 
      98                 :          0 :         atomic_inc(&local->assoc_led_active);
      99                 :            : 
     100                 :          0 :         return 0;
     101                 :            : }
     102                 :            : 
     103                 :          0 : static void ieee80211_assoc_led_deactivate(struct led_classdev *led_cdev)
     104                 :            : {
     105                 :          0 :         struct ieee80211_local *local = container_of(led_cdev->trigger,
     106                 :            :                                                      struct ieee80211_local,
     107                 :            :                                                      assoc_led);
     108                 :            : 
     109                 :          0 :         atomic_dec(&local->assoc_led_active);
     110                 :          0 : }
     111                 :            : 
     112                 :          0 : static int ieee80211_radio_led_activate(struct led_classdev *led_cdev)
     113                 :            : {
     114                 :          0 :         struct ieee80211_local *local = container_of(led_cdev->trigger,
     115                 :            :                                                      struct ieee80211_local,
     116                 :            :                                                      radio_led);
     117                 :            : 
     118                 :          0 :         atomic_inc(&local->radio_led_active);
     119                 :            : 
     120                 :          0 :         return 0;
     121                 :            : }
     122                 :            : 
     123                 :          0 : static void ieee80211_radio_led_deactivate(struct led_classdev *led_cdev)
     124                 :            : {
     125                 :          0 :         struct ieee80211_local *local = container_of(led_cdev->trigger,
     126                 :            :                                                      struct ieee80211_local,
     127                 :            :                                                      radio_led);
     128                 :            : 
     129                 :          0 :         atomic_dec(&local->radio_led_active);
     130                 :          0 : }
     131                 :            : 
     132                 :          0 : static int ieee80211_tpt_led_activate(struct led_classdev *led_cdev)
     133                 :            : {
     134                 :          0 :         struct ieee80211_local *local = container_of(led_cdev->trigger,
     135                 :            :                                                      struct ieee80211_local,
     136                 :            :                                                      tpt_led);
     137                 :            : 
     138                 :          0 :         atomic_inc(&local->tpt_led_active);
     139                 :            : 
     140                 :          0 :         return 0;
     141                 :            : }
     142                 :            : 
     143                 :          0 : static void ieee80211_tpt_led_deactivate(struct led_classdev *led_cdev)
     144                 :            : {
     145                 :          0 :         struct ieee80211_local *local = container_of(led_cdev->trigger,
     146                 :            :                                                      struct ieee80211_local,
     147                 :            :                                                      tpt_led);
     148                 :            : 
     149                 :          0 :         atomic_dec(&local->tpt_led_active);
     150                 :          0 : }
     151                 :            : 
     152                 :          0 : void ieee80211_led_init(struct ieee80211_local *local)
     153                 :            : {
     154                 :          0 :         atomic_set(&local->rx_led_active, 0);
     155                 :          0 :         local->rx_led.activate = ieee80211_rx_led_activate;
     156                 :          0 :         local->rx_led.deactivate = ieee80211_rx_led_deactivate;
     157   [ #  #  #  # ]:          0 :         if (local->rx_led.name && led_trigger_register(&local->rx_led)) {
     158                 :          0 :                 kfree(local->rx_led.name);
     159                 :          0 :                 local->rx_led.name = NULL;
     160                 :            :         }
     161                 :            : 
     162                 :          0 :         atomic_set(&local->tx_led_active, 0);
     163                 :          0 :         local->tx_led.activate = ieee80211_tx_led_activate;
     164                 :          0 :         local->tx_led.deactivate = ieee80211_tx_led_deactivate;
     165   [ #  #  #  # ]:          0 :         if (local->tx_led.name && led_trigger_register(&local->tx_led)) {
     166                 :          0 :                 kfree(local->tx_led.name);
     167                 :          0 :                 local->tx_led.name = NULL;
     168                 :            :         }
     169                 :            : 
     170                 :          0 :         atomic_set(&local->assoc_led_active, 0);
     171                 :          0 :         local->assoc_led.activate = ieee80211_assoc_led_activate;
     172                 :          0 :         local->assoc_led.deactivate = ieee80211_assoc_led_deactivate;
     173   [ #  #  #  # ]:          0 :         if (local->assoc_led.name && led_trigger_register(&local->assoc_led)) {
     174                 :          0 :                 kfree(local->assoc_led.name);
     175                 :          0 :                 local->assoc_led.name = NULL;
     176                 :            :         }
     177                 :            : 
     178                 :          0 :         atomic_set(&local->radio_led_active, 0);
     179                 :          0 :         local->radio_led.activate = ieee80211_radio_led_activate;
     180                 :          0 :         local->radio_led.deactivate = ieee80211_radio_led_deactivate;
     181   [ #  #  #  # ]:          0 :         if (local->radio_led.name && led_trigger_register(&local->radio_led)) {
     182                 :          0 :                 kfree(local->radio_led.name);
     183                 :          0 :                 local->radio_led.name = NULL;
     184                 :            :         }
     185                 :            : 
     186                 :          0 :         atomic_set(&local->tpt_led_active, 0);
     187         [ #  # ]:          0 :         if (local->tpt_led_trigger) {
     188                 :          0 :                 local->tpt_led.activate = ieee80211_tpt_led_activate;
     189                 :          0 :                 local->tpt_led.deactivate = ieee80211_tpt_led_deactivate;
     190         [ #  # ]:          0 :                 if (led_trigger_register(&local->tpt_led)) {
     191                 :          0 :                         kfree(local->tpt_led_trigger);
     192                 :          0 :                         local->tpt_led_trigger = NULL;
     193                 :            :                 }
     194                 :            :         }
     195                 :          0 : }
     196                 :            : 
     197                 :          0 : void ieee80211_led_exit(struct ieee80211_local *local)
     198                 :            : {
     199         [ #  # ]:          0 :         if (local->radio_led.name)
     200                 :          0 :                 led_trigger_unregister(&local->radio_led);
     201         [ #  # ]:          0 :         if (local->assoc_led.name)
     202                 :          0 :                 led_trigger_unregister(&local->assoc_led);
     203         [ #  # ]:          0 :         if (local->tx_led.name)
     204                 :          0 :                 led_trigger_unregister(&local->tx_led);
     205         [ #  # ]:          0 :         if (local->rx_led.name)
     206                 :          0 :                 led_trigger_unregister(&local->rx_led);
     207                 :            : 
     208         [ #  # ]:          0 :         if (local->tpt_led_trigger) {
     209                 :          0 :                 led_trigger_unregister(&local->tpt_led);
     210                 :          0 :                 kfree(local->tpt_led_trigger);
     211                 :            :         }
     212                 :          0 : }
     213                 :            : 
     214                 :          0 : const char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
     215                 :            : {
     216                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
     217                 :            : 
     218                 :          0 :         return local->radio_led.name;
     219                 :            : }
     220                 :            : EXPORT_SYMBOL(__ieee80211_get_radio_led_name);
     221                 :            : 
     222                 :          0 : const char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
     223                 :            : {
     224                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
     225                 :            : 
     226                 :          0 :         return local->assoc_led.name;
     227                 :            : }
     228                 :            : EXPORT_SYMBOL(__ieee80211_get_assoc_led_name);
     229                 :            : 
     230                 :          0 : const char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
     231                 :            : {
     232                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
     233                 :            : 
     234                 :          0 :         return local->tx_led.name;
     235                 :            : }
     236                 :            : EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
     237                 :            : 
     238                 :          0 : const char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
     239                 :            : {
     240                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
     241                 :            : 
     242                 :          0 :         return local->rx_led.name;
     243                 :            : }
     244                 :            : EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
     245                 :            : 
     246                 :          0 : static unsigned long tpt_trig_traffic(struct ieee80211_local *local,
     247                 :            :                                       struct tpt_led_trigger *tpt_trig)
     248                 :            : {
     249                 :          0 :         unsigned long traffic, delta;
     250                 :            : 
     251                 :          0 :         traffic = tpt_trig->tx_bytes + tpt_trig->rx_bytes;
     252                 :            : 
     253                 :          0 :         delta = traffic - tpt_trig->prev_traffic;
     254                 :          0 :         tpt_trig->prev_traffic = traffic;
     255                 :          0 :         return DIV_ROUND_UP(delta, 1024 / 8);
     256                 :            : }
     257                 :            : 
     258                 :          0 : static void tpt_trig_timer(struct timer_list *t)
     259                 :            : {
     260                 :          0 :         struct tpt_led_trigger *tpt_trig = from_timer(tpt_trig, t, timer);
     261                 :          0 :         struct ieee80211_local *local = tpt_trig->local;
     262                 :          0 :         struct led_classdev *led_cdev;
     263                 :          0 :         unsigned long on, off, tpt;
     264                 :          0 :         int i;
     265                 :            : 
     266         [ #  # ]:          0 :         if (!tpt_trig->running)
     267                 :          0 :                 return;
     268                 :            : 
     269                 :          0 :         mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ));
     270                 :            : 
     271                 :          0 :         tpt = tpt_trig_traffic(local, tpt_trig);
     272                 :            : 
     273                 :            :         /* default to just solid on */
     274                 :          0 :         on = 1;
     275                 :          0 :         off = 0;
     276                 :            : 
     277         [ #  # ]:          0 :         for (i = tpt_trig->blink_table_len - 1; i >= 0; i--) {
     278         [ #  # ]:          0 :                 if (tpt_trig->blink_table[i].throughput < 0 ||
     279         [ #  # ]:          0 :                     tpt > tpt_trig->blink_table[i].throughput) {
     280                 :          0 :                         off = tpt_trig->blink_table[i].blink_time / 2;
     281                 :          0 :                         on = tpt_trig->blink_table[i].blink_time - off;
     282                 :          0 :                         break;
     283                 :            :                 }
     284                 :            :         }
     285                 :            : 
     286                 :          0 :         read_lock(&local->tpt_led.leddev_list_lock);
     287         [ #  # ]:          0 :         list_for_each_entry(led_cdev, &local->tpt_led.led_cdevs, trig_list)
     288                 :          0 :                 led_blink_set(led_cdev, &on, &off);
     289                 :          0 :         read_unlock(&local->tpt_led.leddev_list_lock);
     290                 :            : }
     291                 :            : 
     292                 :            : const char *
     293                 :          0 : __ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw,
     294                 :            :                                    unsigned int flags,
     295                 :            :                                    const struct ieee80211_tpt_blink *blink_table,
     296                 :            :                                    unsigned int blink_table_len)
     297                 :            : {
     298         [ #  # ]:          0 :         struct ieee80211_local *local = hw_to_local(hw);
     299                 :          0 :         struct tpt_led_trigger *tpt_trig;
     300                 :            : 
     301   [ #  #  #  # ]:          0 :         if (WARN_ON(local->tpt_led_trigger))
     302                 :            :                 return NULL;
     303                 :            : 
     304                 :          0 :         tpt_trig = kzalloc(sizeof(struct tpt_led_trigger), GFP_KERNEL);
     305         [ #  # ]:          0 :         if (!tpt_trig)
     306                 :            :                 return NULL;
     307                 :            : 
     308                 :          0 :         snprintf(tpt_trig->name, sizeof(tpt_trig->name),
     309         [ #  # ]:          0 :                  "%stpt", wiphy_name(local->hw.wiphy));
     310                 :            : 
     311                 :          0 :         local->tpt_led.name = tpt_trig->name;
     312                 :            : 
     313                 :          0 :         tpt_trig->blink_table = blink_table;
     314                 :          0 :         tpt_trig->blink_table_len = blink_table_len;
     315                 :          0 :         tpt_trig->want = flags;
     316                 :          0 :         tpt_trig->local = local;
     317                 :            : 
     318                 :          0 :         timer_setup(&tpt_trig->timer, tpt_trig_timer, 0);
     319                 :            : 
     320                 :          0 :         local->tpt_led_trigger = tpt_trig;
     321                 :            : 
     322                 :          0 :         return tpt_trig->name;
     323                 :            : }
     324                 :            : EXPORT_SYMBOL(__ieee80211_create_tpt_led_trigger);
     325                 :            : 
     326                 :            : static void ieee80211_start_tpt_led_trig(struct ieee80211_local *local)
     327                 :            : {
     328                 :            :         struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
     329                 :            : 
     330                 :            :         if (tpt_trig->running)
     331                 :            :                 return;
     332                 :            : 
     333                 :            :         /* reset traffic */
     334                 :            :         tpt_trig_traffic(local, tpt_trig);
     335                 :            :         tpt_trig->running = true;
     336                 :            : 
     337                 :            :         tpt_trig_timer(&tpt_trig->timer);
     338                 :            :         mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ));
     339                 :            : }
     340                 :            : 
     341                 :          0 : static void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local)
     342                 :            : {
     343                 :          0 :         struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
     344                 :          0 :         struct led_classdev *led_cdev;
     345                 :            : 
     346         [ #  # ]:          0 :         if (!tpt_trig->running)
     347                 :            :                 return;
     348                 :            : 
     349                 :          0 :         tpt_trig->running = false;
     350                 :          0 :         del_timer_sync(&tpt_trig->timer);
     351                 :            : 
     352                 :          0 :         read_lock(&local->tpt_led.leddev_list_lock);
     353         [ #  # ]:          0 :         list_for_each_entry(led_cdev, &local->tpt_led.led_cdevs, trig_list)
     354                 :          0 :                 led_set_brightness(led_cdev, LED_OFF);
     355                 :          0 :         read_unlock(&local->tpt_led.leddev_list_lock);
     356                 :            : }
     357                 :            : 
     358                 :          0 : void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
     359                 :            :                                 unsigned int types_on, unsigned int types_off)
     360                 :            : {
     361                 :          0 :         struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
     362                 :          0 :         bool allowed;
     363                 :            : 
     364         [ #  # ]:          0 :         WARN_ON(types_on & types_off);
     365                 :            : 
     366         [ #  # ]:          0 :         if (!tpt_trig)
     367                 :            :                 return;
     368                 :            : 
     369                 :          0 :         tpt_trig->active &= ~types_off;
     370                 :          0 :         tpt_trig->active |= types_on;
     371                 :            : 
     372                 :            :         /*
     373                 :            :          * Regardless of wanted state, we shouldn't blink when
     374                 :            :          * the radio is disabled -- this can happen due to some
     375                 :            :          * code ordering issues with __ieee80211_recalc_idle()
     376                 :            :          * being called before the radio is started.
     377                 :            :          */
     378                 :          0 :         allowed = tpt_trig->active & IEEE80211_TPT_LEDTRIG_FL_RADIO;
     379                 :            : 
     380   [ #  #  #  # ]:          0 :         if (!allowed || !(tpt_trig->active & tpt_trig->want))
     381                 :          0 :                 ieee80211_stop_tpt_led_trig(local);
     382                 :            :         else
     383                 :          0 :                 ieee80211_start_tpt_led_trig(local);
     384                 :            : }

Generated by: LCOV version 1.14