1 /*-
2 * Copyright(c) 2002-2011 Exar Corp.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification are permitted provided the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the Exar Corporation nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 /*$FreeBSD: stable/9/sys/dev/vxge/vxgehal/vxgehal-channel.c 221167 2011-04-28 14:33:15Z gnn $*/
32
33 #include <dev/vxge/vxgehal/vxgehal.h>
34
35
36 /*
37 * vxge_hal_channel_allocate - Allocate memory for channel
38 * @devh: Handle to the device object
39 * @vph: Handle to Virtual Path
40 * @type: Type of channel
41 * @length: Lengths of arrays
42 * @per_dtr_space: ULD requested per dtr space to be allocated in priv
43 * @userdata: User data to be passed back in the callback
44 *
45 * This function allocates required memory for the channel and various arrays
46 * in the channel
47 */
48 __hal_channel_t *
vxge_hal_channel_allocate(vxge_hal_device_h devh,vxge_hal_vpath_h vph,__hal_channel_type_e type,u32 length,u32 per_dtr_space,void * userdata)49 vxge_hal_channel_allocate(
50 vxge_hal_device_h devh,
51 vxge_hal_vpath_h vph,
52 __hal_channel_type_e type,
53 u32 length,
54 u32 per_dtr_space,
55 void *userdata)
56 {
57 vxge_hal_device_t *hldev = (vxge_hal_device_t *) devh;
58 __hal_channel_t *channel;
59 u32 i, size = 0;
60
61 vxge_assert((devh != NULL) && (vph != NULL));
62
63 vxge_hal_trace_log_channel("==> %s:%s:%d",
64 __FILE__, __func__, __LINE__);
65
66 vxge_hal_trace_log_channel("devh = 0x"VXGE_OS_STXFMT", vph = "
67 "0x"VXGE_OS_STXFMT", type = %d, length = %d, "
68 "per_dtr_space = %d, userdata = 0x"VXGE_OS_STXFMT,
69 (ptr_t) devh, (ptr_t) vph, type, length, per_dtr_space,
70 (ptr_t) userdata);
71
72 switch (type) {
73 case VXGE_HAL_CHANNEL_TYPE_FIFO:
74 size = sizeof(__hal_fifo_t);
75 break;
76 case VXGE_HAL_CHANNEL_TYPE_RING:
77 size = sizeof(__hal_ring_t);
78 break;
79
80
81 default:
82 vxge_assert(size);
83 break;
84
85 }
86
87 channel = (__hal_channel_t *) vxge_os_malloc(hldev->pdev, size);
88 if (channel == NULL) {
89 vxge_hal_trace_log_channel("<== %s:%s:%d Result: %d",
90 __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY);
91 return (NULL);
92 }
93
94 vxge_os_memzero(channel, size);
95 vxge_list_init(&channel->item);
96
97 channel->pdev = hldev->pdev;
98 channel->type = type;
99 channel->devh = devh;
100 channel->vph = vph;
101
102 channel->userdata = userdata;
103 channel->per_dtr_space = per_dtr_space;
104
105 channel->length = length;
106
107 channel->dtr_arr = (__hal_dtr_item_t *) vxge_os_malloc(hldev->pdev,
108 sizeof(__hal_dtr_item_t)*length);
109 if (channel->dtr_arr == NULL) {
110 vxge_hal_channel_free(channel);
111 vxge_hal_trace_log_channel("<== %s:%s:%d Result: %d",
112 __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY);
113 return (NULL);
114 }
115
116 vxge_os_memzero(channel->dtr_arr, sizeof(__hal_dtr_item_t)*length);
117
118 channel->compl_index = 0;
119 channel->reserve_index = 0;
120
121 for (i = 0; i < length; i++)
122 channel->dtr_arr[i].state = VXGE_HAL_CHANNEL_DTR_FREE;
123
124 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0",
125 __FILE__, __func__, __LINE__);
126 return (channel);
127 }
128
129 /*
130 * __hal_channel_free - Free memory allocated for channel
131 * @channel: channel to be freed
132 *
133 * This function deallocates memory from the channel and various arrays
134 * in the channel
135 */
136 void
vxge_hal_channel_free(__hal_channel_t * channel)137 vxge_hal_channel_free(
138 __hal_channel_t *channel)
139 {
140 int size = 0;
141 vxge_hal_device_t *hldev;
142
143 vxge_assert(channel != NULL);
144
145 hldev = (vxge_hal_device_t *) channel->devh;
146
147 vxge_hal_trace_log_channel("==> %s:%s:%d",
148 __FILE__, __func__, __LINE__);
149
150 vxge_hal_trace_log_channel("channel = 0x"VXGE_OS_STXFMT,
151 (ptr_t) channel);
152
153 vxge_assert(channel->pdev);
154
155 if (channel->dtr_arr) {
156 vxge_os_free(channel->pdev, channel->dtr_arr,
157 sizeof(__hal_dtr_item_t)*channel->length);
158 channel->dtr_arr = NULL;
159 }
160
161 switch (channel->type) {
162 case VXGE_HAL_CHANNEL_TYPE_FIFO:
163 size = sizeof(__hal_fifo_t);
164 break;
165 case VXGE_HAL_CHANNEL_TYPE_RING:
166 size = sizeof(__hal_ring_t);
167 break;
168 default:
169 break;
170 }
171
172 vxge_os_free(channel->pdev, channel, size);
173
174 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0",
175 __FILE__, __func__, __LINE__);
176 }
177
178 /*
179 * __hal_channel_initialize - Initialize a channel
180 * @channel: channel to be initialized
181 *
182 * This function initializes a channel by properly
183 * setting the various references
184 */
185 vxge_hal_status_e
vxge_hal_channel_initialize(__hal_channel_t * channel)186 vxge_hal_channel_initialize(
187 __hal_channel_t *channel)
188 {
189 vxge_hal_device_t *hldev;
190 __hal_virtualpath_t *vpath;
191
192 vxge_assert(channel != NULL);
193
194 hldev = (vxge_hal_device_t *) channel->devh;
195 vpath = (__hal_virtualpath_t *)
196 ((__hal_vpath_handle_t *) channel->vph)->vpath;
197
198 vxge_assert(vpath != NULL);
199
200 vxge_hal_trace_log_channel("==> %s:%s:%d",
201 __FILE__, __func__, __LINE__);
202
203 vxge_hal_trace_log_channel("channel = 0x"VXGE_OS_STXFMT,
204 (ptr_t) channel);
205
206 switch (channel->type) {
207 case VXGE_HAL_CHANNEL_TYPE_FIFO:
208 vpath->fifoh = (vxge_hal_fifo_h) channel;
209 channel->stats =
210 &((__hal_fifo_t *) channel)->stats->common_stats;
211 break;
212 case VXGE_HAL_CHANNEL_TYPE_RING:
213 vpath->ringh = (vxge_hal_ring_h) channel;
214 channel->stats =
215 &((__hal_ring_t *) channel)->stats->common_stats;
216 break;
217
218
219 default:
220 break;
221 }
222
223 channel->is_initd = 1;
224 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0",
225 __FILE__, __func__, __LINE__);
226
227 return (VXGE_HAL_OK);
228 }
229
230 /*
231 * __hal_channel_reset - Resets a channel
232 * @channel: channel to be reset
233 *
234 * This function resets a channel by properly setting the various references
235 */
236 vxge_hal_status_e
__hal_channel_reset(__hal_channel_t * channel)237 __hal_channel_reset(
238 __hal_channel_t *channel)
239 {
240 u32 i;
241 __hal_device_t *hldev;
242
243 vxge_assert(channel != NULL);
244
245 hldev = (__hal_device_t *) channel->devh;
246
247 vxge_hal_trace_log_channel("==> %s:%s:%d",
248 __FILE__, __func__, __LINE__);
249
250 vxge_hal_trace_log_channel("channel = 0x"VXGE_OS_STXFMT,
251 (ptr_t) channel);
252
253 vxge_assert(channel->pdev);
254
255 channel->compl_index = 0;
256 channel->reserve_index = 0;
257
258 for (i = 0; i < channel->length; i++) {
259 channel->dtr_arr[i].state =
260 VXGE_HAL_CHANNEL_DTR_FREE;
261 }
262
263 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0",
264 __FILE__, __func__, __LINE__);
265
266 return (VXGE_HAL_OK);
267 }
268
269 /*
270 * vxge_hal_channel_terminate - Deinitializes a channel
271 * @channel: channel to be deinitialized
272 *
273 * This function deinitializes a channel by properly
274 * setting the various references
275 */
276 void
vxge_hal_channel_terminate(__hal_channel_t * channel)277 vxge_hal_channel_terminate(
278 __hal_channel_t *channel)
279 {
280 __hal_device_t *hldev;
281 __hal_virtualpath_t *vpath;
282
283 vxge_assert(channel != NULL);
284
285 if (!channel || !channel->is_initd)
286 return;
287
288 hldev = (__hal_device_t *) channel->devh;
289 vpath = (__hal_virtualpath_t *)
290 ((__hal_vpath_handle_t *) channel->vph)->vpath;
291
292 vxge_assert(vpath != NULL);
293
294 vxge_hal_trace_log_channel("==> %s:%s:%d",
295 __FILE__, __func__, __LINE__);
296
297 vxge_hal_trace_log_channel("channel = 0x"VXGE_OS_STXFMT,
298 (ptr_t) channel);
299
300 switch (channel->type) {
301 case VXGE_HAL_CHANNEL_TYPE_FIFO:
302 vpath->fifoh = 0;
303 break;
304 case VXGE_HAL_CHANNEL_TYPE_RING:
305 vpath->ringh = 0;
306 break;
307 case VXGE_HAL_CHANNEL_TYPE_SEND_QUEUE:
308 vxge_list_remove(&channel->item);
309 vpath->sw_stats->obj_counts.no_sqs--;
310 break;
311 case VXGE_HAL_CHANNEL_TYPE_RECEIVE_QUEUE:
312 vxge_list_remove(&channel->item);
313 vpath->sw_stats->obj_counts.no_srqs--;
314 break;
315 case VXGE_HAL_CHANNEL_TYPE_COMPLETION_QUEUE:
316 vxge_list_remove(&channel->item);
317 vpath->sw_stats->obj_counts.no_cqrqs--;
318 break;
319 default:
320 break;
321 }
322
323 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0",
324 __FILE__, __func__, __LINE__);
325 }
326
327 void
__hal_channel_init_pending_list(vxge_hal_device_h devh)328 __hal_channel_init_pending_list(
329 vxge_hal_device_h devh)
330 {
331 __hal_device_t *hldev = (__hal_device_t *) devh;
332
333 vxge_assert(devh != NULL);
334
335 vxge_hal_trace_log_channel("==> %s:%s:%d",
336 __FILE__, __func__, __LINE__);
337
338 vxge_hal_trace_log_channel("devh = 0x"VXGE_OS_STXFMT,
339 (ptr_t) devh);
340 vxge_list_init(&hldev->pending_channel_list);
341
342 #if defined(VXGE_HAL_VP_CHANNELS)
343 vxge_os_spin_lock_init(&hldev->pending_channel_lock, hldev->pdev);
344 #elif defined(VXGE_HAL_VP_CHANNELS_IRQ)
345 vxge_os_spin_lock_init_irq(&hldev->pending_channel_lock, hldev->irqh);
346 #endif
347 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0",
348 __FILE__, __func__, __LINE__);
349 }
350
351 void
__hal_channel_insert_pending_list(__hal_channel_t * channel)352 __hal_channel_insert_pending_list(
353 __hal_channel_t * channel)
354 {
355 __hal_device_t *hldev = (__hal_device_t *) channel->devh;
356
357 vxge_assert(channel != NULL);
358
359 vxge_hal_trace_log_channel("==> %s:%s:%d",
360 __FILE__, __func__, __LINE__);
361
362 vxge_hal_trace_log_channel("channel = 0x"VXGE_OS_STXFMT,
363 (ptr_t) channel);
364
365 #if defined(VXGE_HAL_PENDING_CHANNELS)
366 vxge_os_spin_lock(&hldev->pending_channel_lock);
367 #elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ)
368 vxge_os_spin_lock_irq(&hldev->pending_channel_lock, flags);
369 #endif
370
371 vxge_list_insert_before(&channel->item, &hldev->pending_channel_list);
372
373 #if defined(VXGE_HAL_PENDING_CHANNELS)
374 vxge_os_spin_unlock(&hldev->pending_channel_lock);
375 #elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ)
376 vxge_os_spin_unlock_irq(&hldev->pending_channel_lock, flags);
377 #endif
378
379 __hal_channel_process_pending_list(channel->devh);
380
381 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0",
382 __FILE__, __func__, __LINE__);
383 }
384
385 void
__hal_channel_process_pending_list(vxge_hal_device_h devh)386 __hal_channel_process_pending_list(
387 vxge_hal_device_h devh)
388 {
389 vxge_hal_status_e status;
390 __hal_channel_t *channel;
391 __hal_device_t *hldev = (__hal_device_t *) devh;
392
393 vxge_assert(devh != NULL);
394
395 vxge_hal_trace_log_channel("==> %s:%s:%d",
396 __FILE__, __func__, __LINE__);
397
398 vxge_hal_trace_log_channel("devh = 0x"VXGE_OS_STXFMT,
399 (ptr_t) devh);
400
401 for (;;) {
402 #if defined(VXGE_HAL_PENDING_CHANNELS)
403 vxge_os_spin_lock(&hldev->pending_channel_lock);
404 #elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ)
405 vxge_os_spin_lock_irq(&hldev->pending_channel_lock, flags);
406 #endif
407
408 channel = (__hal_channel_t *)
409 vxge_list_first_get(&hldev->pending_channel_list);
410
411 if (channel != NULL)
412 vxge_list_remove(&channel->item);
413
414 #if defined(VXGE_HAL_PENDING_CHANNELS)
415 vxge_os_spin_unlock(&hldev->pending_channel_lock);
416 #elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ)
417 vxge_os_spin_unlock_irq(&hldev->pending_channel_lock, flags);
418 #endif
419
420 if (channel == NULL) {
421 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0",
422 __FILE__, __func__, __LINE__);
423 return;
424 }
425
426 switch (channel->type) {
427 default:
428 status = VXGE_HAL_OK;
429 break;
430 }
431
432 if (status == VXGE_HAL_ERR_OUT_OF_MEMORY) {
433 #if defined(VXGE_HAL_PENDING_CHANNELS)
434 vxge_os_spin_lock(&hldev->pending_channel_lock);
435 #elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ)
436 vxge_os_spin_lock_irq(&hldev->pending_channel_lock,
437 flags);
438 #endif
439
440 vxge_list_insert(&channel->item,
441 &hldev->pending_channel_list);
442
443 #if defined(VXGE_HAL_PENDING_CHANNELS)
444 vxge_os_spin_unlock(&hldev->pending_channel_lock);
445 #elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ)
446 vxge_os_spin_unlock_irq(&hldev->pending_channel_lock,
447 flags);
448 #endif
449 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0",
450 __FILE__, __func__, __LINE__);
451
452 return;
453 }
454
455 }
456 }
457
458 void
__hal_channel_destroy_pending_list(vxge_hal_device_h devh)459 __hal_channel_destroy_pending_list(
460 vxge_hal_device_h devh)
461 {
462 vxge_list_t *p, *n;
463 __hal_device_t *hldev = (__hal_device_t *) devh;
464
465 vxge_assert(devh != NULL);
466
467 vxge_hal_trace_log_channel("==> %s:%s:%d",
468 __FILE__, __func__, __LINE__);
469
470 vxge_hal_trace_log_channel("devh = 0x"VXGE_OS_STXFMT,
471 (ptr_t) devh);
472
473 vxge_list_for_each_safe(p, n, &hldev->pending_channel_list) {
474
475 vxge_list_remove(p);
476
477 switch (((__hal_channel_t *) p)->type) {
478 default:
479 break;
480 }
481
482 }
483
484 #if defined(VXGE_HAL_PENDING_CHANNELS)
485 vxge_os_spin_lock_destroy(&hldev->pending_channel_lock,
486 hldev->header.pdev);
487 #elif defined(VXGE_HAL_PENDING_CHANNELS_IRQ)
488 vxge_os_spin_lock_destroy_irq(&hldev->pending_channel_lock,
489 hldev->header.pdev);
490 #endif
491 vxge_hal_trace_log_channel("<== %s:%s:%d Result: 0",
492 __FILE__, __func__, __LINE__);
493 }
494