root/drivers/staging/uwb/radio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. uwb_radio_select_channel
  2. uwb_radio_channel_changed
  3. uwb_radio_change_channel
  4. uwb_radio_start
  5. uwb_radio_stop
  6. uwb_radio_force_channel
  7. uwb_radio_setup
  8. uwb_radio_reset_state
  9. uwb_radio_shutdown

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * UWB radio (channel) management.
   4  *
   5  * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
   6  */
   7 #include <linux/kernel.h>
   8 #include <linux/export.h>
   9 
  10 #include "uwb.h"
  11 #include "uwb-internal.h"
  12 
  13 
  14 static int uwb_radio_select_channel(struct uwb_rc *rc)
  15 {
  16         /*
  17          * Default to channel 9 (BG1, TFC1) unless the user has
  18          * selected a specific channel or there are no active PALs.
  19          */
  20         if (rc->active_pals == 0)
  21                 return -1;
  22         if (rc->beaconing_forced)
  23                 return rc->beaconing_forced;
  24         return 9;
  25 }
  26 
  27 
  28 /*
  29  * Notify all active PALs that the channel has changed.
  30  */
  31 static void uwb_radio_channel_changed(struct uwb_rc *rc, int channel)
  32 {
  33         struct uwb_pal *pal;
  34 
  35         list_for_each_entry(pal, &rc->pals, node) {
  36                 if (pal->channel && channel != pal->channel) {
  37                         pal->channel = channel;
  38                         if (pal->channel_changed)
  39                                 pal->channel_changed(pal, pal->channel);
  40                 }
  41         }
  42 }
  43 
  44 /*
  45  * Change to a new channel and notify any active PALs of the new
  46  * channel.
  47  *
  48  * When stopping the radio, PALs need to be notified first so they can
  49  * terminate any active reservations.
  50  */
  51 static int uwb_radio_change_channel(struct uwb_rc *rc, int channel)
  52 {
  53         int ret = 0;
  54         struct device *dev = &rc->uwb_dev.dev;
  55 
  56         dev_dbg(dev, "%s: channel = %d, rc->beaconing = %d\n", __func__,
  57                 channel, rc->beaconing);
  58 
  59         if (channel == -1)
  60                 uwb_radio_channel_changed(rc, channel);
  61 
  62         if (channel != rc->beaconing) {
  63                 if (rc->beaconing != -1 && channel != -1) {
  64                         /*
  65                          * FIXME: should signal the channel change
  66                          * with a Channel Change IE.
  67                          */
  68                         ret = uwb_radio_change_channel(rc, -1);
  69                         if (ret < 0)
  70                                 return ret;
  71                 }
  72                 ret = uwb_rc_beacon(rc, channel, 0);
  73         }
  74 
  75         if (channel != -1)
  76                 uwb_radio_channel_changed(rc, rc->beaconing);
  77 
  78         return ret;
  79 }
  80 
  81 /**
  82  * uwb_radio_start - request that the radio be started
  83  * @pal: the PAL making the request.
  84  *
  85  * If the radio is not already active, a suitable channel is selected
  86  * and beacons are started.
  87  */
  88 int uwb_radio_start(struct uwb_pal *pal)
  89 {
  90         struct uwb_rc *rc = pal->rc;
  91         int ret = 0;
  92 
  93         mutex_lock(&rc->uwb_dev.mutex);
  94 
  95         if (!pal->channel) {
  96                 pal->channel = -1;
  97                 rc->active_pals++;
  98                 ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc));
  99         }
 100 
 101         mutex_unlock(&rc->uwb_dev.mutex);
 102         return ret;
 103 }
 104 EXPORT_SYMBOL_GPL(uwb_radio_start);
 105 
 106 /**
 107  * uwb_radio_stop - request that the radio be stopped.
 108  * @pal: the PAL making the request.
 109  *
 110  * Stops the radio if no other PAL is making use of it.
 111  */
 112 void uwb_radio_stop(struct uwb_pal *pal)
 113 {
 114         struct uwb_rc *rc = pal->rc;
 115 
 116         mutex_lock(&rc->uwb_dev.mutex);
 117 
 118         if (pal->channel) {
 119                 rc->active_pals--;
 120                 uwb_radio_change_channel(rc, uwb_radio_select_channel(rc));
 121                 pal->channel = 0;
 122         }
 123 
 124         mutex_unlock(&rc->uwb_dev.mutex);
 125 }
 126 EXPORT_SYMBOL_GPL(uwb_radio_stop);
 127 
 128 /*
 129  * uwb_radio_force_channel - force a specific channel to be used
 130  * @rc: the radio controller.
 131  * @channel: the channel to use; -1 to force the radio to stop; 0 to
 132  *   use the default channel selection algorithm.
 133  */
 134 int uwb_radio_force_channel(struct uwb_rc *rc, int channel)
 135 {
 136         int ret = 0;
 137 
 138         mutex_lock(&rc->uwb_dev.mutex);
 139 
 140         rc->beaconing_forced = channel;
 141         ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc));
 142 
 143         mutex_unlock(&rc->uwb_dev.mutex);
 144         return ret;
 145 }
 146 
 147 /*
 148  * uwb_radio_setup - setup the radio manager
 149  * @rc: the radio controller.
 150  *
 151  * The radio controller is reset to ensure it's in a known state
 152  * before it's used.
 153  */
 154 int uwb_radio_setup(struct uwb_rc *rc)
 155 {
 156         return uwb_rc_reset(rc);
 157 }
 158 
 159 /*
 160  * uwb_radio_reset_state - reset any radio manager state
 161  * @rc: the radio controller.
 162  *
 163  * All internal radio manager state is reset to values corresponding
 164  * to a reset radio controller.
 165  */
 166 void uwb_radio_reset_state(struct uwb_rc *rc)
 167 {
 168         struct uwb_pal *pal;
 169 
 170         mutex_lock(&rc->uwb_dev.mutex);
 171 
 172         list_for_each_entry(pal, &rc->pals, node) {
 173                 if (pal->channel) {
 174                         pal->channel = -1;
 175                         if (pal->channel_changed)
 176                                 pal->channel_changed(pal, -1);
 177                 }
 178         }
 179 
 180         rc->beaconing = -1;
 181         rc->scanning = -1;
 182 
 183         mutex_unlock(&rc->uwb_dev.mutex);
 184 }
 185 
 186 /*
 187  * uwb_radio_shutdown - shutdown the radio manager
 188  * @rc: the radio controller.
 189  *
 190  * The radio controller is reset.
 191  */
 192 void uwb_radio_shutdown(struct uwb_rc *rc)
 193 {
 194         uwb_radio_reset_state(rc);
 195         uwb_rc_reset(rc);
 196 }

/* [<][>][^][v][top][bottom][index][help] */