a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * CDDL HEADER START
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * The contents of this file are subject to the terms of the
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Common Development and Distribution License (the "License").
a23fd118e437af0a7877dd313db8fdaa3537c675yl * You may not use this file except in compliance with the License.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a23fd118e437af0a7877dd313db8fdaa3537c675yl * or http://www.opensolaris.org/os/licensing.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See the License for the specific language governing permissions
a23fd118e437af0a7877dd313db8fdaa3537c675yl * and limitations under the License.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * When distributing Covered Code, include this CDDL HEADER in each
a23fd118e437af0a7877dd313db8fdaa3537c675yl * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * If applicable, add the following below this CDDL HEADER, with the
a23fd118e437af0a7877dd313db8fdaa3537c675yl * fields enclosed by brackets "[]" replaced with your own identifying
a23fd118e437af0a7877dd313db8fdaa3537c675yl * information: Portions Copyright [yyyy] [name of copyright owner]
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * CDDL HEADER END
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Copyright (c) 2002-2006 Neterion, Inc.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl#ifdef XGE_DEBUG_FP
a23fd118e437af0a7877dd313db8fdaa3537c675yl#include "xgehal-channel.h"
a23fd118e437af0a7877dd313db8fdaa3537c675yl#endif
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__hal_channel_dtr_alloc(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl void **tmp_arr;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl unsigned long flags = 0;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl#endif
7eced415e5dd557aef2d78483b5a7785f0e13670xw if (channel->terminating) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw return XGE_HAL_FAIL;
7eced415e5dd557aef2d78483b5a7785f0e13670xw }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (channel->reserve_length - channel->reserve_top >
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel->reserve_threshold) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl_alloc_after_swap:
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *dtrh = channel->reserve_arr[--channel->reserve_length];
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_debug_channel(XGE_TRACE, "dtrh 0x"XGE_OS_LLXFMT" allocated, "
8347601bcb0a439f6e50fc36b4039a73d08700e1yl "channel %d:%d:%d, reserve_idx %d",
a23fd118e437af0a7877dd313db8fdaa3537c675yl (unsigned long long)(ulong_t)*dtrh,
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->type, channel->post_qid,
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->compl_qid, channel->reserve_length);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_os_spin_lock_irq(&channel->free_lock, flags);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_spin_lock(&channel->free_lock);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl#endif
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* switch between empty and full arrays */
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* the idea behind such a design is that by having free and reserved
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * arrays separated we basically separated irq and non-irq parts.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * i.e. no additional lock need to be done when we free a resource */
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (channel->reserve_initial - channel->free_length >
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel->reserve_threshold) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl tmp_arr = channel->reserve_arr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->reserve_arr = channel->free_arr;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel->reserve_length = channel->reserve_initial;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel->free_arr = tmp_arr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->reserve_top = channel->free_length;
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->free_length = channel->reserve_initial;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->stats.reserve_free_swaps_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_channel(XGE_TRACE,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl "switch on channel %d:%d:%d, reserve_length %d, "
8347601bcb0a439f6e50fc36b4039a73d08700e1yl "free_length %d", channel->type, channel->post_qid,
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->compl_qid, channel->reserve_length,
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->free_length);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_spin_unlock_irq(&channel->free_lock, flags);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_spin_unlock(&channel->free_lock);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl#endif
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl goto _alloc_after_swap;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl#if defined(XGE_HAL_RX_MULTI_FREE_IRQ) || defined(XGE_HAL_TX_MULTI_FREE_IRQ)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_spin_unlock_irq(&channel->free_lock, flags);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl#elif defined(XGE_HAL_RX_MULTI_FREE) || defined(XGE_HAL_TX_MULTI_FREE)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_spin_unlock(&channel->free_lock);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl#endif
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_channel(XGE_TRACE, "channel %d:%d:%d is empty!",
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->type, channel->post_qid,
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->compl_qid);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel->stats.full_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *dtrh = NULL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_INF_OUT_OF_DESCRIPTORS;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__hal_channel_dtr_restore(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
a23fd118e437af0a7877dd313db8fdaa3537c675yl int offset)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* restore a previously allocated dtrh at current offset and update
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * the available reserve length accordingly. If dtrh is null just
a23fd118e437af0a7877dd313db8fdaa3537c675yl * update the reserve length, only */
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (dtrh) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->reserve_arr[channel->reserve_length + offset] = dtrh;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_debug_channel(XGE_TRACE, "dtrh 0x"XGE_OS_LLXFMT" restored for "
8347601bcb0a439f6e50fc36b4039a73d08700e1yl "channel %d:%d:%d, offset %d at reserve index %d, ",
a23fd118e437af0a7877dd313db8fdaa3537c675yl (unsigned long long)(ulong_t)dtrh, channel->type,
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->post_qid, channel->compl_qid, offset,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel->reserve_length + offset);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl else {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel->reserve_length += offset;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_debug_channel(XGE_TRACE, "channel %d:%d:%d, restored "
8347601bcb0a439f6e50fc36b4039a73d08700e1yl "for offset %d, new reserve_length %d, free length %d",
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->type, channel->post_qid, channel->compl_qid,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl offset, channel->reserve_length, channel->free_length);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
a23fd118e437af0a7877dd313db8fdaa3537c675yl__hal_channel_dtr_post(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_channel_t *channel = (xge_hal_channel_t*)channelh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_assert(channel->work_arr[channel->post_index] == NULL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->work_arr[channel->post_index++] = dtrh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* wrap-around */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (channel->post_index == channel->length)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel->post_index = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
a23fd118e437af0a7877dd313db8fdaa3537c675yl__hal_channel_dtr_try_complete(xge_hal_channel_h channelh, xge_hal_dtr_h *dtrh)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_assert(channel->work_arr);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_assert(channel->compl_index < channel->length);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *dtrh = channel->work_arr[channel->compl_index];
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
a23fd118e437af0a7877dd313db8fdaa3537c675yl__hal_channel_dtr_complete(xge_hal_channel_h channelh)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel->work_arr[channel->compl_index] = NULL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* wrap-around */
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (++channel->compl_index == channel->length)
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->compl_index = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->stats.total_compl_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
a23fd118e437af0a7877dd313db8fdaa3537c675yl__hal_channel_dtr_free(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel->free_arr[--channel->free_length] = dtrh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_debug_channel(XGE_TRACE, "dtrh 0x"XGE_OS_LLXFMT" freed, "
8347601bcb0a439f6e50fc36b4039a73d08700e1yl "channel %d:%d:%d, new free_length %d",
a23fd118e437af0a7877dd313db8fdaa3537c675yl (unsigned long long)(ulong_t)dtrh,
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->type, channel->post_qid,
a23fd118e437af0a7877dd313db8fdaa3537c675yl channel->compl_qid, channel->free_length);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_channel_dtr_count
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @channelh: Channel handle. Obtained via xge_hal_channel_open().
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Retreive number of DTRs available. This function can not be called
7eced415e5dd557aef2d78483b5a7785f0e13670xw * from data path.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int
8347601bcb0a439f6e50fc36b4039a73d08700e1ylxge_hal_channel_dtr_count(xge_hal_channel_h channelh)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return ((channel->reserve_length - channel->reserve_top) +
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (channel->reserve_initial - channel->free_length) -
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel->reserve_threshold);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl}
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_channel_userdata - Get user-specified channel context.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @channelh: Channel handle. Obtained via xge_hal_channel_open().
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Returns: per-channel "user data", which can be any ULD-defined context.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * The %userdata "gets" into the channel at open time
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * (see xge_hal_channel_open()).
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See also: xge_hal_channel_open().
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void*
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_channel_userdata(xge_hal_channel_h channelh)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return channel->userdata;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_channel_id - Get channel ID.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @channelh: Channel handle. Obtained via xge_hal_channel_open().
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Returns: channel ID. For link layer channel id is the number
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * in the range from 0 to 7 that identifies hardware ring or fifo,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * depending on the channel type.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_channel_id(xge_hal_channel_h channelh)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_channel_t *channel = (xge_hal_channel_t *)channelh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return channel->post_qid;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_check_alignment - Check buffer alignment and calculate the
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * "misaligned" portion.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @dma_pointer: DMA address of the buffer.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @size: Buffer size, in bytes.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @alignment: Alignment "granularity" (see below), in bytes.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @copy_size: Maximum number of bytes to "extract" from the buffer
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * (in order to spost it as a separate scatter-gather entry). See below.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Check buffer alignment and calculate "misaligned" portion, if exists.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * The buffer is considered aligned if its address is multiple of
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * the specified @alignment. If this is the case,
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_check_alignment() returns zero.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Otherwise, xge_hal_check_alignment() uses the last argument,
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @copy_size,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * to calculate the size to "extract" from the buffer. The @copy_size
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * may or may not be equal @alignment. The difference between these two
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * arguments is that the @alignment is used to make the decision: aligned
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * or not aligned. While the @copy_size is used to calculate the portion
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * of the buffer to "extract", i.e. to post as a separate entry in the
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * transmit descriptor. For example, the combination
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @alignment=8 and @copy_size=64 will work okay on AMD Opteron boxes.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Note: @copy_size should be a multiple of @alignment. In many practical
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * cases @copy_size and @alignment will probably be equal.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See also: xge_hal_fifo_dtr_buffer_set_aligned().
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int
8347601bcb0a439f6e50fc36b4039a73d08700e1ylxge_hal_check_alignment(dma_addr_t dma_pointer, int size, int alignment,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int copy_size)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int misaligned_size;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl misaligned_size = (int)(dma_pointer & (alignment - 1));
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (!misaligned_size) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (size > copy_size) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl misaligned_size = (int)(dma_pointer & (copy_size - 1));
8347601bcb0a439f6e50fc36b4039a73d08700e1yl misaligned_size = copy_size - misaligned_size;
a23fd118e437af0a7877dd313db8fdaa3537c675yl } else {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl misaligned_size = size;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return misaligned_size;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
8347601bcb0a439f6e50fc36b4039a73d08700e1yl