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
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Use is subject to license terms.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
a23fd118e437af0a7877dd313db8fdaa3537c675yl#ifdef XGE_DEBUG_FP
a23fd118e437af0a7877dd313db8fdaa3537c675yl#include "xgehal-device.h"
a23fd118e437af0a7877dd313db8fdaa3537c675yl#endif
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl#include "xgehal-ring.h"
a23fd118e437af0a7877dd313db8fdaa3537c675yl#include "xgehal-fifo.h"
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_bar0 - Get BAR0 mapped address.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Returns: BAR0 address of the specified device.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE char *
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_device_bar0(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl return hldev->bar0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_device_isrbar0 - Get BAR0 mapped address.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Returns: BAR0 address of the specified device.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE char *
8347601bcb0a439f6e50fc36b4039a73d08700e1ylxge_hal_device_isrbar0(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl return hldev->isrbar0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_bar1 - Get BAR1 mapped address.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Returns: BAR1 address of the specified device.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE char *
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_device_bar1(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl return hldev->bar1;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_bar0_set - Set BAR0 mapped address.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @bar0: BAR0 mapped address.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * * Set BAR0 address in the HAL device object.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_device_bar0_set(xge_hal_device_t *hldev, char *bar0)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_assert(bar0);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->bar0 = bar0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_device_isrbar0_set - Set BAR0 mapped address.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @isrbar0: BAR0 mapped address.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * * Set BAR0 address in the HAL device object.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
8347601bcb0a439f6e50fc36b4039a73d08700e1ylxge_hal_device_isrbar0_set(xge_hal_device_t *hldev, char *isrbar0)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_assert(isrbar0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl hldev->isrbar0 = isrbar0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_bar1_set - Set BAR1 mapped address.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @channelh: Channel handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @bar1: BAR1 mapped address.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Set BAR1 address for the given channel.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_device_bar1_set(xge_hal_device_t *hldev, xge_hal_channel_h channelh,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl char *bar1)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_assert(bar1);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_assert(fifo);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* Initializing the BAR1 address as the start of
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * the FIFO queue pointer and as a location of FIFO control
a23fd118e437af0a7877dd313db8fdaa3537c675yl * word. */
a23fd118e437af0a7877dd313db8fdaa3537c675yl fifo->hw_pair =
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (xge_hal_fifo_hw_pair_t *) (bar1 +
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (fifo->channel.post_qid * XGE_HAL_FIFO_HW_PAIR_OFFSET));
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->bar1 = bar1;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_device_rev - Get Device revision number.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Returns: Device revision number
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE int
8347601bcb0a439f6e50fc36b4039a73d08700e1ylxge_hal_device_rev(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return hldev->revision;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_device_begin_irq - Begin IRQ processing.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @reason: "Reason" for the interrupt, the value of Xframe's
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * general_int_status register.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * The function performs two actions, It first checks whether (shared IRQ) the
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * interrupt was raised by the device. Next, it masks the device interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Note:
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_begin_irq() does not flush MMIO writes through the
a23fd118e437af0a7877dd313db8fdaa3537c675yl * bridge. Therefore, two back-to-back interrupts are potentially possible.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * It is the responsibility of the ULD to make sure that only one
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_continue_irq() runs at a time.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Returns: 0, if the interrupt is not "ours" (note that in this case the
a23fd118e437af0a7877dd313db8fdaa3537c675yl * device remain enabled).
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Otherwise, xge_hal_device_begin_irq() returns 64bit general adapter
a23fd118e437af0a7877dd313db8fdaa3537c675yl * status.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See also: xge_hal_device_handle_irq()
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_device_begin_irq(xge_hal_device_t *hldev, u64 *reason)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u64 val64;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl hldev->stats.sw_dev_info_stats.total_intr_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl val64 = xge_os_pio_mem_read64(hldev->pdev,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->regh0, &isrbar0->general_int_status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (xge_os_unlikely(!val64)) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* not Xframe interrupt */
7eced415e5dd557aef2d78483b5a7785f0e13670xw hldev->stats.sw_dev_info_stats.not_xge_intr_cnt++;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *reason = 0;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_ERR_WRONG_IRQ;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (xge_os_unlikely(val64 == XGE_HAL_ALL_FOXES)) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u64 adapter_status =
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl &isrbar0->adapter_status);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (adapter_status == XGE_HAL_ALL_FOXES) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (void) xge_queue_produce(hldev->queueh,
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGE_HAL_EVENT_SLOT_FREEZE,
a23fd118e437af0a7877dd313db8fdaa3537c675yl hldev,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl 1, /* critical: slot freeze */
a23fd118e437af0a7877dd313db8fdaa3537c675yl sizeof(u64),
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void*)&adapter_status);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *reason = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_ERR_CRITICAL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *reason = val64;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* separate fast path, i.e. no errors */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (val64 & XGE_HAL_GEN_INTR_RXTRAFFIC) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl hldev->stats.sw_dev_info_stats.rx_traffic_intr_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (val64 & XGE_HAL_GEN_INTR_TXTRAFFIC) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt++;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_TXPIC)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.txpic_intr_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = __hal_device_handle_txpic(hldev, val64);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_TXDMA)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.txdma_intr_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = __hal_device_handle_txdma(hldev, val64);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_TXMAC)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.txmac_intr_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = __hal_device_handle_txmac(hldev, val64);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_TXXGXS)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.txxgxs_intr_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = __hal_device_handle_txxgxs(hldev, val64);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_RXPIC)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.rxpic_intr_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = __hal_device_handle_rxpic(hldev, val64);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_RXDMA)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.rxdma_intr_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = __hal_device_handle_rxdma(hldev, val64);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_RXMAC)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.rxmac_intr_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = __hal_device_handle_rxmac(hldev, val64);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_RXXGXS)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.rxxgxs_intr_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = __hal_device_handle_rxxgxs(hldev, val64);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_MC)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.mc_intr_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = __hal_device_handle_mc(hldev, val64);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_clear_rx - Acknowledge (that is, clear) the
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * condition that has caused the RX interrupt.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Acknowledge (that is, clear) the condition that has caused
a23fd118e437af0a7877dd313db8fdaa3537c675yl * the Rx interrupt.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See also: xge_hal_device_begin_irq(), xge_hal_device_continue_irq(),
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_clear_tx(), xge_hal_device_mask_rx().
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_device_clear_rx(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl 0xFFFFFFFFFFFFFFFFULL,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl &isrbar0->rx_traffic_int);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_clear_tx - Acknowledge (that is, clear) the
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * condition that has caused the TX interrupt.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Acknowledge (that is, clear) the condition that has caused
a23fd118e437af0a7877dd313db8fdaa3537c675yl * the Tx interrupt.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See also: xge_hal_device_begin_irq(), xge_hal_device_continue_irq(),
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_clear_rx(), xge_hal_device_mask_tx().
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_device_clear_tx(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl 0xFFFFFFFFFFFFFFFFULL,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl &isrbar0->tx_traffic_int);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl}
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_device_poll_rx_channel - Poll Rx channel for completed
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * descriptors and process the same.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @channel: HAL channel.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @got_rx: Buffer to return the flag set if receive interrupt is occured
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * The function polls the Rx channel for the completed descriptors and calls
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * the upper-layer driver (ULD) via supplied completion callback.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Returns: XGE_HAL_OK, if the polling is completed successful.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * XGE_HAL_COMPLETIONS_REMAIN: There are still more completed
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * descriptors available which are yet to be processed.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * See also: xge_hal_device_poll_tx_channel()
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
8347601bcb0a439f6e50fc36b4039a73d08700e1ylxge_hal_device_poll_rx_channel(xge_hal_channel_t *channel, int *got_rx)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_status_e ret = XGE_HAL_OK;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_dtr_h first_dtrh;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_device_t *hldev = (xge_hal_device_t *)channel->devh;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u8 t_code;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int got_bytes;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* for each opened rx channel */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl got_bytes = *got_rx = 0;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl ((xge_hal_ring_t *)channel)->cmpl_cnt = 0;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel->poll_bytes = 0;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if ((ret = xge_hal_ring_dtr_next_completed (channel, &first_dtrh,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl &t_code)) == XGE_HAL_OK) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (channel->callback(channel, first_dtrh,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl t_code, channel->userdata) != XGE_HAL_OK) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (*got_rx) += ((xge_hal_ring_t *)channel)->cmpl_cnt + 1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl got_bytes += channel->poll_bytes + 1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl ret = XGE_HAL_COMPLETIONS_REMAIN;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl } else {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (*got_rx) += ((xge_hal_ring_t *)channel)->cmpl_cnt + 1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl got_bytes += channel->poll_bytes + 1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (*got_rx) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->irq_workload_rxd[channel->post_qid] += *got_rx;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->irq_workload_rxcnt[channel->post_qid] ++;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->irq_workload_rxlen[channel->post_qid] += got_bytes;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return ret;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl}
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_device_poll_tx_channel - Poll Tx channel for completed
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * descriptors and process the same.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @channel: HAL channel.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @got_tx: Buffer to return the flag set if transmit interrupt is occured
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * The function polls the Tx channel for the completed descriptors and calls
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * the upper-layer driver (ULD) via supplied completion callback.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Returns: XGE_HAL_OK, if the polling is completed successful.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * XGE_HAL_COMPLETIONS_REMAIN: There are still more completed
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * descriptors available which are yet to be processed.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * See also: xge_hal_device_poll_rx_channel().
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
8347601bcb0a439f6e50fc36b4039a73d08700e1ylxge_hal_device_poll_tx_channel(xge_hal_channel_t *channel, int *got_tx)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_dtr_h first_dtrh;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_device_t *hldev = (xge_hal_device_t *)channel->devh;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u8 t_code;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int got_bytes;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* for each opened tx channel */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl got_bytes = *got_tx = 0;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel->poll_bytes = 0;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (xge_hal_fifo_dtr_next_completed (channel, &first_dtrh,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl &t_code) == XGE_HAL_OK) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (channel->callback(channel, first_dtrh,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl t_code, channel->userdata) != XGE_HAL_OK) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (*got_tx)++;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl got_bytes += channel->poll_bytes + 1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_COMPLETIONS_REMAIN;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (*got_tx)++;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl got_bytes += channel->poll_bytes + 1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (*got_tx) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->irq_workload_txd[channel->post_qid] += *got_tx;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->irq_workload_txcnt[channel->post_qid] ++;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->irq_workload_txlen[channel->post_qid] += got_bytes;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_poll_rx_channels - Poll Rx channels for completed
a23fd118e437af0a7877dd313db8fdaa3537c675yl * descriptors and process the same.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @got_rx: Buffer to return flag set if receive is ready
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * The function polls the Rx channels for the completed descriptors and calls
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * the upper-layer driver (ULD) via supplied completion callback.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Returns: XGE_HAL_OK, if the polling is completed successful.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * XGE_HAL_COMPLETIONS_REMAIN: There are still more completed
a23fd118e437af0a7877dd313db8fdaa3537c675yl * descriptors available which are yet to be processed.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * See also: xge_hal_device_poll_tx_channels(), xge_hal_device_continue_irq().
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
8347601bcb0a439f6e50fc36b4039a73d08700e1ylxge_hal_device_poll_rx_channels(xge_hal_device_t *hldev, int *got_rx)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_list_t *item;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_channel_t *channel;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* for each opened rx channel */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_list_for_each(item, &hldev->ring_channels) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (hldev->terminating)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_OK;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel = xge_container_of(item, xge_hal_channel_t, item);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!(channel->flags & XGE_HAL_CHANNEL_FLAG_USE_RX_POLLING)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) xge_hal_device_poll_rx_channel(channel, got_rx);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_poll_tx_channels - Poll Tx channels for completed
a23fd118e437af0a7877dd313db8fdaa3537c675yl * descriptors and process the same.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @got_tx: Buffer to return flag set if transmit is ready
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * The function polls the Tx channels for the completed descriptors and calls
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * the upper-layer driver (ULD) via supplied completion callback.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Returns: XGE_HAL_OK, if the polling is completed successful.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * XGE_HAL_COMPLETIONS_REMAIN: There are still more completed
a23fd118e437af0a7877dd313db8fdaa3537c675yl * descriptors available which are yet to be processed.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * See also: xge_hal_device_poll_rx_channels(), xge_hal_device_continue_irq().
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
8347601bcb0a439f6e50fc36b4039a73d08700e1ylxge_hal_device_poll_tx_channels(xge_hal_device_t *hldev, int *got_tx)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_list_t *item;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_channel_t *channel;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* for each opened tx channel */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_list_for_each(item, &hldev->fifo_channels) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (hldev->terminating)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_OK;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl channel = xge_container_of(item, xge_hal_channel_t, item);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (void) xge_hal_device_poll_tx_channel(channel, got_tx);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/**
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxge_hal_device_rx_channel_enable_polling(xge_hal_channel_t *channel)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng channel->flags |= XGE_HAL_CHANNEL_FLAG_USE_RX_POLLING;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxge_hal_device_rx_channel_disable_polling(xge_hal_channel_t *channel)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng channel->flags &= ~XGE_HAL_CHANNEL_FLAG_USE_RX_POLLING;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_device_mask_tx - Mask Tx interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Mask Tx device interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See also: xge_hal_device_unmask_tx(), xge_hal_device_mask_rx(),
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_clear_tx().
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
8347601bcb0a439f6e50fc36b4039a73d08700e1ylxge_hal_device_mask_tx(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl 0xFFFFFFFFFFFFFFFFULL,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl &isrbar0->tx_traffic_mask);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_device_mask_rx - Mask Rx interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Mask Rx device interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See also: xge_hal_device_unmask_rx(), xge_hal_device_mask_tx(),
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_clear_rx().
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
8347601bcb0a439f6e50fc36b4039a73d08700e1ylxge_hal_device_mask_rx(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl 0xFFFFFFFFFFFFFFFFULL,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl &isrbar0->rx_traffic_mask);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_mask_all - Mask all device interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Mask all device interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See also: xge_hal_device_unmask_all()
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_device_mask_all(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl 0xFFFFFFFFFFFFFFFFULL,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl &isrbar0->general_int_mask);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_device_unmask_tx - Unmask Tx interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Unmask Tx device interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See also: xge_hal_device_mask_tx(), xge_hal_device_clear_tx().
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_device_unmask_tx(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl 0x0ULL,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl &isrbar0->tx_traffic_mask);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_device_unmask_rx - Unmask Rx interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Unmask Rx device interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See also: xge_hal_device_mask_rx(), xge_hal_device_clear_rx().
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_device_unmask_rx(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl 0x0ULL,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl &isrbar0->rx_traffic_mask);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_unmask_all - Unmask all device interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Unmask all device interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See also: xge_hal_device_mask_all()
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_device_unmask_all(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl 0x0ULL,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl &isrbar0->general_int_mask);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_device_continue_irq - Continue handling IRQ: process all
a23fd118e437af0a7877dd313db8fdaa3537c675yl * completed descriptors.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Process completed descriptors and unmask the device interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * The xge_hal_device_continue_irq() walks all open channels
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * and calls upper-layer driver (ULD) via supplied completion
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * callback. Note that the completion callback is specified at channel open
a23fd118e437af0a7877dd313db8fdaa3537c675yl * time, see xge_hal_channel_open().
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Note that the xge_hal_device_continue_irq is part of the _fast_ path.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * To optimize the processing, the function does _not_ check for
a23fd118e437af0a7877dd313db8fdaa3537c675yl * errors and alarms.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * The latter is done in a polling fashion, via xge_hal_device_poll().
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Returns: XGE_HAL_OK.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See also: xge_hal_device_handle_irq(), xge_hal_device_poll(),
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_ring_dtr_next_completed(),
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_fifo_dtr_next_completed(), xge_hal_channel_callback_f{}.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_device_continue_irq(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int got_rx = 1, got_tx = 1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int isr_polling_cnt = hldev->config.isr_polling_cnt;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int count = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl do
8347601bcb0a439f6e50fc36b4039a73d08700e1yl {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (got_rx)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (void) xge_hal_device_poll_rx_channels(hldev, &got_rx);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (got_tx && hldev->tti_enabled)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (void) xge_hal_device_poll_tx_channels(hldev, &got_tx);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (!got_rx && !got_tx)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl count += (got_rx + got_tx);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }while (isr_polling_cnt--);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (!count)
a23fd118e437af0a7877dd313db8fdaa3537c675yl hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_hal_device_handle_irq - Handle device IRQ.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device handle.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Perform the complete handling of the line interrupt. The function
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * performs two calls.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * First it uses xge_hal_device_begin_irq() to check the reason for
a23fd118e437af0a7877dd313db8fdaa3537c675yl * the interrupt and mask the device interrupts.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Second, it calls xge_hal_device_continue_irq() to process all
a23fd118e437af0a7877dd313db8fdaa3537c675yl * completed descriptors and re-enable the interrupts.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Returns: XGE_HAL_OK - success;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * XGE_HAL_ERR_WRONG_IRQ - (shared) IRQ produced by other device.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See also: xge_hal_device_begin_irq(), xge_hal_device_continue_irq().
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_device_handle_irq(xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u64 reason;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_mask_all(hldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl status = xge_hal_device_begin_irq(hldev, &reason);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_unmask_all(hldev);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (reason & XGE_HAL_GEN_INTR_RXTRAFFIC) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_clear_rx(hldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl status = xge_hal_device_continue_irq(hldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_clear_tx(hldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_unmask_all(hldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl#if defined(XGE_HAL_CONFIG_LRO)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__hal_lro_check_for_session_match(lro_t *lro, tcplro_t *tcp, iplro_t *ip)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* Match Source address field */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if ((lro->ip_hdr->saddr != ip->saddr))
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_FAIL;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* Match Destination address field */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if ((lro->ip_hdr->daddr != ip->daddr))
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_FAIL;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* Match Source Port field */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if ((lro->tcp_hdr->source != tcp->source))
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_FAIL;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* Match Destination Port field */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if ((lro->tcp_hdr->dest != tcp->dest))
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_FAIL;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_OK;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * __hal_tcp_seg_len: Find the tcp seg len.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @ip: ip header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @tcp: tcp header.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * returns: Tcp seg length.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL u16
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__hal_tcp_seg_len(iplro_t *ip, tcplro_t *tcp)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u16 ret;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl ret = (xge_os_ntohs(ip->tot_len) -
8347601bcb0a439f6e50fc36b4039a73d08700e1yl ((ip->version_ihl & 0x0F)<<2) -
8347601bcb0a439f6e50fc36b4039a73d08700e1yl ((tcp->doff_res)>>2));
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (ret);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * __hal_ip_lro_capable: Finds whether ip is lro capable.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @ip: ip header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @ext_info: descriptor info.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
a23fd118e437af0a7877dd313db8fdaa3537c675yl__hal_ip_lro_capable(iplro_t *ip,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_dtr_info_t *ext_info)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl#ifdef XGE_LL_DEBUG_DUMP_PKT
a23fd118e437af0a7877dd313db8fdaa3537c675yl {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u16 i;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u8 ch, *iph = (u8 *)ip;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_debug_ring(XGE_TRACE, "Dump Ip:" );
8347601bcb0a439f6e50fc36b4039a73d08700e1yl for (i =0; i < 40; i++) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl ch = ntohs(*((u8 *)(iph + i)) );
a23fd118e437af0a7877dd313db8fdaa3537c675yl printf("i:%d %02x, ",i,ch);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl#endif
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (ip->version_ihl != IP_FAST_PATH_HDR_MASK) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_debug_ring(XGE_ERR, "iphdr !=45 :%d",ip->version_ihl);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_FAIL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (ext_info->proto & XGE_HAL_FRAME_PROTO_IP_FRAGMENTED) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_debug_ring(XGE_ERR, "IP fragmented");
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_FAIL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * __hal_tcp_lro_capable: Finds whether tcp is lro capable.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @ip: ip header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @tcp: tcp header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__hal_tcp_lro_capable(iplro_t *ip, tcplro_t *tcp, lro_t *lro, int *ts_off)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl#ifdef XGE_LL_DEBUG_DUMP_PKT
a23fd118e437af0a7877dd313db8fdaa3537c675yl {
a23fd118e437af0a7877dd313db8fdaa3537c675yl u8 ch;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u16 i;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_debug_ring(XGE_TRACE, "Dump Tcp:" );
8347601bcb0a439f6e50fc36b4039a73d08700e1yl for (i =0; i < 20; i++) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl ch = ntohs(*((u8 *)((u8 *)tcp + i)) );
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_printf("i:%d %02x, ",i,ch);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl#endif
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if ((TCP_FAST_PATH_HDR_MASK2 != tcp->ctrl) &&
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (TCP_FAST_PATH_HDR_MASK3 != tcp->ctrl))
8347601bcb0a439f6e50fc36b4039a73d08700e1yl goto _exit_fail;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *ts_off = -1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (TCP_FAST_PATH_HDR_MASK1 != tcp->doff_res) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u16 tcp_hdr_len = tcp->doff_res >> 2; /* TCP header len */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u16 off = 20; /* Start of tcp options */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int i, diff;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* Does Packet can contain time stamp */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (tcp_hdr_len < 32) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * If the session is not opened, we can consider
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * this packet for LRO
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (lro == NULL)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_OK;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl goto _exit_fail;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* Ignore No-operation 0x1 */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl while (((u8 *)tcp)[off] == 0x1)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl off++;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* Next option == Timestamp */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (((u8 *)tcp)[off] != 0x8) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * If the session ie not opened, we can consider
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * this packet for LRO
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (lro == NULL)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_OK;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl goto _exit_fail;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *ts_off = off;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (lro == NULL)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_OK;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Now the session is opened. If the LRO frame doesn't
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * have time stamp, we cannot consider current packet for
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * LRO.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (lro->ts_off == -1) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw xge_debug_ring(XGE_ERR, "Pkt received with time stamp after session opened with no time stamp : %02x %02x", tcp->doff_res, tcp->ctrl);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_FAIL;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * If the difference is greater than three, then there are
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * more options possible.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * else, there are two cases:
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * case 1: remaining are padding bytes.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * case 2: remaining can contain options or padding
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl off += ((u8 *)tcp)[off+1];
8347601bcb0a439f6e50fc36b4039a73d08700e1yl diff = tcp_hdr_len - off;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (diff > 3) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Probably contains more options.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
7eced415e5dd557aef2d78483b5a7785f0e13670xw 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);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_FAIL;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl for (i = 0; i < diff; i++) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u8 byte = ((u8 *)tcp)[off+i];
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* Ignore No-operation 0x1 */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if ((byte == 0x0) || (byte == 0x1))
8347601bcb0a439f6e50fc36b4039a73d08700e1yl continue;
7eced415e5dd557aef2d78483b5a7785f0e13670xw 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);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_FAIL;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Update the time stamp of LRO frame.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_memcpy(((char *)lro->tcp_hdr + lro->ts_off + 2),
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (char *)((char *)tcp + (*ts_off) + 2), 8);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl_exit_fail:
7eced415e5dd557aef2d78483b5a7785f0e13670xw xge_debug_ring(XGE_TRACE, "tcphdr not fastpth %02x %02x", tcp->doff_res, tcp->ctrl);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_FAIL;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * __hal_lro_capable: Finds whether frame is lro capable.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @buffer: Ethernet frame.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @ip: ip frame.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @tcp: tcp frame.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @ext_info: Descriptor info.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
a23fd118e437af0a7877dd313db8fdaa3537c675yl__hal_lro_capable( u8 *buffer,
a23fd118e437af0a7877dd313db8fdaa3537c675yl iplro_t **ip,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl tcplro_t **tcp,
7eced415e5dd557aef2d78483b5a7785f0e13670xw xge_hal_dtr_info_t *ext_info)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl u8 ip_off, ip_length;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (!(ext_info->proto & XGE_HAL_FRAME_PROTO_TCP)) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_debug_ring(XGE_ERR, "Cant do lro %d", ext_info->proto);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_FAIL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
7eced415e5dd557aef2d78483b5a7785f0e13670xw
7eced415e5dd557aef2d78483b5a7785f0e13670xw if ( !*ip )
7eced415e5dd557aef2d78483b5a7785f0e13670xw {
a23fd118e437af0a7877dd313db8fdaa3537c675yl#ifdef XGE_LL_DEBUG_DUMP_PKT
a23fd118e437af0a7877dd313db8fdaa3537c675yl {
a23fd118e437af0a7877dd313db8fdaa3537c675yl u8 ch;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u16 i;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_printf("Dump Eth:" );
8347601bcb0a439f6e50fc36b4039a73d08700e1yl for (i =0; i < 60; i++) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl ch = ntohs(*((u8 *)(buffer + i)) );
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_os_printf("i:%d %02x, ",i,ch);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl#endif
a23fd118e437af0a7877dd313db8fdaa3537c675yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw switch (ext_info->frame) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw case XGE_HAL_FRAME_TYPE_DIX:
7eced415e5dd557aef2d78483b5a7785f0e13670xw ip_off = XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE;
7eced415e5dd557aef2d78483b5a7785f0e13670xw break;
7eced415e5dd557aef2d78483b5a7785f0e13670xw case XGE_HAL_FRAME_TYPE_LLC:
7eced415e5dd557aef2d78483b5a7785f0e13670xw ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE +
7eced415e5dd557aef2d78483b5a7785f0e13670xw XGE_HAL_HEADER_802_2_SIZE);
7eced415e5dd557aef2d78483b5a7785f0e13670xw break;
7eced415e5dd557aef2d78483b5a7785f0e13670xw case XGE_HAL_FRAME_TYPE_SNAP:
7eced415e5dd557aef2d78483b5a7785f0e13670xw ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE +
7eced415e5dd557aef2d78483b5a7785f0e13670xw XGE_HAL_HEADER_SNAP_SIZE);
7eced415e5dd557aef2d78483b5a7785f0e13670xw break;
7eced415e5dd557aef2d78483b5a7785f0e13670xw default: // XGE_HAL_FRAME_TYPE_IPX, etc.
7eced415e5dd557aef2d78483b5a7785f0e13670xw return XGE_HAL_FAIL;
7eced415e5dd557aef2d78483b5a7785f0e13670xw }
7eced415e5dd557aef2d78483b5a7785f0e13670xw
7eced415e5dd557aef2d78483b5a7785f0e13670xw
7eced415e5dd557aef2d78483b5a7785f0e13670xw if (ext_info->proto & XGE_HAL_FRAME_PROTO_VLAN_TAGGED) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw ip_off += XGE_HAL_HEADER_VLAN_SIZE;
7eced415e5dd557aef2d78483b5a7785f0e13670xw }
7eced415e5dd557aef2d78483b5a7785f0e13670xw
7eced415e5dd557aef2d78483b5a7785f0e13670xw /* Grab ip, tcp headers */
7eced415e5dd557aef2d78483b5a7785f0e13670xw *ip = (iplro_t *)((char*)buffer + ip_off);
7eced415e5dd557aef2d78483b5a7785f0e13670xw } /* !*ip */
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl ip_length = (u8)((*ip)->version_ihl & 0x0F);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl ip_length = ip_length <<2;
7eced415e5dd557aef2d78483b5a7785f0e13670xw *tcp = (tcplro_t *)((char *)*ip + ip_length);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_debug_ring(XGE_TRACE, "ip_length:%d ip:"XGE_OS_LLXFMT
8347601bcb0a439f6e50fc36b4039a73d08700e1yl " tcp:"XGE_OS_LLXFMT"", (int)ip_length,
7eced415e5dd557aef2d78483b5a7785f0e13670xw (unsigned long long)(ulong_t)*ip, (unsigned long long)(ulong_t)*tcp);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl/*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * __hal_open_lro_session: Open a new LRO session.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @buffer: Ethernet frame.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @ip: ip header.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @tcp: tcp header.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @lro: lro pointer
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @ext_info: Descriptor info.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @hldev: Hal context.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @ring_lro: LRO descriptor per rx ring.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @slot: Bucket no.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @tcp_seg_len: Length of tcp segment.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @ts_off: time stamp offset in the packet.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__hal_open_lro_session (u8 *buffer, iplro_t *ip, tcplro_t *tcp, lro_t **lro,
7eced415e5dd557aef2d78483b5a7785f0e13670xw xge_hal_device_t *hldev, xge_hal_lro_desc_t *ring_lro, int slot,
7eced415e5dd557aef2d78483b5a7785f0e13670xw u32 tcp_seg_len, int ts_off)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw lro_t *lro_new = &ring_lro->lro_pool[slot];
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_new->in_use = 1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_new->ll_hdr = buffer;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_new->ip_hdr = ip;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_new->tcp_hdr = tcp;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_new->tcp_next_seq_num = tcp_seg_len + xge_os_ntohl(
8347601bcb0a439f6e50fc36b4039a73d08700e1yl tcp->seq);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_new->tcp_seq_num = tcp->seq;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_new->tcp_ack_num = tcp->ack_seq;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_new->sg_num = 1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_new->total_length = xge_os_ntohs(ip->tot_len);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_new->frags_len = 0;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_new->ts_off = ts_off;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.tot_frms_lroised++;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.tot_lro_sessions++;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw *lro = ring_lro->lro_recent = lro_new;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * __hal_lro_get_free_slot: Get a free LRO bucket.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @ring_lro: LRO descriptor per ring.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int
7eced415e5dd557aef2d78483b5a7785f0e13670xw__hal_lro_get_free_slot (xge_hal_lro_desc_t *ring_lro)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int i;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl for (i = 0; i < XGE_HAL_LRO_MAX_BUCKETS; i++) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw lro_t *lro_temp = &ring_lro->lro_pool[i];
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (!lro_temp->in_use)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return i;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return -1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * __hal_get_lro_session: Gets matching LRO session or creates one.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @eth_hdr: Ethernet header.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @ip: ip header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @tcp: tcp header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @lro: lro pointer
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @ext_info: Descriptor info.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: Hal context.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @ring_lro: LRO descriptor per rx ring
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
7eced415e5dd557aef2d78483b5a7785f0e13670xw__hal_get_lro_session (u8 *eth_hdr,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl iplro_t *ip,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl tcplro_t *tcp,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_t **lro,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_dtr_info_t *ext_info,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_device_t *hldev,
7eced415e5dd557aef2d78483b5a7785f0e13670xw xge_hal_lro_desc_t *ring_lro,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_t **lro_end3 /* Valid only when ret=END_3 */)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_t *lro_match;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int i, free_slot = -1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl u32 tcp_seg_len;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int ts_off = -1;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *lro = lro_match = NULL;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Compare the incoming frame with the lro session left from the
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * previous call. There is a good chance that this incoming frame
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * matches the lro session.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
7eced415e5dd557aef2d78483b5a7785f0e13670xw if (ring_lro->lro_recent && ring_lro->lro_recent->in_use) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw if (__hal_lro_check_for_session_match(ring_lro->lro_recent,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl tcp, ip)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl == XGE_HAL_OK)
7eced415e5dd557aef2d78483b5a7785f0e13670xw lro_match = ring_lro->lro_recent;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (!lro_match) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Search in the pool of LROs for the session that matches
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * the incoming frame.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl for (i = 0; i < XGE_HAL_LRO_MAX_BUCKETS; i++) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw lro_t *lro_temp = &ring_lro->lro_pool[i];
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (!lro_temp->in_use) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (free_slot == -1)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl free_slot = i;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl continue;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (__hal_lro_check_for_session_match(lro_temp, tcp,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl ip) == XGE_HAL_OK) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_match = lro_temp;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl break;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (lro_match) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Matching LRO Session found
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *lro = lro_match;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (lro_match->tcp_next_seq_num != xge_os_ntohl(tcp->seq)) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw xge_debug_ring(XGE_ERR, "**retransmit **"
a23fd118e437af0a7877dd313db8fdaa3537c675yl "found***");
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.lro_out_of_seq_pkt_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_INF_LRO_END_2;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (XGE_HAL_OK != __hal_ip_lro_capable(ip, ext_info))
7eced415e5dd557aef2d78483b5a7785f0e13670xw {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_INF_LRO_END_2;
7eced415e5dd557aef2d78483b5a7785f0e13670xw }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (XGE_HAL_OK != __hal_tcp_lro_capable(ip, tcp, lro_match,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl &ts_off)) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Close the current session and open a new
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * LRO session with this packet,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * provided it has tcp payload
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl tcp_seg_len = __hal_tcp_seg_len(ip, tcp);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (tcp_seg_len == 0)
7eced415e5dd557aef2d78483b5a7785f0e13670xw {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_INF_LRO_END_2;
7eced415e5dd557aef2d78483b5a7785f0e13670xw }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* Get a free bucket */
7eced415e5dd557aef2d78483b5a7785f0e13670xw free_slot = __hal_lro_get_free_slot(ring_lro);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (free_slot == -1)
7eced415e5dd557aef2d78483b5a7785f0e13670xw {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_INF_LRO_END_2;
7eced415e5dd557aef2d78483b5a7785f0e13670xw }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Open a new LRO session
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
7eced415e5dd557aef2d78483b5a7785f0e13670xw __hal_open_lro_session (eth_hdr, ip, tcp, lro_end3,
7eced415e5dd557aef2d78483b5a7785f0e13670xw hldev, ring_lro, free_slot, tcp_seg_len,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl ts_off);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_INF_LRO_END_3;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * The frame is good, in-sequence, can be LRO-ed;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * take its (latest) ACK - unless it is a dupack.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Note: to be exact need to check window size as well..
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (lro_match->tcp_ack_num == tcp->ack_seq &&
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_match->tcp_seq_num == tcp->seq) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.lro_dup_pkt_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_INF_LRO_END_2;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_match->tcp_seq_num = tcp->seq;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_match->tcp_ack_num = tcp->ack_seq;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro_match->frags_len += __hal_tcp_seg_len(ip, tcp);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw ring_lro->lro_recent = lro_match;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_INF_LRO_CONT;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* ********** New Session ***************/
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (free_slot == -1)
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_INF_LRO_UNCAPABLE;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (XGE_HAL_FAIL == __hal_ip_lro_capable(ip, ext_info))
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_INF_LRO_UNCAPABLE;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (XGE_HAL_FAIL == __hal_tcp_lro_capable(ip, tcp, NULL, &ts_off))
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_INF_LRO_UNCAPABLE;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_debug_ring(XGE_TRACE, "Creating lro session.");
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Open a LRO session, provided the packet contains payload.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl tcp_seg_len = __hal_tcp_seg_len(ip, tcp);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (tcp_seg_len == 0)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return XGE_HAL_INF_LRO_UNCAPABLE;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw __hal_open_lro_session (eth_hdr, ip, tcp, lro, hldev, ring_lro, free_slot,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl tcp_seg_len, ts_off);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_INF_LRO_BEGIN;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * __hal_lro_under_optimal_thresh: Finds whether combined session is optimal.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @ip: ip header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @tcp: tcp header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @lro: lro pointer
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: Hal context.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__hal_lro_under_optimal_thresh (iplro_t *ip,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl tcplro_t *tcp,
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro_t *lro,
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (!lro) return XGE_HAL_FAIL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if ((lro->total_length + __hal_tcp_seg_len(ip, tcp) ) >
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->config.lro_frm_len) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_debug_ring(XGE_TRACE, "Max LRO frame len exceeded:"
7eced415e5dd557aef2d78483b5a7785f0e13670xw "max length %d ", hldev->config.lro_frm_len);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.lro_frm_len_exceed_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_FAIL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (lro->sg_num == hldev->config.lro_sg_size) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_debug_ring(XGE_TRACE, "Max sg count exceeded:"
7eced415e5dd557aef2d78483b5a7785f0e13670xw "max sg %d ", hldev->config.lro_sg_size);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.lro_sg_exceed_cnt++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_FAIL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * __hal_collapse_ip_hdr: Collapses ip header.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @ip: ip header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @tcp: tcp header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @lro: lro pointer
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: Hal context.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__hal_collapse_ip_hdr ( iplro_t *ip,
a23fd118e437af0a7877dd313db8fdaa3537c675yl tcplro_t *tcp,
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro_t *lro,
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro->total_length += __hal_tcp_seg_len(ip, tcp);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* May be we have to handle time stamps or more options */
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * __hal_collapse_tcp_hdr: Collapses tcp header.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @ip: ip header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @tcp: tcp header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @lro: lro pointer
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: Hal context.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
a23fd118e437af0a7877dd313db8fdaa3537c675yl__hal_collapse_tcp_hdr ( iplro_t *ip,
a23fd118e437af0a7877dd313db8fdaa3537c675yl tcplro_t *tcp,
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro_t *lro,
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro->tcp_next_seq_num += __hal_tcp_seg_len(ip, tcp);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * __hal_append_lro: Appends new frame to existing LRO session.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @ip: ip header.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @tcp: IN tcp header, OUT tcp payload.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @seg_len: tcp payload length.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @lro: lro pointer
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: Hal context.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
a23fd118e437af0a7877dd313db8fdaa3537c675yl__hal_append_lro(iplro_t *ip,
a23fd118e437af0a7877dd313db8fdaa3537c675yl tcplro_t **tcp,
a23fd118e437af0a7877dd313db8fdaa3537c675yl u32 *seg_len,
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro_t *lro,
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_t *hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (void) __hal_collapse_ip_hdr(ip, *tcp, lro, hldev);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (void) __hal_collapse_tcp_hdr(ip, *tcp, lro, hldev);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl // Update mbuf chain will be done in ll driver.
a23fd118e437af0a7877dd313db8fdaa3537c675yl // xge_hal_accumulate_large_rx on success of appending new frame to
8347601bcb0a439f6e50fc36b4039a73d08700e1yl // lro will return to ll driver tcpdata pointer, and tcp payload length.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl // along with return code lro frame appended.
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro->sg_num++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl *seg_len = __hal_tcp_seg_len(ip, *tcp);
7eced415e5dd557aef2d78483b5a7785f0e13670xw *tcp = (tcplro_t *)((char *)*tcp + (((*tcp)->doff_res)>>2));
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
7eced415e5dd557aef2d78483b5a7785f0e13670xw * __xge_hal_accumulate_large_rx: LRO a given frame
a23fd118e437af0a7877dd313db8fdaa3537c675yl * frames
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @ring: rx ring number
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @eth_hdr: ethernet header.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @ip_hdr: ip header (optional)
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @tcp: tcp header.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @seglen: packet length.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @p_lro: lro pointer.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @ext_info: descriptor info, see xge_hal_dtr_info_t{}.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @hldev: HAL device.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @lro_end3: for lro_end3 output
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * LRO the newly received frame, i.e. attach it (if possible) to the
a23fd118e437af0a7877dd313db8fdaa3537c675yl * already accumulated (i.e., already LRO-ed) received frames (if any),
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * to form one super-sized frame for the subsequent processing
a23fd118e437af0a7877dd313db8fdaa3537c675yl * by the stack.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
7eced415e5dd557aef2d78483b5a7785f0e13670xwxge_hal_lro_process_rx(int ring, u8 *eth_hdr, u8 *ip_hdr, tcplro_t **tcp,
7eced415e5dd557aef2d78483b5a7785f0e13670xw u32 *seglen, lro_t **p_lro,
7eced415e5dd557aef2d78483b5a7785f0e13670xw xge_hal_dtr_info_t *ext_info, xge_hal_device_t *hldev,
7eced415e5dd557aef2d78483b5a7785f0e13670xw lro_t **lro_end3)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
7eced415e5dd557aef2d78483b5a7785f0e13670xw iplro_t *ip = (iplro_t *)ip_hdr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e ret;
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro_t *lro;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ring(XGE_TRACE, "Entered accumu lro. ");
7eced415e5dd557aef2d78483b5a7785f0e13670xw if (XGE_HAL_OK != __hal_lro_capable(eth_hdr, &ip, (tcplro_t **)tcp,
7eced415e5dd557aef2d78483b5a7785f0e13670xw ext_info))
a23fd118e437af0a7877dd313db8fdaa3537c675yl return XGE_HAL_INF_LRO_UNCAPABLE;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
7eced415e5dd557aef2d78483b5a7785f0e13670xw * This function shall get matching LRO or else
a23fd118e437af0a7877dd313db8fdaa3537c675yl * create one and return it
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
7eced415e5dd557aef2d78483b5a7785f0e13670xw ret = __hal_get_lro_session(eth_hdr, ip, (tcplro_t *)*tcp,
7eced415e5dd557aef2d78483b5a7785f0e13670xw p_lro, ext_info, hldev, &hldev->lro_desc[ring],
7eced415e5dd557aef2d78483b5a7785f0e13670xw lro_end3);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ring(XGE_TRACE, "ret from get_lro:%d ",ret);
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro = *p_lro;
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (XGE_HAL_INF_LRO_CONT == ret) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (XGE_HAL_OK == __hal_lro_under_optimal_thresh(ip,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (tcplro_t *)*tcp, lro, hldev)) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (void) __hal_append_lro(ip,(tcplro_t **) tcp, seglen,
7eced415e5dd557aef2d78483b5a7785f0e13670xw lro, hldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl hldev->stats.sw_dev_info_stats.tot_frms_lroised++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (lro->sg_num >= hldev->config.lro_sg_size) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev->stats.sw_dev_info_stats.lro_sg_exceed_cnt++;
7eced415e5dd557aef2d78483b5a7785f0e13670xw ret = XGE_HAL_INF_LRO_END_1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl } else ret = XGE_HAL_INF_LRO_END_2;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Since its time to flush,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * update ip header so that it can be sent up
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl if ((ret == XGE_HAL_INF_LRO_END_1) ||
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (ret == XGE_HAL_INF_LRO_END_2) ||
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (ret == XGE_HAL_INF_LRO_END_3)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro->ip_hdr->tot_len = xge_os_htons((*p_lro)->total_length);
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro->ip_hdr->check = xge_os_htons(0);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro->ip_hdr->check = XGE_LL_IP_FAST_CSUM(((u8 *)(lro->ip_hdr)),
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (lro->ip_hdr->version_ihl & 0x0F));
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro->tcp_hdr->ack_seq = lro->tcp_ack_num;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (ret);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw/**
7eced415e5dd557aef2d78483b5a7785f0e13670xw * xge_hal_accumulate_large_rx: LRO a given frame
7eced415e5dd557aef2d78483b5a7785f0e13670xw * frames
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @buffer: Ethernet frame.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @tcp: tcp header.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @seglen: packet length.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @p_lro: lro pointer.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @ext_info: descriptor info, see xge_hal_dtr_info_t{}.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @hldev: HAL device.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @lro_end3: for lro_end3 output
7eced415e5dd557aef2d78483b5a7785f0e13670xw *
7eced415e5dd557aef2d78483b5a7785f0e13670xw * LRO the newly received frame, i.e. attach it (if possible) to the
7eced415e5dd557aef2d78483b5a7785f0e13670xw * already accumulated (i.e., already LRO-ed) received frames (if any),
7eced415e5dd557aef2d78483b5a7785f0e13670xw * to form one super-sized frame for the subsequent processing
7eced415e5dd557aef2d78483b5a7785f0e13670xw * by the stack.
7eced415e5dd557aef2d78483b5a7785f0e13670xw */
7eced415e5dd557aef2d78483b5a7785f0e13670xw__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
7eced415e5dd557aef2d78483b5a7785f0e13670xwxge_hal_accumulate_large_rx(u8 *buffer, tcplro_t **tcp, u32 *seglen,
7eced415e5dd557aef2d78483b5a7785f0e13670xwlro_t **p_lro, xge_hal_dtr_info_t *ext_info, xge_hal_device_t *hldev,
7eced415e5dd557aef2d78483b5a7785f0e13670xwlro_t **lro_end3)
7eced415e5dd557aef2d78483b5a7785f0e13670xw{
7eced415e5dd557aef2d78483b5a7785f0e13670xw int ring = 0;
7eced415e5dd557aef2d78483b5a7785f0e13670xw return xge_hal_lro_process_rx(ring, buffer, NULL, tcp, seglen, p_lro,
7eced415e5dd557aef2d78483b5a7785f0e13670xw ext_info, hldev, lro_end3);
7eced415e5dd557aef2d78483b5a7785f0e13670xw}
7eced415e5dd557aef2d78483b5a7785f0e13670xw
a23fd118e437af0a7877dd313db8fdaa3537c675yl/**
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_lro_close_session: Close LRO session
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @lro: LRO Session.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * @hldev: HAL Context.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
8347601bcb0a439f6e50fc36b4039a73d08700e1ylxge_hal_lro_close_session (lro_t *lro)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lro->in_use = 0;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl}
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl/**
7eced415e5dd557aef2d78483b5a7785f0e13670xw * xge_hal_lro_next_session: Returns next LRO session in the list or NULL
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * if none exists.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @hldev: HAL Context.
7eced415e5dd557aef2d78483b5a7785f0e13670xw * @ring: rx ring number.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL lro_t *
7eced415e5dd557aef2d78483b5a7785f0e13670xwxge_hal_lro_next_session (xge_hal_device_t *hldev, int ring)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
7eced415e5dd557aef2d78483b5a7785f0e13670xwxge_hal_lro_desc_t *ring_lro = &hldev->lro_desc[ring];
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int i;
7eced415e5dd557aef2d78483b5a7785f0e13670xw int start_idx = ring_lro->lro_next_idx;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl for(i = start_idx; i < XGE_HAL_LRO_MAX_BUCKETS; i++) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw lro_t *lro = &ring_lro->lro_pool[i];
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (!lro->in_use)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl continue;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro->ip_hdr->tot_len = xge_os_htons(lro->total_length);
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro->ip_hdr->check = xge_os_htons(0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl lro->ip_hdr->check = XGE_LL_IP_FAST_CSUM(((u8 *)(lro->ip_hdr)),
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (lro->ip_hdr->version_ihl & 0x0F));
7eced415e5dd557aef2d78483b5a7785f0e13670xw ring_lro->lro_next_idx = i + 1;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return lro;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw ring_lro->lro_next_idx = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl return NULL;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
7eced415e5dd557aef2d78483b5a7785f0e13670xw
7eced415e5dd557aef2d78483b5a7785f0e13670xw__HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL lro_t *
7eced415e5dd557aef2d78483b5a7785f0e13670xwxge_hal_lro_get_next_session(xge_hal_device_t *hldev)
7eced415e5dd557aef2d78483b5a7785f0e13670xw{
7eced415e5dd557aef2d78483b5a7785f0e13670xw int ring = 0; /* assume default ring=0 */
7eced415e5dd557aef2d78483b5a7785f0e13670xw return xge_hal_lro_next_session(hldev, ring);
7eced415e5dd557aef2d78483b5a7785f0e13670xw}
a23fd118e437af0a7877dd313db8fdaa3537c675yl#endif