~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/uwb/drp-avail.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Ultra Wide Band
 
3
 * DRP availability management
 
4
 *
 
5
 * Copyright (C) 2005-2006 Intel Corporation
 
6
 * Reinette Chatre <reinette.chatre@intel.com>
 
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
 
 
43
/**
 
44
 * uwb_drp_avail_init - initialize an RC's MAS availability
 
45
 *
 
46
 * All MAS are available initially.  The RC will inform use which
 
47
 * slots are used for the BP (it may change in size).
 
48
 */
 
49
void uwb_drp_avail_init(struct uwb_rc *rc)
 
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
 
 
67
/**
 
68
 * uwb_drp_avail_reserve_pending - reserve MAS for a new reservation
 
69
 * @rc: the radio controller
 
70
 * @mas: the MAS to reserve
 
71
 *
 
72
 * Returns 0 on success, or -EBUSY if the MAS requested aren't available.
 
73
 */
 
74
int uwb_drp_avail_reserve_pending(struct uwb_rc *rc, struct uwb_mas_bm *mas)
 
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
 
 
86
/**
 
87
 * uwb_drp_avail_reserve - reserve MAS for an established reservation
 
88
 * @rc: the radio controller
 
89
 * @mas: the MAS to reserve
 
90
 */
 
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
 
 
98
/**
 
99
 * uwb_drp_avail_release - release MAS from a pending or established reservation
 
100
 * @rc: the radio controller
 
101
 * @mas: the MAS to release
 
102
 */
 
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;
 
108
        uwb_rsv_handle_drp_avail_change(rc);
 
109
}
 
110
 
 
111
/**
 
112
 * uwb_drp_avail_ie_update - update the DRP Availability IE
 
113
 * @rc: the radio controller
 
114
 *
 
115
 * avail = global & local
 
116
 */
 
117
void uwb_drp_avail_ie_update(struct uwb_rc *rc)
 
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
 
 
129
/**
 
130
 * Create an unsigned long from a buffer containing a byte stream.
 
131
 *
 
132
 * @array: pointer to buffer
 
133
 * @itr:   index of buffer from where we start
 
134
 * @len:   the buffer's remaining size may not be exact multiple of
 
135
 *         sizeof(unsigned long), @len is the length of buffer that needs
 
136
 *         to be converted. This will be sizeof(unsigned long) or smaller
 
137
 *         (BUG if not). If it is smaller then we will pad the remaining
 
138
 *         space of the result with zeroes.
 
139
 */
 
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
 
 
157
/**
 
158
 * Initialize bitmap from data buffer.
 
159
 *
 
160
 * The bitmap to be converted could come from a IE, for example a
 
161
 * DRP Availability IE.
 
162
 * From ECMA-368 1.0 [16.8.7]: "
 
163
 * octets: 1            1               N * (0 to 32)
 
164
 *         Element ID   Length (=N)     DRP Availability Bitmap
 
165
 *
 
166
 * The DRP Availability Bitmap field is up to 256 bits long, one
 
167
 * bit for each MAS in the superframe, where the least-significant
 
168
 * bit of the field corresponds to the first MAS in the superframe
 
169
 * and successive bits correspond to successive MASs."
 
170
 *
 
171
 * The DRP Availability bitmap is in octets from 0 to 32, so octet
 
172
 * 32 contains bits for MAS 1-8, etc. If the bitmap is smaller than 32
 
173
 * octets, the bits in octets not included at the end of the bitmap are
 
174
 * treated as zero. In this case (when the bitmap is smaller than 32
 
175
 * octets) the MAS represented range from MAS 1 to MAS (size of bitmap)
 
176
 * with the last octet still containing bits for MAS 1-8, etc.
 
177
 *
 
178
 * For example:
 
179
 * F00F0102 03040506 0708090A 0B0C0D0E 0F010203
 
180
 * ^^^^
 
181
 * ||||
 
182
 * ||||
 
183
 * |||\LSB of byte is MAS 9
 
184
 * ||\MSB of byte is MAS 16
 
185
 * |\LSB of first byte is MAS 1
 
186
 * \ MSB of byte is MAS 8
 
187
 *
 
188
 * An example of this encoding can be found in ECMA-368 Annex-D [Table D.11]
 
189
 *
 
190
 * The resulting bitmap will have the following mapping:
 
191
 *      bit position 0 == MAS 1
 
192
 *      bit position 1 == MAS 2
 
193
 *      ...
 
194
 *      bit position (UWB_NUM_MAS - 1) == MAS UWB_NUM_MAS
 
195
 *
 
196
 * @bmp_itr:    pointer to bitmap (can be declared with DECLARE_BITMAP)
 
197
 * @buffer:     pointer to buffer containing bitmap data in big endian
 
198
 *              format (MSB first)
 
199
 * @buffer_size:number of bytes with which bitmap should be initialized
 
200
 */
 
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
 
 
220
/**
 
221
 * Extract DRP Availability bitmap from the notification.
 
222
 *
 
223
 * The notification that comes in contains a bitmap of (UWB_NUM_MAS / 8) bytes
 
224
 * We convert that to our internal representation.
 
225
 */
 
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
 
 
248
/**
 
249
 * Process an incoming DRP Availability notification.
 
250
 *
 
251
 * @evt:        Event information (packs the actual event data, which
 
252
 *              radio controller it came to, etc).
 
253
 *
 
254
 * @returns:    0 on success (so uwbd() frees the event buffer), < 0
 
255
 *              on error.
 
256
 *
 
257
 * According to ECMA-368 1.0 [16.8.7], bits set to ONE indicate that
 
258
 * the MAS slot is available, bits set to ZERO indicate that the slot
 
259
 * is busy.
 
260
 *
 
261
 * So we clear available slots, we set used slots :)
 
262
 *
 
263
 * The notification only marks non-availability based on the BP and
 
264
 * received DRP IEs that are not for this radio controller.  A copy of
 
265
 * this bitmap is needed to generate the real availability (which
 
266
 * includes local and pending reservations).
 
267
 *
 
268
 * The DRP Availability IE that this radio controller emits will need
 
269
 * to be updated.
 
270
 */
 
271
int uwbd_evt_handle_rc_drp_avail(struct uwb_event *evt)
 
272
{
 
273
        int result;
 
274
        struct uwb_rc *rc = evt->rc;
 
275
        DECLARE_BITMAP(bmp, UWB_NUM_MAS);
 
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;
 
284
        uwb_rsv_handle_drp_avail_change(rc);
 
285
        mutex_unlock(&rc->rsvs_mutex);
 
286
 
 
287
        uwb_rsv_sched_update(rc);
 
288
 
 
289
        return 0;
 
290
}