180708Sjake/*-
282899Sjake * Copyright(c) 2002-2011 Exar Corp.
380708Sjake * All rights reserved.
482899Sjake *
582899Sjake * Redistribution and use in source and binary forms, with or without
680708Sjake * modification are permitted provided the following conditions are met:
782899Sjake *
882899Sjake *    1. Redistributions of source code must retain the above copyright notice,
982899Sjake *       this list of conditions and the following disclaimer.
1080708Sjake *
1180708Sjake *    2. Redistributions in binary form must reproduce the above copyright
1280708Sjake *       notice, this list of conditions and the following disclaimer in the
1380708Sjake *       documentation and/or other materials provided with the distribution.
1480708Sjake *
1580708Sjake *    3. Neither the name of the Exar Corporation nor the names of its
1680708Sjake *       contributors may be used to endorse or promote products derived from
1780708Sjake *       this software without specific prior written permission.
1882899Sjake *
1982899Sjake * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2082899Sjake * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2182899Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2282899Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2382899Sjake * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2482899Sjake * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2580708Sjake * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2682899Sjake * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2780708Sjake * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2880708Sjake * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2982899Sjake * POSSIBILITY OF SUCH DAMAGE.
3080708Sjake */
3180708Sjake/*$FreeBSD: releng/10.3/sys/dev/vxge/vxgehal/vxgehal-channel.c 221167 2011-04-28 14:33:15Z gnn $*/
3280708Sjake
3380708Sjake#include <dev/vxge/vxgehal/vxgehal.h>
3480708Sjake
3580708Sjake
3680708Sjake/*
3780708Sjake * vxge_hal_channel_allocate - Allocate memory for channel
3882899Sjake * @devh: Handle to the device object
3982899Sjake * @vph: Handle to Virtual Path
4080708Sjake * @type: Type of channel
4180708Sjake * @length: Lengths of arrays
4280708Sjake * @per_dtr_space: ULD requested per dtr space to be allocated in priv
4382899Sjake * @userdata: User data to be passed back in the callback
4480708Sjake *
4580708Sjake * This function allocates required memory for the channel and various arrays
4680708Sjake * in the channel
4780708Sjake */
4880708Sjake__hal_channel_t *
4980708Sjakevxge_hal_channel_allocate(
5080708Sjake    vxge_hal_device_h devh,
5180708Sjake    vxge_hal_vpath_h vph,
5280708Sjake    __hal_channel_type_e type,
5380708Sjake    u32 length,
5480708Sjake    u32 per_dtr_space,
5580708Sjake    void *userdata)
5680708Sjake{
5780708Sjake	vxge_hal_device_t *hldev = (vxge_hal_device_t *) devh;
5880708Sjake	__hal_channel_t *channel;
5980708Sjake	u32 i, size = 0;
6080708Sjake
6180708Sjake	vxge_assert((devh != NULL) && (vph != NULL));
6280708Sjake
6380708Sjake	vxge_hal_trace_log_channel("==> %s:%s:%d",
6480708Sjake	    __FILE__, __func__, __LINE__);
6580708Sjake
6680708Sjake	vxge_hal_trace_log_channel("devh = 0x"VXGE_OS_STXFMT", vph = "
6780708Sjake	    "0x"VXGE_OS_STXFMT", type = %d, length = %d, "
6880708Sjake	    "per_dtr_space = %d, userdata = 0x"VXGE_OS_STXFMT,
6980708Sjake	    (ptr_t) devh, (ptr_t) vph, type, length, per_dtr_space,
7080708Sjake	    (ptr_t) userdata);
7180708Sjake
7280708Sjake	switch (type) {
7380708Sjake	case VXGE_HAL_CHANNEL_TYPE_FIFO:
7480708Sjake		size = sizeof(__hal_fifo_t);
7580708Sjake		break;
7680708Sjake	case VXGE_HAL_CHANNEL_TYPE_RING:
7780708Sjake		size = sizeof(__hal_ring_t);
7880708Sjake		break;
7980708Sjake
8088653Sjake
81169291Salc	default:
82169291Salc		vxge_assert(size);
83169291Salc		break;
84169291Salc
85169291Salc	}
86108245Sjake
87108245Sjake	channel = (__hal_channel_t *) vxge_os_malloc(hldev->pdev, size);
88108245Sjake	if (channel == NULL) {
89108245Sjake		vxge_hal_trace_log_channel("<== %s:%s:%d  Result: %d",
90108245Sjake		    __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY);
91108245Sjake		return (NULL);
92108245Sjake	}
93108245Sjake
94108245Sjake	vxge_os_memzero(channel, size);
95108245Sjake	vxge_list_init(&channel->item);
96108245Sjake
97108245Sjake	channel->pdev = hldev->pdev;
98108245Sjake	channel->type = type;
99108245Sjake	channel->devh = devh;
100108245Sjake	channel->vph = vph;
101108245Sjake
102108245Sjake	channel->userdata = userdata;
103108245Sjake	channel->per_dtr_space = per_dtr_space;
104108245Sjake
105108245Sjake	channel->length = length;
106108245Sjake
107108245Sjake	channel->dtr_arr = (__hal_dtr_item_t *) vxge_os_malloc(hldev->pdev,
108108245Sjake	    sizeof(__hal_dtr_item_t)*length);
109108245Sjake	if (channel->dtr_arr == NULL) {
110108245Sjake		vxge_hal_channel_free(channel);
111108245Sjake		vxge_hal_trace_log_channel("<== %s:%s:%d  Result: %d",
112108245Sjake		    __FILE__, __func__, __LINE__, VXGE_HAL_ERR_OUT_OF_MEMORY);
113108245Sjake		return (NULL);
114108245Sjake	}
115108245Sjake
116108245Sjake	vxge_os_memzero(channel->dtr_arr, sizeof(__hal_dtr_item_t)*length);
117108245Sjake
118108245Sjake	channel->compl_index = 0;
119108245Sjake	channel->reserve_index = 0;
120108245Sjake
121108245Sjake	for (i = 0; i < length; i++)
122108245Sjake		channel->dtr_arr[i].state = VXGE_HAL_CHANNEL_DTR_FREE;
123108245Sjake
124108245Sjake	vxge_hal_trace_log_channel("<== %s:%s:%d  Result: 0",
125108245Sjake	    __FILE__, __func__, __LINE__);
126108245Sjake	return (channel);
127108245Sjake}
128108245Sjake
129108245Sjake/*
130108245Sjake * __hal_channel_free - Free memory allocated for channel
131108245Sjake * @channel: channel to be freed
132108245Sjake *
133108245Sjake * This function deallocates memory from the channel and various arrays
134108245Sjake * in the channel
135108245Sjake */
136108245Sjakevoid
137108245Sjakevxge_hal_channel_free(
138108245Sjake    __hal_channel_t *channel)
139108245Sjake{
14088653Sjake	int size = 0;
141108245Sjake	vxge_hal_device_t *hldev;
142108245Sjake
14380708Sjake	vxge_assert(channel != NULL);
144108245Sjake
145108245Sjake	hldev = (vxge_hal_device_t *) channel->devh;
14688653Sjake
147108245Sjake	vxge_hal_trace_log_channel("==> %s:%s:%d",
148108245Sjake	    __FILE__, __func__, __LINE__);
14980708Sjake
150108245Sjake	vxge_hal_trace_log_channel("channel = 0x"VXGE_OS_STXFMT,
151108245Sjake	    (ptr_t) channel);
152108245Sjake
153108245Sjake	vxge_assert(channel->pdev);
154108245Sjake
155108245Sjake	if (channel->dtr_arr) {
156108245Sjake		vxge_os_free(channel->pdev, channel->dtr_arr,
157108245Sjake		    sizeof(__hal_dtr_item_t)*channel->length);
158108245Sjake		channel->dtr_arr = NULL;
159108245Sjake	}
160108245Sjake
161108245Sjake	switch (channel->type) {
16280708Sjake	case VXGE_HAL_CHANNEL_TYPE_FIFO:
16380708Sjake		size = sizeof(__hal_fifo_t);
16480708Sjake		break;
16580708Sjake	case VXGE_HAL_CHANNEL_TYPE_RING:
16691974Sjake		size = sizeof(__hal_ring_t);
16780708Sjake		break;
16880708Sjake	default:
16985241Sjake		break;
17091974Sjake	}
171168920Ssepotvin
172168920Ssepotvin	vxge_os_free(channel->pdev, channel, size);
17391974Sjake
17491974Sjake	vxge_hal_trace_log_channel("<== %s:%s:%d  Result: 0",
17591974Sjake	    __FILE__, __func__, __LINE__);
17691974Sjake}
17791974Sjake
17891974Sjake/*
17991974Sjake * __hal_channel_initialize - Initialize a channel
18080708Sjake * @channel: channel to be initialized
18180708Sjake *
18280708Sjake * This function initializes a channel by properly
18380708Sjake *		setting the various references
18480708Sjake */
18580708Sjakevxge_hal_status_e
186108332Sjakevxge_hal_channel_initialize(
187108332Sjake    __hal_channel_t *channel)
188101653Sjake{
189101653Sjake	vxge_hal_device_t *hldev;
19080708Sjake	__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 */
236vxge_hal_status_e
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 */
276void
277vxge_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
327void
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
351void
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
385void
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
458void
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