Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
drp-avail.c
Go to the documentation of this file.
1 /*
2  * Ultra Wide Band
3  * DRP availability management
4  *
5  * Copyright (C) 2005-2006 Intel Corporation
6  * Reinette Chatre <[email protected]>
7  * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License version
11  * 2 as published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  *
21  *
22  * Manage DRP Availability (the MAS available for DRP
23  * reservations). Thus:
24  *
25  * - Handle DRP Availability Change notifications
26  *
27  * - Allow the reservation manager to indicate MAS reserved/released
28  * by local (owned by/targeted at the radio controller)
29  * reservations.
30  *
31  * - Based on the two sources above, generate a DRP Availability IE to
32  * be included in the beacon.
33  *
34  * See also the documentation for struct uwb_drp_avail.
35  */
36 
37 #include <linux/errno.h>
38 #include <linux/module.h>
39 #include <linux/device.h>
40 #include <linux/bitmap.h>
41 #include "uwb-internal.h"
42 
50 {
51  bitmap_fill(rc->drp_avail.global, UWB_NUM_MAS);
52  bitmap_fill(rc->drp_avail.local, UWB_NUM_MAS);
53  bitmap_fill(rc->drp_avail.pending, UWB_NUM_MAS);
54 }
55 
56 /*
57  * Determine MAS available for new local reservations.
58  *
59  * avail = global & local & pending
60  */
61 void uwb_drp_available(struct uwb_rc *rc, struct uwb_mas_bm *avail)
62 {
63  bitmap_and(avail->bm, rc->drp_avail.global, rc->drp_avail.local, UWB_NUM_MAS);
64  bitmap_and(avail->bm, avail->bm, rc->drp_avail.pending, UWB_NUM_MAS);
65 }
66 
75 {
76  struct uwb_mas_bm avail;
77 
78  uwb_drp_available(rc, &avail);
79  if (!bitmap_subset(mas->bm, avail.bm, UWB_NUM_MAS))
80  return -EBUSY;
81 
82  bitmap_andnot(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS);
83  return 0;
84 }
85 
91 void uwb_drp_avail_reserve(struct uwb_rc *rc, struct uwb_mas_bm *mas)
92 {
93  bitmap_or(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS);
94  bitmap_andnot(rc->drp_avail.local, rc->drp_avail.local, mas->bm, UWB_NUM_MAS);
95  rc->drp_avail.ie_valid = false;
96 }
97 
103 void uwb_drp_avail_release(struct uwb_rc *rc, struct uwb_mas_bm *mas)
104 {
105  bitmap_or(rc->drp_avail.local, rc->drp_avail.local, mas->bm, UWB_NUM_MAS);
106  bitmap_or(rc->drp_avail.pending, rc->drp_avail.pending, mas->bm, UWB_NUM_MAS);
107  rc->drp_avail.ie_valid = false;
109 }
110 
118 {
119  struct uwb_mas_bm avail;
120 
121  bitmap_and(avail.bm, rc->drp_avail.global, rc->drp_avail.local, UWB_NUM_MAS);
122 
123  rc->drp_avail.ie.hdr.element_id = UWB_IE_DRP_AVAILABILITY;
124  rc->drp_avail.ie.hdr.length = UWB_NUM_MAS / 8;
125  uwb_mas_bm_copy_le(rc->drp_avail.ie.bmp, &avail);
126  rc->drp_avail.ie_valid = true;
127 }
128 
140 static
141 unsigned long get_val(u8 *array, size_t itr, size_t len)
142 {
143  unsigned long val = 0;
144  size_t top = itr + len;
145 
146  BUG_ON(len > sizeof(val));
147 
148  while (itr < top) {
149  val <<= 8;
150  val |= array[top - 1];
151  top--;
152  }
153  val <<= 8 * (sizeof(val) - len); /* padding */
154  return val;
155 }
156 
201 static
202 void buffer_to_bmp(unsigned long *bmp_itr, void *_buffer,
203  size_t buffer_size)
204 {
205  u8 *buffer = _buffer;
206  size_t itr, len;
207  unsigned long val;
208 
209  itr = 0;
210  while (itr < buffer_size) {
211  len = buffer_size - itr >= sizeof(val) ?
212  sizeof(val) : buffer_size - itr;
213  val = get_val(buffer, itr, len);
214  bmp_itr[itr / sizeof(val)] = val;
215  itr += sizeof(val);
216  }
217 }
218 
219 
226 static
227 int uwbd_evt_get_drp_avail(struct uwb_event *evt, unsigned long *bmp)
228 {
229  struct device *dev = &evt->rc->uwb_dev.dev;
230  struct uwb_rc_evt_drp_avail *drp_evt;
231  int result = -EINVAL;
232 
233  /* Is there enough data to decode the event? */
234  if (evt->notif.size < sizeof(*drp_evt)) {
235  dev_err(dev, "DRP Availability Change: Not enough "
236  "data to decode event [%zu bytes, %zu "
237  "needed]\n", evt->notif.size, sizeof(*drp_evt));
238  goto error;
239  }
240  drp_evt = container_of(evt->notif.rceb, struct uwb_rc_evt_drp_avail, rceb);
241  buffer_to_bmp(bmp, drp_evt->bmp, UWB_NUM_MAS/8);
242  result = 0;
243 error:
244  return result;
245 }
246 
247 
272 {
273  int result;
274  struct uwb_rc *rc = evt->rc;
276 
277  result = uwbd_evt_get_drp_avail(evt, bmp);
278  if (result < 0)
279  return result;
280 
281  mutex_lock(&rc->rsvs_mutex);
282  bitmap_copy(rc->drp_avail.global, bmp, UWB_NUM_MAS);
283  rc->drp_avail.ie_valid = false;
285  mutex_unlock(&rc->rsvs_mutex);
286 
288 
289  return 0;
290 }