Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.6-rc3 278 lines 8.3 kB view raw
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 */ 37void 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 */ 49void 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 */ 62int 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 */ 79void 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 */ 91void 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 */ 105void 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 */ 128static 129unsigned 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 */ 189static 190void 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 */ 214static 215int 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; 231error: 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 */ 259int 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}