xgehal-device-fp.c revision da14cebe459d3275048785f25bd869cb09b5307f
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright (c) 2002-2006 Neterion, Inc.
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifdef XGE_DEBUG_FP
#include "xgehal-device.h"
#endif
#include "xgehal-ring.h"
#include "xgehal-fifo.h"
/**
* xge_hal_device_bar0 - Get BAR0 mapped address.
* @hldev: HAL device handle.
*
* Returns: BAR0 address of the specified device.
*/
{
}
/**
* xge_hal_device_isrbar0 - Get BAR0 mapped address.
* @hldev: HAL device handle.
*
* Returns: BAR0 address of the specified device.
*/
{
}
/**
* xge_hal_device_bar1 - Get BAR1 mapped address.
* @hldev: HAL device handle.
*
* Returns: BAR1 address of the specified device.
*/
{
}
/**
* xge_hal_device_bar0_set - Set BAR0 mapped address.
* @hldev: HAL device handle.
* @bar0: BAR0 mapped address.
* * Set BAR0 address in the HAL device object.
*/
{
}
/**
* xge_hal_device_isrbar0_set - Set BAR0 mapped address.
* @hldev: HAL device handle.
* @isrbar0: BAR0 mapped address.
* * Set BAR0 address in the HAL device object.
*/
{
}
/**
* xge_hal_device_bar1_set - Set BAR1 mapped address.
* @hldev: HAL device handle.
* @channelh: Channel handle.
* @bar1: BAR1 mapped address.
*
* Set BAR1 address for the given channel.
*/
char *bar1)
{
/* Initializing the BAR1 address as the start of
* the FIFO queue pointer and as a location of FIFO control
* word. */
(xge_hal_fifo_hw_pair_t *) (bar1 +
}
/**
* xge_hal_device_rev - Get Device revision number.
* @hldev: HAL device handle.
*
* Returns: Device revision number
*/
{
}
/**
* xge_hal_device_begin_irq - Begin IRQ processing.
* @hldev: HAL device handle.
* @reason: "Reason" for the interrupt, the value of Xframe's
* general_int_status register.
*
* The function performs two actions, It first checks whether (shared IRQ) the
* interrupt was raised by the device. Next, it masks the device interrupts.
*
* Note:
* xge_hal_device_begin_irq() does not flush MMIO writes through the
* bridge. Therefore, two back-to-back interrupts are potentially possible.
* It is the responsibility of the ULD to make sure that only one
* xge_hal_device_continue_irq() runs at a time.
*
* Returns: 0, if the interrupt is not "ours" (note that in this case the
* device remain enabled).
* Otherwise, xge_hal_device_begin_irq() returns 64bit general adapter
* status.
* See also: xge_hal_device_handle_irq()
*/
{
if (xge_os_unlikely(!val64)) {
/* not Xframe interrupt */
*reason = 0;
return XGE_HAL_ERR_WRONG_IRQ;
}
if (adapter_status == XGE_HAL_ALL_FOXES) {
1, /* critical: slot freeze */
sizeof(u64),
(void*)&adapter_status);
*reason = 0;
return XGE_HAL_ERR_CRITICAL;
}
}
/* separate fast path, i.e. no errors */
if (val64 & XGE_HAL_GEN_INTR_RXTRAFFIC) {
return XGE_HAL_OK;
}
if (val64 & XGE_HAL_GEN_INTR_TXTRAFFIC) {
return XGE_HAL_OK;
}
if (status != XGE_HAL_OK) {
return status;
}
}
if (status != XGE_HAL_OK) {
return status;
}
}
if (status != XGE_HAL_OK) {
return status;
}
}
if (status != XGE_HAL_OK) {
return status;
}
}
if (status != XGE_HAL_OK) {
return status;
}
}
if (status != XGE_HAL_OK) {
return status;
}
}
if (status != XGE_HAL_OK) {
return status;
}
}
if (status != XGE_HAL_OK) {
return status;
}
}
if (status != XGE_HAL_OK) {
return status;
}
}
return XGE_HAL_OK;
}
/**
* xge_hal_device_clear_rx - Acknowledge (that is, clear) the
* condition that has caused the RX interrupt.
* @hldev: HAL device handle.
*
* Acknowledge (that is, clear) the condition that has caused
* the Rx interrupt.
* See also: xge_hal_device_begin_irq(), xge_hal_device_continue_irq(),
* xge_hal_device_clear_tx(), xge_hal_device_mask_rx().
*/
{
0xFFFFFFFFFFFFFFFFULL,
}
/**
* xge_hal_device_clear_tx - Acknowledge (that is, clear) the
* condition that has caused the TX interrupt.
* @hldev: HAL device handle.
*
* Acknowledge (that is, clear) the condition that has caused
* the Tx interrupt.
* See also: xge_hal_device_begin_irq(), xge_hal_device_continue_irq(),
* xge_hal_device_clear_rx(), xge_hal_device_mask_tx().
*/
{
0xFFFFFFFFFFFFFFFFULL,
}
/**
* xge_hal_device_poll_rx_channel - Poll Rx channel for completed
* descriptors and process the same.
* @channel: HAL channel.
* @got_rx: Buffer to return the flag set if receive interrupt is occured
*
* The function polls the Rx channel for the completed descriptors and calls
* the upper-layer driver (ULD) via supplied completion callback.
*
* Returns: XGE_HAL_OK, if the polling is completed successful.
* XGE_HAL_COMPLETIONS_REMAIN: There are still more completed
* descriptors available which are yet to be processed.
*
* See also: xge_hal_device_poll_tx_channel()
*/
{
int got_bytes;
/* for each opened rx channel */
channel->poll_bytes = 0;
&t_code)) == XGE_HAL_OK) {
} else {
}
}
if (*got_rx) {
}
return ret;
}
/**
* xge_hal_device_poll_tx_channel - Poll Tx channel for completed
* descriptors and process the same.
* @channel: HAL channel.
* @got_tx: Buffer to return the flag set if transmit interrupt is occured
*
* The function polls the Tx channel for the completed descriptors and calls
* the upper-layer driver (ULD) via supplied completion callback.
*
* Returns: XGE_HAL_OK, if the polling is completed successful.
* XGE_HAL_COMPLETIONS_REMAIN: There are still more completed
* descriptors available which are yet to be processed.
*
* See also: xge_hal_device_poll_rx_channel().
*/
{
int got_bytes;
/* for each opened tx channel */
channel->poll_bytes = 0;
&t_code) == XGE_HAL_OK) {
(*got_tx)++;
return XGE_HAL_COMPLETIONS_REMAIN;
}
(*got_tx)++;
}
if (*got_tx) {
}
return XGE_HAL_OK;
}
/**
* xge_hal_device_poll_rx_channels - Poll Rx channels for completed
* descriptors and process the same.
* @hldev: HAL device handle.
* @got_rx: Buffer to return flag set if receive is ready
*
* The function polls the Rx channels for the completed descriptors and calls
* the upper-layer driver (ULD) via supplied completion callback.
*
* Returns: XGE_HAL_OK, if the polling is completed successful.
* XGE_HAL_COMPLETIONS_REMAIN: There are still more completed
* descriptors available which are yet to be processed.
*
* See also: xge_hal_device_poll_tx_channels(), xge_hal_device_continue_irq().
*/
{
/* for each opened rx channel */
if (hldev->terminating)
return XGE_HAL_OK;
}
}
return XGE_HAL_OK;
}
/**
* xge_hal_device_poll_tx_channels - Poll Tx channels for completed
* descriptors and process the same.
* @hldev: HAL device handle.
* @got_tx: Buffer to return flag set if transmit is ready
*
* The function polls the Tx channels for the completed descriptors and calls
* the upper-layer driver (ULD) via supplied completion callback.
*
* Returns: XGE_HAL_OK, if the polling is completed successful.
* XGE_HAL_COMPLETIONS_REMAIN: There are still more completed
* descriptors available which are yet to be processed.
*
* See also: xge_hal_device_poll_rx_channels(), xge_hal_device_continue_irq().
*/
{
/* for each opened tx channel */
if (hldev->terminating)
return XGE_HAL_OK;
}
return XGE_HAL_OK;
}
/**
*
*/
{
}
{
}
/**
* xge_hal_device_mask_tx - Mask Tx interrupts.
* @hldev: HAL device handle.
*
* Mask Tx device interrupts.
*
* See also: xge_hal_device_unmask_tx(), xge_hal_device_mask_rx(),
* xge_hal_device_clear_tx().
*/
{
0xFFFFFFFFFFFFFFFFULL,
}
/**
* xge_hal_device_mask_rx - Mask Rx interrupts.
* @hldev: HAL device handle.
*
* Mask Rx device interrupts.
*
* See also: xge_hal_device_unmask_rx(), xge_hal_device_mask_tx(),
* xge_hal_device_clear_rx().
*/
{
0xFFFFFFFFFFFFFFFFULL,
}
/**
* xge_hal_device_mask_all - Mask all device interrupts.
* @hldev: HAL device handle.
*
* Mask all device interrupts.
*
* See also: xge_hal_device_unmask_all()
*/
{
0xFFFFFFFFFFFFFFFFULL,
}
/**
* xge_hal_device_unmask_tx - Unmask Tx interrupts.
* @hldev: HAL device handle.
*
* Unmask Tx device interrupts.
*
* See also: xge_hal_device_mask_tx(), xge_hal_device_clear_tx().
*/
{
0x0ULL,
}
/**
* xge_hal_device_unmask_rx - Unmask Rx interrupts.
* @hldev: HAL device handle.
*
* Unmask Rx device interrupts.
*
* See also: xge_hal_device_mask_rx(), xge_hal_device_clear_rx().
*/
{
0x0ULL,
}
/**
* xge_hal_device_unmask_all - Unmask all device interrupts.
* @hldev: HAL device handle.
*
* Unmask all device interrupts.
*
* See also: xge_hal_device_mask_all()
*/
{
0x0ULL,
}
/**
* xge_hal_device_continue_irq - Continue handling IRQ: process all
* completed descriptors.
* @hldev: HAL device handle.
*
* Process completed descriptors and unmask the device interrupts.
*
* The xge_hal_device_continue_irq() walks all open channels
* and calls upper-layer driver (ULD) via supplied completion
* callback. Note that the completion callback is specified at channel open
* time, see xge_hal_channel_open().
*
* Note that the xge_hal_device_continue_irq is part of the _fast_ path.
* To optimize the processing, the function does _not_ check for
* errors and alarms.
*
* The latter is done in a polling fashion, via xge_hal_device_poll().
*
* Returns: XGE_HAL_OK.
*
* See also: xge_hal_device_handle_irq(), xge_hal_device_poll(),
* xge_hal_ring_dtr_next_completed(),
* xge_hal_fifo_dtr_next_completed(), xge_hal_channel_callback_f{}.
*/
{
int count = 0;
do
{
if (got_rx)
break;
}while (isr_polling_cnt--);
if (!count)
return XGE_HAL_OK;
}
/**
* xge_hal_device_handle_irq - Handle device IRQ.
* @hldev: HAL device handle.
*
* Perform the complete handling of the line interrupt. The function
* performs two calls.
* First it uses xge_hal_device_begin_irq() to check the reason for
* the interrupt and mask the device interrupts.
* Second, it calls xge_hal_device_continue_irq() to process all
* completed descriptors and re-enable the interrupts.
*
* Returns: XGE_HAL_OK - success;
* XGE_HAL_ERR_WRONG_IRQ - (shared) IRQ produced by other device.
*
* See also: xge_hal_device_begin_irq(), xge_hal_device_continue_irq().
*/
{
if (status != XGE_HAL_OK) {
return status;
}
if (reason & XGE_HAL_GEN_INTR_RXTRAFFIC) {
}
return status;
}
#if defined(XGE_HAL_CONFIG_LRO)
{
/* Match Source address field */
return XGE_HAL_FAIL;
/* Match Destination address field */
return XGE_HAL_FAIL;
/* Match Source Port field */
return XGE_HAL_FAIL;
/* Match Destination Port field */
return XGE_HAL_FAIL;
return XGE_HAL_OK;
}
/*
* __hal_tcp_seg_len: Find the tcp seg len.
* @ip: ip header.
* @tcp: tcp header.
* returns: Tcp seg length.
*/
{
return (ret);
}
/*
* __hal_ip_lro_capable: Finds whether ip is lro capable.
* @ip: ip header.
* @ext_info: descriptor info.
*/
{
#ifdef XGE_LL_DEBUG_DUMP_PKT
{
u16 i;
for (i =0; i < 40; i++) {
}
}
#endif
return XGE_HAL_FAIL;
}
return XGE_HAL_FAIL;
}
return XGE_HAL_OK;
}
/*
* __hal_tcp_lro_capable: Finds whether tcp is lro capable.
* @ip: ip header.
* @tcp: tcp header.
*/
{
#ifdef XGE_LL_DEBUG_DUMP_PKT
{
u16 i;
for (i =0; i < 20; i++) {
}
}
#endif
goto _exit_fail;
*ts_off = -1;
int i, diff;
/* Does Packet can contain time stamp */
if (tcp_hdr_len < 32) {
/*
* If the session is not opened, we can consider
* this packet for LRO
*/
return XGE_HAL_OK;
goto _exit_fail;
}
/* Ignore No-operation 0x1 */
off++;
/* Next option == Timestamp */
/*
* If the session ie not opened, we can consider
* this packet for LRO
*/
return XGE_HAL_OK;
goto _exit_fail;
}
return XGE_HAL_OK;
/*
* Now the session is opened. If the LRO frame doesn't
* have time stamp, we cannot consider current packet for
* LRO.
*/
xge_debug_ring(XGE_ERR, "Pkt received with time stamp after session opened with no time stamp : %02x %02x", tcp->doff_res, tcp->ctrl);
return XGE_HAL_FAIL;
}
/*
* If the difference is greater than three, then there are
* more options possible.
* else, there are two cases:
* case 1: remaining are padding bytes.
* case 2: remaining can contain options or padding
*/
if (diff > 3) {
/*
* Probably contains more options.
*/
xge_debug_ring(XGE_ERR, "tcphdr not fastpth : pkt received with tcp options in addition to time stamp after the session is opened %02x %02x ", tcp->doff_res, tcp->ctrl);
return XGE_HAL_FAIL;
}
for (i = 0; i < diff; i++) {
/* Ignore No-operation 0x1 */
continue;
xge_debug_ring(XGE_ERR, "tcphdr not fastpth : pkt received with tcp options in addition to time stamp after the session is opened %02x %02x ", tcp->doff_res, tcp->ctrl);
return XGE_HAL_FAIL;
}
/*
* Update the time stamp of LRO frame.
*/
}
return XGE_HAL_OK;
return XGE_HAL_FAIL;
}
/*
* __hal_lro_capable: Finds whether frame is lro capable.
* @buffer: Ethernet frame.
* @ip: ip frame.
* @tcp: tcp frame.
* @ext_info: Descriptor info.
*/
{
return XGE_HAL_FAIL;
}
if ( !*ip )
{
#ifdef XGE_LL_DEBUG_DUMP_PKT
{
u16 i;
xge_os_printf("Dump Eth:" );
for (i =0; i < 60; i++) {
}
}
#endif
case XGE_HAL_FRAME_TYPE_DIX:
break;
case XGE_HAL_FRAME_TYPE_LLC:
break;
case XGE_HAL_FRAME_TYPE_SNAP:
break;
default: // XGE_HAL_FRAME_TYPE_IPX, etc.
return XGE_HAL_FAIL;
}
}
/* Grab ip, tcp headers */
} /* !*ip */
return XGE_HAL_OK;
}
/*
* __hal_open_lro_session: Open a new LRO session.
* @buffer: Ethernet frame.
* @ip: ip header.
* @tcp: tcp header.
* @lro: lro pointer
* @ext_info: Descriptor info.
* @hldev: Hal context.
* @ring_lro: LRO descriptor per rx ring.
* @slot: Bucket no.
* @tcp_seg_len: Length of tcp segment.
* @ts_off: time stamp offset in the packet.
*/
{
return;
}
/*
* __hal_lro_get_free_slot: Get a free LRO bucket.
* @ring_lro: LRO descriptor per ring.
*/
{
int i;
for (i = 0; i < XGE_HAL_LRO_MAX_BUCKETS; i++) {
return i;
}
return -1;
}
/*
* __hal_get_lro_session: Gets matching LRO session or creates one.
* @eth_hdr: Ethernet header.
* @ip: ip header.
* @tcp: tcp header.
* @lro: lro pointer
* @ext_info: Descriptor info.
* @hldev: Hal context.
* @ring_lro: LRO descriptor per rx ring
*/
{
int i, free_slot = -1;
int ts_off = -1;
/*
* Compare the incoming frame with the lro session left from the
* previous call. There is a good chance that this incoming frame
* matches the lro session.
*/
== XGE_HAL_OK)
}
if (!lro_match) {
/*
* Search in the pool of LROs for the session that matches
* the incoming frame.
*/
for (i = 0; i < XGE_HAL_LRO_MAX_BUCKETS; i++) {
if (free_slot == -1)
free_slot = i;
continue;
}
ip) == XGE_HAL_OK) {
break;
}
}
}
if (lro_match) {
/*
* Matching LRO Session found
*/
"found***");
return XGE_HAL_INF_LRO_END_2;
}
{
return XGE_HAL_INF_LRO_END_2;
}
&ts_off)) {
/*
* Close the current session and open a new
* LRO session with this packet,
* provided it has tcp payload
*/
if (tcp_seg_len == 0)
{
return XGE_HAL_INF_LRO_END_2;
}
/* Get a free bucket */
if (free_slot == -1)
{
return XGE_HAL_INF_LRO_END_2;
}
/*
* Open a new LRO session
*/
ts_off);
return XGE_HAL_INF_LRO_END_3;
}
/*
* The frame is good, in-sequence, can be LRO-ed;
* take its (latest) ACK - unless it is a dupack.
* Note: to be exact need to check window size as well..
*/
return XGE_HAL_INF_LRO_END_2;
}
return XGE_HAL_INF_LRO_CONT;
}
/* ********** New Session ***************/
if (free_slot == -1)
return XGE_HAL_INF_LRO_UNCAPABLE;
return XGE_HAL_INF_LRO_UNCAPABLE;
return XGE_HAL_INF_LRO_UNCAPABLE;
/*
* Open a LRO session, provided the packet contains payload.
*/
if (tcp_seg_len == 0)
return XGE_HAL_INF_LRO_UNCAPABLE;
return XGE_HAL_INF_LRO_BEGIN;
}
/*
* __hal_lro_under_optimal_thresh: Finds whether combined session is optimal.
* @ip: ip header.
* @tcp: tcp header.
* @lro: lro pointer
* @hldev: Hal context.
*/
{
if (!lro) return XGE_HAL_FAIL;
return XGE_HAL_FAIL;
}
return XGE_HAL_FAIL;
}
return XGE_HAL_OK;
}
/*
* __hal_collapse_ip_hdr: Collapses ip header.
* @ip: ip header.
* @tcp: tcp header.
* @lro: lro pointer
* @hldev: Hal context.
*/
{
/* May be we have to handle time stamps or more options */
return XGE_HAL_OK;
}
/*
* __hal_collapse_tcp_hdr: Collapses tcp header.
* @ip: ip header.
* @tcp: tcp header.
* @lro: lro pointer
* @hldev: Hal context.
*/
{
return XGE_HAL_OK;
}
/*
* __hal_append_lro: Appends new frame to existing LRO session.
* @ip: ip header.
* @tcp: IN tcp header, OUT tcp payload.
* @seg_len: tcp payload length.
* @lro: lro pointer
* @hldev: Hal context.
*/
{
// Update mbuf chain will be done in ll driver.
// xge_hal_accumulate_large_rx on success of appending new frame to
// lro will return to ll driver tcpdata pointer, and tcp payload length.
// along with return code lro frame appended.
return XGE_HAL_OK;
}
/**
* __xge_hal_accumulate_large_rx: LRO a given frame
* frames
* @ring: rx ring number
* @eth_hdr: ethernet header.
* @ip_hdr: ip header (optional)
* @tcp: tcp header.
* @seglen: packet length.
* @p_lro: lro pointer.
* @ext_info: descriptor info, see xge_hal_dtr_info_t{}.
* @hldev: HAL device.
* @lro_end3: for lro_end3 output
*
* LRO the newly received frame, i.e. attach it (if possible) to the
* already accumulated (i.e., already LRO-ed) received frames (if any),
* to form one super-sized frame for the subsequent processing
* by the stack.
*/
{
ext_info))
return XGE_HAL_INF_LRO_UNCAPABLE;
/*
* This function shall get matching LRO or else
* create one and return it
*/
lro_end3);
if (XGE_HAL_INF_LRO_CONT == ret) {
}
} else ret = XGE_HAL_INF_LRO_END_2;
}
/*
* Since its time to flush,
* update ip header so that it can be sent up
*/
if ((ret == XGE_HAL_INF_LRO_END_1) ||
(ret == XGE_HAL_INF_LRO_END_2) ||
(ret == XGE_HAL_INF_LRO_END_3)) {
}
return (ret);
}
/**
* xge_hal_accumulate_large_rx: LRO a given frame
* frames
* @buffer: Ethernet frame.
* @tcp: tcp header.
* @seglen: packet length.
* @p_lro: lro pointer.
* @ext_info: descriptor info, see xge_hal_dtr_info_t{}.
* @hldev: HAL device.
* @lro_end3: for lro_end3 output
*
* LRO the newly received frame, i.e. attach it (if possible) to the
* already accumulated (i.e., already LRO-ed) received frames (if any),
* to form one super-sized frame for the subsequent processing
* by the stack.
*/
{
int ring = 0;
}
/**
* xge_hal_lro_close_session: Close LRO session
* @lro: LRO Session.
* @hldev: HAL Context.
*/
{
}
/**
* xge_hal_lro_next_session: Returns next LRO session in the list or NULL
* if none exists.
* @hldev: HAL Context.
* @ring: rx ring number.
*/
{
int i;
for(i = start_idx; i < XGE_HAL_LRO_MAX_BUCKETS; i++) {
continue;
return lro;
}
ring_lro->lro_next_idx = 0;
return NULL;
}
{
int ring = 0; /* assume default ring=0 */
}
#endif