root/drivers/staging/uwb/drp-avail.c

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

DEFINITIONS

This source file includes following definitions.
  1. uwb_drp_avail_init
  2. uwb_drp_available
  3. uwb_drp_avail_reserve_pending
  4. uwb_drp_avail_reserve
  5. uwb_drp_avail_release
  6. uwb_drp_avail_ie_update
  7. get_val
  8. buffer_to_bmp
  9. uwbd_evt_get_drp_avail
  10. uwbd_evt_handle_rc_drp_avail

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Ultra Wide Band
   4  * DRP availability management
   5  *
   6  * Copyright (C) 2005-2006 Intel Corporation
   7  * Reinette Chatre <reinette.chatre@intel.com>
   8  * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
   9  *
  10  * Manage DRP Availability (the MAS available for DRP
  11  * reservations). Thus:
  12  *
  13  * - Handle DRP Availability Change notifications
  14  *
  15  * - Allow the reservation manager to indicate MAS reserved/released
  16  *   by local (owned by/targeted at the radio controller)
  17  *   reservations.
  18  *
  19  * - Based on the two sources above, generate a DRP Availability IE to
  20  *   be included in the beacon.
  21  *
  22  * See also the documentation for struct uwb_drp_avail.
  23  */
  24 
  25 #include <linux/errno.h>
  26 #include <linux/module.h>
  27 #include <linux/device.h>
  28 #include <linux/bitmap.h>
  29 #include "uwb-internal.h"
  30 
  31 /**
  32  * uwb_drp_avail_init - initialize an RC's MAS availability
  33  *
  34  * All MAS are available initially.  The RC will inform use which
  35  * slots are used for the BP (it may change in size).
  36  */
  37 void uwb_drp_avail_init(struct uwb_rc *rc)
  38 {
  39         bitmap_fill(rc->drp_avail.global, UWB_NUM_MAS);
  40         bitmap_fill(rc->drp_avail.local, UWB_NUM_MAS);
  41         bitmap_fill(rc->drp_avail.pending, UWB_NUM_MAS);
  42 }
  43 
  44 /*
  45  * Determine MAS available for new local reservations.
  46  *
  47  * avail = global & local & pending
  48  */
  49 void uwb_drp_available(struct uwb_rc *rc, struct uwb_mas_bm *avail)
  50 {
  51         bitmap_and(avail->bm, rc->drp_avail.global, rc->drp_avail.local, UWB_NUM_MAS);
  52         bitmap_and(avail->bm, avail->bm, rc->drp_avail.pending, UWB_NUM_MAS);
  53 }
  54 
  55 /**
  56  * uwb_drp_avail_reserve_pending - reserve MAS for a new reservation
  57  * @rc: the radio controller
  58  * @mas: the MAS to reserve
  59  *
  60  * Returns 0 on success, or -EBUSY if the MAS requested aren't available.
  61  */
  62 int uwb_drp_avail_reserve_pending(struct uwb_rc *rc, struct uwb_mas_bm *mas)
  63 {
  64         struct uwb_mas_bm avail;
  65 
  66         uwb_drp_available(rc, &avail);
  67         if (!bitmap_subset(mas->bm, avail.bm, UWB_NUM_MAS))
  68                 return -EBUSY;
  69 
  70         bitmap_andnot(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS);
  71         return 0;
  72 }
  73 
  74 /**
  75  * uwb_drp_avail_reserve - reserve MAS for an established reservation
  76  * @rc: the radio controller
  77  * @mas: the MAS to reserve
  78  */
  79 void uwb_drp_avail_reserve(struct uwb_rc *rc, struct uwb_mas_bm *mas)
  80 {
  81         bitmap_or(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS);
  82         bitmap_andnot(rc->drp_avail.local, rc->drp_avail.local, mas->bm, UWB_NUM_MAS);
  83         rc->drp_avail.ie_valid = false;
  84 }
  85 
  86 /**
  87  * uwb_drp_avail_release - release MAS from a pending or established reservation
  88  * @rc: the radio controller
  89  * @mas: the MAS to release
  90  */
  91 void uwb_drp_avail_release(struct uwb_rc *rc, struct uwb_mas_bm *mas)
  92 {
  93         bitmap_or(rc->drp_avail.local, rc->drp_avail.local, mas->bm, UWB_NUM_MAS);
  94         bitmap_or(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS);
  95         rc->drp_avail.ie_valid = false;
  96         uwb_rsv_handle_drp_avail_change(rc);
  97 }
  98 
  99 /**
 100  * uwb_drp_avail_ie_update - update the DRP Availability IE
 101  * @rc: the radio controller
 102  *
 103  * avail = global & local
 104  */
 105 void uwb_drp_avail_ie_update(struct uwb_rc *rc)
 106 {
 107         struct uwb_mas_bm avail;
 108 
 109         bitmap_and(avail.bm, rc->drp_avail.global, rc->drp_avail.local, UWB_NUM_MAS);
 110 
 111         rc->drp_avail.ie.hdr.element_id = UWB_IE_DRP_AVAILABILITY;
 112         rc->drp_avail.ie.hdr.length = UWB_NUM_MAS / 8;
 113         uwb_mas_bm_copy_le(rc->drp_avail.ie.bmp, &avail);
 114         rc->drp_avail.ie_valid = true;
 115 }
 116 
 117 /**
 118  * Create an unsigned long from a buffer containing a byte stream.
 119  *
 120  * @array: pointer to buffer
 121  * @itr:   index of buffer from where we start
 122  * @len:   the buffer's remaining size may not be exact multiple of
 123  *         sizeof(unsigned long), @len is the length of buffer that needs
 124  *         to be converted. This will be sizeof(unsigned long) or smaller
 125  *         (BUG if not). If it is smaller then we will pad the remaining
 126  *         space of the result with zeroes.
 127  */
 128 static
 129 unsigned long get_val(u8 *array, size_t itr, size_t len)
 130 {
 131         unsigned long val = 0;
 132         size_t top = itr + len;
 133 
 134         BUG_ON(len > sizeof(val));
 135 
 136         while (itr < top) {
 137                 val <<= 8;
 138                 val |= array[top - 1];
 139                 top--;
 140         }
 141         val <<= 8 * (sizeof(val) - len); /* padding */
 142         return val;
 143 }
 144 
 145 /**
 146  * Initialize bitmap from data buffer.
 147  *
 148  * The bitmap to be converted could come from a IE, for example a
 149  * DRP Availability IE.
 150  * From ECMA-368 1.0 [16.8.7]: "
 151  * octets: 1            1               N * (0 to 32)
 152  *         Element ID   Length (=N)     DRP Availability Bitmap
 153  *
 154  * The DRP Availability Bitmap field is up to 256 bits long, one
 155  * bit for each MAS in the superframe, where the least-significant
 156  * bit of the field corresponds to the first MAS in the superframe
 157  * and successive bits correspond to successive MASs."
 158  *
 159  * The DRP Availability bitmap is in octets from 0 to 32, so octet
 160  * 32 contains bits for MAS 1-8, etc. If the bitmap is smaller than 32
 161  * octets, the bits in octets not included at the end of the bitmap are
 162  * treated as zero. In this case (when the bitmap is smaller than 32
 163  * octets) the MAS represented range from MAS 1 to MAS (size of bitmap)
 164  * with the last octet still containing bits for MAS 1-8, etc.
 165  *
 166  * For example:
 167  * F00F0102 03040506 0708090A 0B0C0D0E 0F010203
 168  * ^^^^
 169  * ||||
 170  * ||||
 171  * |||\LSB of byte is MAS 9
 172  * ||\MSB of byte is MAS 16
 173  * |\LSB of first byte is MAS 1
 174  * \ MSB of byte is MAS 8
 175  *
 176  * An example of this encoding can be found in ECMA-368 Annex-D [Table D.11]
 177  *
 178  * The resulting bitmap will have the following mapping:
 179  *      bit position 0 == MAS 1
 180  *      bit position 1 == MAS 2
 181  *      ...
 182  *      bit position (UWB_NUM_MAS - 1) == MAS UWB_NUM_MAS
 183  *
 184  * @bmp_itr:    pointer to bitmap (can be declared with DECLARE_BITMAP)
 185  * @buffer:     pointer to buffer containing bitmap data in big endian
 186  *              format (MSB first)
 187  * @buffer_size:number of bytes with which bitmap should be initialized
 188  */
 189 static
 190 void buffer_to_bmp(unsigned long *bmp_itr, void *_buffer,
 191                    size_t buffer_size)
 192 {
 193         u8 *buffer = _buffer;
 194         size_t itr, len;
 195         unsigned long val;
 196 
 197         itr = 0;
 198         while (itr < buffer_size) {
 199                 len = buffer_size - itr >= sizeof(val) ?
 200                         sizeof(val) : buffer_size - itr;
 201                 val = get_val(buffer, itr, len);
 202                 bmp_itr[itr / sizeof(val)] = val;
 203                 itr += sizeof(val);
 204         }
 205 }
 206 
 207 
 208 /**
 209  * Extract DRP Availability bitmap from the notification.
 210  *
 211  * The notification that comes in contains a bitmap of (UWB_NUM_MAS / 8) bytes
 212  * We convert that to our internal representation.
 213  */
 214 static
 215 int uwbd_evt_get_drp_avail(struct uwb_event *evt, unsigned long *bmp)
 216 {
 217         struct device *dev = &evt->rc->uwb_dev.dev;
 218         struct uwb_rc_evt_drp_avail *drp_evt;
 219         int result = -EINVAL;
 220 
 221         /* Is there enough data to decode the event? */
 222         if (evt->notif.size < sizeof(*drp_evt)) {
 223                 dev_err(dev, "DRP Availability Change: Not enough "
 224                         "data to decode event [%zu bytes, %zu "
 225                         "needed]\n", evt->notif.size, sizeof(*drp_evt));
 226                 goto error;
 227         }
 228         drp_evt = container_of(evt->notif.rceb, struct uwb_rc_evt_drp_avail, rceb);
 229         buffer_to_bmp(bmp, drp_evt->bmp, UWB_NUM_MAS/8);
 230         result = 0;
 231 error:
 232         return result;
 233 }
 234 
 235 
 236 /**
 237  * Process an incoming DRP Availability notification.
 238  *
 239  * @evt:        Event information (packs the actual event data, which
 240  *              radio controller it came to, etc).
 241  *
 242  * @returns:    0 on success (so uwbd() frees the event buffer), < 0
 243  *              on error.
 244  *
 245  * According to ECMA-368 1.0 [16.8.7], bits set to ONE indicate that
 246  * the MAS slot is available, bits set to ZERO indicate that the slot
 247  * is busy.
 248  *
 249  * So we clear available slots, we set used slots :)
 250  *
 251  * The notification only marks non-availability based on the BP and
 252  * received DRP IEs that are not for this radio controller.  A copy of
 253  * this bitmap is needed to generate the real availability (which
 254  * includes local and pending reservations).
 255  *
 256  * The DRP Availability IE that this radio controller emits will need
 257  * to be updated.
 258  */
 259 int uwbd_evt_handle_rc_drp_avail(struct uwb_event *evt)
 260 {
 261         int result;
 262         struct uwb_rc *rc = evt->rc;
 263         DECLARE_BITMAP(bmp, UWB_NUM_MAS);
 264 
 265         result = uwbd_evt_get_drp_avail(evt, bmp);
 266         if (result < 0)
 267                 return result;
 268 
 269         mutex_lock(&rc->rsvs_mutex);
 270         bitmap_copy(rc->drp_avail.global, bmp, UWB_NUM_MAS);
 271         rc->drp_avail.ie_valid = false;
 272         uwb_rsv_handle_drp_avail_change(rc);
 273         mutex_unlock(&rc->rsvs_mutex);
 274 
 275         uwb_rsv_sched_update(rc);
 276 
 277         return 0;
 278 }

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