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