49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Copyright (c) 2008-2016 Solarflare Communications Inc.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * All rights reserved.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Redistribution and use in source and binary forms, with or without
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * modification, are permitted provided that the following conditions are met:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * 1. Redistributions of source code must retain the above copyright notice,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * this list of conditions and the following disclaimer.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * 2. Redistributions in binary form must reproduce the above copyright notice,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * this list of conditions and the following disclaimer in the documentation
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * and/or other materials provided with the distribution.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * The views and conclusions contained in the software and documentation are
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * those of the authors and should not be interpreted as representing official
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * policies, either expressed or implied, of the FreeBSD Project.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/types.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/sysmacros.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/ddi.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/sunddi.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/atomic.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/stream.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/strsun.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/strsubr.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/strft.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/ksynch.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/ethernet.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/crc32.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/pattr.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/cpu.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/ethernet.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <inet/ip.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <netinet/in.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <netinet/ip.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <netinet/tcp.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "sfxge.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "efx.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/* RXQ flush response timeout (in microseconds) */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#define SFXGE_RX_QFLUSH_USEC (2000000)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/* RXQ flush tries in the case of failure */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#define SFXGE_RX_QFLUSH_TRIES (5)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/* RXQ default packet buffer preallocation (number of packet buffers) */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#define SFXGE_RX_QPREALLOC (0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/* Receive packet DMA attributes */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic ddi_device_acc_attr_t sfxge_rx_packet_devacc = {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_DEVICE_ATTR_V0, /* devacc_attr_version */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_NEVERSWAP_ACC, /* devacc_attr_endian_flags */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_STRICTORDER_ACC /* devacc_attr_dataorder */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore};
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic ddi_dma_attr_t sfxge_rx_packet_dma_attr = {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DMA_ATTR_V0, /* dma_attr_version */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0, /* dma_attr_addr_lo */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0xffffffffffffffffull, /* dma_attr_addr_hi */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0xffffffffffffffffull, /* dma_attr_count_max */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_CPU_CACHE_SIZE, /* dma_attr_align */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0xffffffff, /* dma_attr_burstsizes */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 1, /* dma_attr_minxfer */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0xffffffffffffffffull, /* dma_attr_maxxfer */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0xffffffffffffffffull, /* dma_attr_seg */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 1, /* dma_attr_sgllen */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 1, /* dma_attr_granular */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0 /* dma_attr_flags */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore};
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/* Receive queue DMA attributes */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic ddi_device_acc_attr_t sfxge_rxq_devacc = {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_DEVICE_ATTR_V0, /* devacc_attr_version */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_NEVERSWAP_ACC, /* devacc_attr_endian_flags */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_STRICTORDER_ACC /* devacc_attr_dataorder */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore};
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic ddi_dma_attr_t sfxge_rxq_dma_attr = {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DMA_ATTR_V0, /* dma_attr_version */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0, /* dma_attr_addr_lo */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0xffffffffffffffffull, /* dma_attr_addr_hi */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0xffffffffffffffffull, /* dma_attr_count_max */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore EFX_BUF_SIZE, /* dma_attr_align */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0xffffffff, /* dma_attr_burstsizes */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 1, /* dma_attr_minxfer */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0xffffffffffffffffull, /* dma_attr_maxxfer */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0xffffffffffffffffull, /* dma_attr_seg */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 1, /* dma_attr_sgllen */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 1, /* dma_attr_granular */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore 0 /* dma_attr_flags */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore};
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/* Forward declaration */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void sfxge_rx_qpreallocate(sfxge_rxq_t *srp, int nprealloc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_packet_ctor(void *buf, void *arg, int kmflags)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_packet_t *srpp = buf;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = arg;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_info_t *dip = sp->s_dip;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int err;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sizeof (srpp->__srp_u1.__srp_s1), <=,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sizeof (srpp->__srp_u1.__srp_pad));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sizeof (srpp->__srp_u2.__srp_s2), <=,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sizeof (srpp->__srp_u2.__srp_pad));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore bzero(buf, sizeof (sfxge_rx_packet_t));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Allocate a DMA handle */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore err = ddi_dma_alloc_handle(dip, &sfxge_rx_packet_dma_attr,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (kmflags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore NULL, &(srpp->srp_dma_handle));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (err != DDI_SUCCESS)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, err);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_OBJ_CHECK(srpp, sfxge_rx_packet_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (-1);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_packet_dtor(void *buf, void *arg)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_packet_t *srpp = buf;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore _NOTE(ARGUNUSED(arg))
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Free the DMA handle */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_dma_free_handle(&(srpp->srp_dma_handle));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_dma_handle = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_OBJ_CHECK(srpp, sfxge_rx_packet_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qctor(void *buf, void *arg, int kmflags)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rxq_t *srp = buf;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efsys_mem_t *esmp = &(srp->sr_mem);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = arg;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_dma_buffer_attr_t dma_attr;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_t *srfppp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int nprealloc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int id;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Compile-time structure layout checks */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore EFX_STATIC_ASSERT(sizeof (srp->__sr_u1.__sr_s1) <=
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sizeof (srp->__sr_u1.__sr_pad));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore EFX_STATIC_ASSERT(sizeof (srp->__sr_u2.__sr_s2) <=
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sizeof (srp->__sr_u2.__sr_pad));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore EFX_STATIC_ASSERT(sizeof (srp->__sr_u3.__sr_s3) <=
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sizeof (srp->__sr_u3.__sr_pad));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore bzero(buf, sizeof (sfxge_rxq_t));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_sp = sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dma_attr.sdba_dip = sp->s_dip;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dma_attr.sdba_dattrp = &sfxge_rxq_dma_attr;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dma_attr.sdba_callback = DDI_DMA_SLEEP;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dma_attr.sdba_length = EFX_RXQ_SIZE(sp->s_rxq_size);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dma_attr.sdba_memflags = DDI_DMA_CONSISTENT;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dma_attr.sdba_devaccp = &sfxge_rxq_devacc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dma_attr.sdba_bindflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dma_attr.sdba_maxcookies = 1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dma_attr.sdba_zeroinit = B_FALSE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Allocate some buffer table entries */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_sram_buf_tbl_alloc(sp, EFX_RXQ_NBUFS(sp->s_rxq_size),
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore &(srp->sr_id))) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Allocate the context array */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((srp->sr_srpp = kmem_zalloc(sizeof (sfxge_rx_packet_t *) *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rxq_size, kmflags)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Allocate the flow table */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((srp->sr_flow = kmem_zalloc(sizeof (sfxge_rx_flow_t) *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_MAX_FLOW, kmflags)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail4;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_srfpp = &(srp->sr_srfp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_rto = drv_usectohz(200000);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_mpp = &(srp->sr_mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Initialize the free packet pool */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp = &(srp->sr_fpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((srfppp->srfpp_putp = kmem_zalloc(SFXGE_CPU_CACHE_SIZE *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_RX_FPP_NSLOTS, kmflags)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail5;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (id = 0; id < SFXGE_RX_FPP_NSLOTS; id++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_putlist_t *putp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t off;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore off = id * SFXGE_CPU_CACHE_SIZE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore putp = (void *)(srfppp->srfpp_putp + off);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore putp->srfpl_putp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore putp->srfpl_putpp = &(putp->srfpl_putp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_init(&(putp->srfpl_lock), NULL, MUTEX_DRIVER,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_INTR_PRI(sp->s_intr.si_intr_pri));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore cv_init(&(srp->sr_flush_kv), NULL, CV_DRIVER, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Preallocate some packets on the free packet pool */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore nprealloc = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_PROP_DONTPASS, "rx_prealloc_pkt_buffers", SFXGE_RX_QPREALLOC);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qpreallocate(srp, nprealloc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail5:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail5);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_mpp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_rto = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_srfpp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Free the flow table */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(srp->sr_flow, sizeof (sfxge_rx_flow_t) *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_MAX_FLOW);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_flow = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail4:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail4);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Free the context array */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(srp->sr_srpp, sizeof (sfxge_rx_packet_t *) *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rxq_size);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_srpp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail3:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail3);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Free the buffer table entries */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_sram_buf_tbl_free(sp, srp->sr_id,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore EFX_RXQ_NBUFS(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_id = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Remove dma setup */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_dma_buffer_destroy(esmp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_sp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_OBJ_CHECK(srp, sfxge_rxq_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (-1);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qdtor(void *buf, void *arg)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rxq_t *srp = buf;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efsys_mem_t *esmp = &(srp->sr_mem);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int id;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore _NOTE(ARGUNUSED(arg))
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore cv_destroy(&(srp->sr_flush_kv));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Tear down the free packet pool */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (id = 0; id < SFXGE_RX_FPP_NSLOTS; id++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_putlist_t *putp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t off;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore off = id * SFXGE_CPU_CACHE_SIZE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore putp = (void *)(srfppp->srfpp_putp + off);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore putp->srfpl_putpp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_destroy(&(putp->srfpl_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_OBJ_CHECK(putp, sfxge_rx_fpp_putlist_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(srfppp->srfpp_putp, SFXGE_CPU_CACHE_SIZE *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_RX_FPP_NSLOTS);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_putp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_mpp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_rto = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_srfpp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Free the flow table */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(srp->sr_flow, sizeof (sfxge_rx_flow_t) *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_MAX_FLOW);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_flow = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Free the context array */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(srp->sr_srpp, sizeof (sfxge_rx_packet_t *) *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rxq_size);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_srpp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Free the buffer table entries */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_sram_buf_tbl_free(sp, srp->sr_id,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore EFX_RXQ_NBUFS(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_id = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Tear down dma setup */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_dma_buffer_destroy(esmp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_OBJ_CHECK(srp, sfxge_rxq_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/* Note: This function takes ownership of *srpp. */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic inline void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qfpp_put(sfxge_rxq_t *srp, sfxge_rx_packet_t *srpp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *mp = srpp->srp_mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int id;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t off;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_putlist_t *putp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(mp->b_next, ==, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(mp->b_prev, ==, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore id = CPU->cpu_seqid & SFXGE_RX_FPP_MASK;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore off = id * SFXGE_CPU_CACHE_SIZE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(srpp->srp_putp, ==, srfppp->srfpp_putp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore putp = (void *)(srpp->srp_putp + off);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(putp->srfpl_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore putp->srfpl_count++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *putp->srfpl_putpp = mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore putp->srfpl_putpp = &(mp->b_next);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(putp->srfpl_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic unsigned int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qfpp_swizzle(sfxge_rxq_t *srp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index = srp->sr_index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int start;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int id;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *p;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t **pp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int loaned;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sep->se_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* We want to access the put list for the current CPU last */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore id = start = (CPU->cpu_seqid + 1) & SFXGE_RX_FPP_MASK;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore do {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_putlist_t *putp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t off;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore off = id * SFXGE_CPU_CACHE_SIZE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore id = (id + 1) & SFXGE_RX_FPP_MASK;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore putp = (void *)(srfppp->srfpp_putp + off);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Acquire the put list */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(putp->srfpl_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore p = putp->srfpl_putp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore pp = putp->srfpl_putpp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore count = putp->srfpl_count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore putp->srfpl_putp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore putp->srfpl_putpp = &(putp->srfpl_putp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore putp->srfpl_count = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(putp->srfpl_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (p == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore continue;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Add the list to the head of the get list */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *pp = srfppp->srfpp_get;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_get = p;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Adjust the counters */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srfppp->srfpp_loaned, >=, count);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_loaned -= count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_count += count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#if 0
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* NOTE: this probe is disabled because it is expensive!! */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE2(count,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int, (id - 1) & SFXGE_RX_FPP_MASK,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int, count);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#endif
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore } while (id != start);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Return the number of packets yet to appear in the put list */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore loaned = srfppp->srfpp_loaned;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (loaned);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#define DB_FRTNP(mp) ((mp)->b_datap->db_frtnp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qfpp_empty(sfxge_rxq_t *srp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index = srp->sr_index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_t *srfppp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(sep->se_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp = &(srp->sr_fpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Swizzle put list to get list */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) sfxge_rx_qfpp_swizzle(srp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srfppp->srfpp_loaned, ==, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp = srfppp->srfpp_get;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_get = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Free the remainder */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (mp != NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore frtn_t *freep;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_packet_t *srpp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore next = mp->b_next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp->b_next = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srfppp->srfpp_count, >, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_count--;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freep = DB_FRTNP(mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * ASSERT3P(freep->free_func, ==, sfxge_rx_qpacket_free);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * is implied by srpp test below
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*LINTED*/
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp = (sfxge_rx_packet_t *)(freep->free_arg);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(srpp->srp_mp, ==, mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(mp->b_cont, ==, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_recycle = B_FALSE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freeb(mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp = next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srfppp->srfpp_count, ==, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_min = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(sep->se_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * This is an estimate of all memory consumed per RX packet
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * it can be inaccurate but but sp->s_rx_pkt_mem_alloc mustn't drift
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic uint64_t
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_pkt_mem_approx(const sfxge_rx_packet_t *srpp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (srpp->srp_mblksize + sizeof (mblk_t) + sizeof (dblk_t) +
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sizeof (sfxge_rx_packet_t));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qpacket_destroy(sfxge_rxq_t *srp, sfxge_rx_packet_t *srpp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int64_t delta = sfxge_rx_pkt_mem_approx(srpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(!(srpp->srp_recycle));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(srpp->srp_mp, ==, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_off = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_thp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_iphp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_etherhp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_size = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_flags = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore bzero(&(srpp->srp_free), sizeof (frtn_t));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_mblksize = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_base = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Unbind the DMA memory from the DMA handle */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_addr = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) ddi_dma_unbind_handle(srpp->srp_dma_handle);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Free the DMA memory */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_base = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_dma_mem_free(&(srpp->srp_acc_handle));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_acc_handle = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_putp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_srp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_cache_free(sp->s_rpc, srpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_rx_pkt_mem_max)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore atomic_add_64(&sp->s_rx_pkt_mem_alloc, -delta);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qpacket_free(void *arg)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_packet_t *srpp = arg;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rxq_t *srp = srpp->srp_srp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * WARNING "man -s 9f esballoc" states:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * => runs sync from the thread calling freeb()
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * => must not sleep, or access data structures that could be freed
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Check whether we want to recycle the receive packets */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srpp->srp_recycle) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore frtn_t *freep;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freep = &(srpp->srp_free);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(freep->free_func, ==, sfxge_rx_qpacket_free);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(freep->free_arg, ==, (caddr_t)srpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Allocate a matching mblk_t before the current one is
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * freed.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size = srpp->srp_mblksize;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((mp = desballoc(srpp->srp_base, size, BPRI_HI,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freep)) != NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_mp = mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* NORMAL recycled case */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qfpp_put(srp, srpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_mp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qpacket_destroy(srp, srpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic sfxge_rx_packet_t *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qpacket_create(sfxge_rxq_t *srp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_packet_t *srpp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore caddr_t base;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t unit;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_dma_cookie_t dmac;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int ncookies;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore frtn_t *freep;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int err;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size = sp->s_rx_buffer_size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_rx_pkt_mem_max &&
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (sp->s_rx_pkt_mem_alloc + size >= sp->s_rx_pkt_mem_max)) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(rx_pkt_mem_max);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_kstat.srk_rx_pkt_mem_limit++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Allocate a new packet */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((srpp = kmem_cache_alloc(sp->s_rpc, KM_NOSLEEP)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_kstat.srk_kcache_alloc_nomem++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_srp = srp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_putp = srfppp->srfpp_putp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Allocate some DMA memory */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore err = ddi_dma_mem_alloc(srpp->srp_dma_handle, size,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore &sfxge_rx_packet_devacc, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore NULL, &base, &unit, &(srpp->srp_acc_handle));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore switch (err) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case DDI_SUCCESS:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case DDI_FAILURE:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_kstat.srk_dma_alloc_nomem++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore default:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_kstat.srk_dma_alloc_fail++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = EFAULT;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Adjust the buffer to align the start of the DMA area correctly */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore base += sp->s_rx_buffer_align;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size -= sp->s_rx_buffer_align;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Bind the DMA memory to the DMA handle */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore err = ddi_dma_addr_bind_handle(srpp->srp_dma_handle, NULL,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore base, size, DDI_DMA_READ | DDI_DMA_STREAMING,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_DMA_DONTWAIT, NULL, &dmac, &ncookies);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore switch (err) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case DDI_DMA_MAPPED:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case DDI_DMA_INUSE:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_kstat.srk_dma_bind_fail++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = EEXIST;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case DDI_DMA_NORESOURCES:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_kstat.srk_dma_bind_nomem++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case DDI_DMA_NOMAPPING:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_kstat.srk_dma_bind_fail++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOTSUP;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case DDI_DMA_TOOBIG:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_kstat.srk_dma_bind_fail++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = EFBIG;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore default:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_kstat.srk_dma_bind_fail++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = EFAULT;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(ncookies, ==, 1);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_addr = dmac.dmac_laddress;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_base = (unsigned char *)base;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_mblksize = size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Allocate a STREAMS block: We use size 1 so that the allocator will
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * use the first (and smallest) dblk cache.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freep = &(srpp->srp_free);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freep->free_func = sfxge_rx_qpacket_free;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freep->free_arg = (caddr_t)srpp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((mp = desballoc(srpp->srp_base, size, BPRI_HI, freep)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_kstat.srk_desballoc_fail++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail4;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_mp = mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_recycle = B_TRUE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_rx_pkt_mem_max) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int64_t delta = sfxge_rx_pkt_mem_approx(srpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore atomic_add_64(&sp->s_rx_pkt_mem_alloc, delta);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (srpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail4:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail4);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore bzero(&(srpp->srp_free), sizeof (frtn_t));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_mblksize = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_base = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Unbind the DMA memory from the DMA handle */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_addr = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) ddi_dma_unbind_handle(srpp->srp_dma_handle);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail3:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail3);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Free the DMA memory */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_dma_mem_free(&(srpp->srp_acc_handle));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_acc_handle = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_putp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_srp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_cache_free(sp->s_rpc, srpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#define SFXGE_REFILL_BATCH 64
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/* Try to refill the RX descriptor ring from the associated free pkt pool */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qrefill(sfxge_rxq_t *srp, unsigned int target)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index = srp->sr_index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efsys_dma_addr_t addr[SFXGE_REFILL_BATCH];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int ntodo;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int batch;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int rxfill;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int mblksize;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore prefetch_read_many(sp->s_enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore prefetch_read_many(srp->sr_erp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sep->se_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srp->sr_state != SFXGE_RXQ_STARTED)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rxfill = srp->sr_added - srp->sr_completed;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(rxfill, <=, EFX_RXQ_LIMIT(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ntodo = min(EFX_RXQ_LIMIT(sp->s_rxq_size) - rxfill, target);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(ntodo, <=, EFX_RXQ_LIMIT(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (ntodo == 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto out;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) sfxge_rx_qfpp_swizzle(srp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp = srfppp->srfpp_get;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore count = srfppp->srfpp_count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblksize = sp->s_rx_buffer_size - sp->s_rx_buffer_align;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore batch = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (ntodo-- > 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore frtn_t *freep;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_packet_t *srpp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int id;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (mp == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore next = mp->b_next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp->b_next = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (next != NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore prefetch_read_many(next);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freep = DB_FRTNP(mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*LINTED*/
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp = (sfxge_rx_packet_t *)(freep->free_arg);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(srpp->srp_mp, ==, mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* The MTU may have changed since the packet was allocated */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (MBLKSIZE(mp) != mblksize) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_recycle = B_FALSE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freeb(mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore --count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp = next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore continue;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_off = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_thp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_iphp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_etherhp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_size = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_flags = EFX_DISCARD;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore id = (srp->sr_added + batch) & (sp->s_rxq_size - 1);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(srp->sr_srpp[id] == NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_srpp[id] = srpp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore addr[batch++] = srpp->srp_addr;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (batch == SFXGE_REFILL_BATCH) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_rx_qpost(srp->sr_erp, addr, mblksize, batch,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_completed, srp->sr_added);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_added += batch;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore batch = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore --count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp = next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_get = mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_count = count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (batch != 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_rx_qpost(srp->sr_erp, addr, mblksize, batch,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_completed, srp->sr_added);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_added += batch;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_rx_qpush(srp->sr_erp, srp->sr_added, &srp->sr_pushed);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreout:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfppp->srfpp_count < srfppp->srfpp_min)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_min = srfppp->srfpp_count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/* Preallocate packets and put them in the free packet pool */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qpreallocate(sfxge_rxq_t *srp, int nprealloc)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_t *srfppp = &((srp)->sr_fpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_lowat = nprealloc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (nprealloc-- > 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_packet_t *srpp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((srpp = sfxge_rx_qpacket_create(srp)) == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qfpp_put(srp, srpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/* Try to refill the RX descriptor ring by allocating new packets */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qfill(sfxge_rxq_t *srp, unsigned int target)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index = srp->sr_index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int batch;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int rxfill;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int mblksize;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int ntodo;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efsys_dma_addr_t addr[SFXGE_REFILL_BATCH];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *mp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore prefetch_read_many(sp->s_enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore prefetch_read_many(srp->sr_erp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sep->se_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srp->sr_state != SFXGE_RXQ_STARTED)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rxfill = srp->sr_added - srp->sr_completed;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(rxfill, <=, EFX_RXQ_LIMIT(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ntodo = min(EFX_RXQ_LIMIT(sp->s_rxq_size) - rxfill, target);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(ntodo, <=, EFX_RXQ_LIMIT(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (ntodo == 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblksize = sp->s_rx_buffer_size - sp->s_rx_buffer_align;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore batch = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (ntodo-- > 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_packet_t *srpp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int id;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((srpp = sfxge_rx_qpacket_create(srp)) == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp = srpp->srp_mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(MBLKSIZE(mp), ==, mblksize);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srpp->srp_off, ==, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(srpp->srp_thp, ==, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(srpp->srp_iphp, ==, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(srpp->srp_etherhp, ==, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srpp->srp_size, ==, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_flags = EFX_DISCARD;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore id = (srp->sr_added + batch) & (sp->s_rxq_size - 1);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(srp->sr_srpp[id] == NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_srpp[id] = srpp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore addr[batch++] = srpp->srp_addr;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (batch == SFXGE_REFILL_BATCH) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_rx_qpost(srp->sr_erp, addr, mblksize, batch,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_completed, srp->sr_added);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_added += batch;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore batch = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (batch != 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_rx_qpost(srp->sr_erp, addr, mblksize, batch,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_completed, srp->sr_added);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_added += batch;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_rx_qpush(srp->sr_erp, srp->sr_added, &srp->sr_pushed);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorevoid
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qfpp_trim(sfxge_rxq_t *srp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index = srp->sr_index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *p;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t **pp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sep->se_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srp->sr_state != SFXGE_RXQ_STARTED)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto done;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Make sure the queue is full */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qrefill(srp, EFX_RXQ_LIMIT(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* The refill may have emptied the pool */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfppp->srfpp_min == 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto done;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Don't trim below the pool's low water mark */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfppp->srfpp_count <= srfppp->srfpp_lowat)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto done;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(srfppp->srfpp_min <= srfppp->srfpp_count);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Trim to the largest of srfppp->srfpp_min and srfpp->srfpp_lowat */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfppp->srfpp_lowat > srfppp->srfpp_min)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore count = srfppp->srfpp_count - srfppp->srfpp_lowat;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore else
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore count = srfppp->srfpp_count - srfppp->srfpp_min;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Walk the get list */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore pp = &(srfppp->srfpp_get);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (--count >= 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(pp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore p = *pp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(p != NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore pp = &(p->b_next);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(pp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore p = *pp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Truncate the get list */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *pp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Free the remainder */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (p != NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore frtn_t *freep;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_packet_t *srpp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore next = p->b_next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore p->b_next = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srfppp->srfpp_min, >, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_min--;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_count--;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freep = DB_FRTNP(p);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*LINTED*/
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp = (sfxge_rx_packet_t *)(freep->free_arg);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(srpp->srp_mp, ==, p);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_recycle = B_FALSE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freeb(p);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore p = next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoredone:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_min = srfppp->srfpp_count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qpoll(void *arg)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rxq_t *srp = arg;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index = srp->sr_index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore uint16_t magic;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * man timeout(9f) states that this code should adhere to the
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * same requirements as a softirq handler - DO NOT BLOCK
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Post an event to the event queue to cause the free packet pool to be
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * trimmed if it is oversize.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore magic = SFXGE_MAGIC_RX_QFPP_TRIM | index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#if defined(DEBUG)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* This is guaranteed due to the start/stop order of rx and ev */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sep->se_state, ==, SFXGE_EVQ_STARTED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_STARTED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#else
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Bug22691 WORKAROUND:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * This handler has been observed in the field to be invoked for a
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * queue in the INITIALIZED state, which should never happen.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Until the mechanism for this is properly understood, add defensive
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * checks.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((sep->se_state != SFXGE_EVQ_STARTED) ||
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (srp->sr_state != SFXGE_RXQ_STARTED) ||
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (!sep->se_eep)) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_err(sp->s_dip, CE_WARN, SFXGE_CMN_ERR
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore "RXQ[%d] bad state in sfxge_rx_qpoll %d %d %p",
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore index, sep->se_state, srp->sr_state, sep->se_eep);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#endif
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_ev_qpost(sep->se_eep, magic);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_tid = timeout(sfxge_rx_qpoll, srp,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore drv_usectohz(sp->s_rxq_poll_usec));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qpoll_start(sfxge_rxq_t *srp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index = srp->sr_index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sep->se_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_STARTED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Schedule a poll */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(srp->sr_tid, ==, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_tid = timeout(sfxge_rx_qpoll, srp, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qpoll_stop(sfxge_rxq_t *srp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index = srp->sr_index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore timeout_id_t tid;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sep->se_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_STARTED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Cancel the qpoll timer. Care is needed as this function
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * can race with sfxge_rx_qpoll() for timeout id updates.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Do not hold locks used by any timeout(9f) handlers across
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * calls to untimeout(9f) as this will deadlock.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore tid = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while ((srp->sr_tid != 0) && (srp->sr_tid != tid)) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore tid = srp->sr_tid;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) untimeout(tid);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_tid = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_kstat_update(kstat_t *ksp, int rw)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rxq_t *srp = ksp->ks_private;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index = srp->sr_index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_t *knp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (rw != KSTAT_READ) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = EACCES;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sep->se_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srp->sr_state != SFXGE_RXQ_STARTED)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto done;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp = ksp->ks_data;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* NB pointer post-increment below */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++->value.ui32 = srp->sr_kstat.srk_rx_pkt_mem_limit;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++->value.ui32 = srp->sr_kstat.srk_kcache_alloc_nomem;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++->value.ui32 = srp->sr_kstat.srk_dma_alloc_nomem;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++->value.ui32 = srp->sr_kstat.srk_dma_alloc_fail;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++->value.ui32 = srp->sr_kstat.srk_dma_bind_nomem;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++->value.ui32 = srp->sr_kstat.srk_dma_bind_fail;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++->value.ui32 = srp->sr_kstat.srk_desballoc_fail;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++->value.ui32 = srp->sr_kstat.srk_rxq_empty_discard;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoredone:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_kstat_init(sfxge_rxq_t *srp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index = srp->sr_index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_info_t *dip = sp->s_dip;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore char name[MAXNAMELEN];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_t *ksp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_t *knp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Create the set */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) snprintf(name, MAXNAMELEN - 1, "%s_rxq%04d",
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_driver_name(dip), index);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((ksp = kstat_create((char *)ddi_driver_name(dip),
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_get_instance(dip), name, "rxq", KSTAT_TYPE_NAMED,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_RX_NSTATS, 0)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_ksp = ksp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ksp->ks_update = sfxge_rx_kstat_update;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ksp->ks_private = srp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ksp->ks_lock = &(sep->se_lock);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Initialise the named stats */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp = ksp->ks_data;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_init(knp, "rx_pkt_mem_limit", KSTAT_DATA_UINT32);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_init(knp, "kcache_alloc_nomem", KSTAT_DATA_UINT32);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_init(knp, "dma_alloc_nomem", KSTAT_DATA_UINT32);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_init(knp, "dma_alloc_fail", KSTAT_DATA_UINT32);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_init(knp, "dma_bind_nomem", KSTAT_DATA_UINT32);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_init(knp, "dma_bind_fail", KSTAT_DATA_UINT32);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_init(knp, "desballoc_fail", KSTAT_DATA_UINT32);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_init(knp, "rxq_empty_discard", KSTAT_DATA_UINT32);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_install(ksp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qinit(sfxge_t *sp, unsigned int index)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rxq_t *srp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(index, <, SFXGE_RX_SCALE_MAX);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((srp = kmem_cache_alloc(sp->s_rqc, KM_SLEEP)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_UNINITIALIZED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_index = index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_srp[index] = srp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_rx_kstat_init(srp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_state = SFXGE_RXQ_INITIALIZED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_cache_free(sp->s_rqc, srp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qstart(sfxge_t *sp, unsigned int index)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rxq_t *srp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efsys_mem_t *esmp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nic_t *enp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int level;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(sep->se_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp = sp->s_srp[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore enp = sp->s_enp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore esmp = &(srp->sr_mem);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_INITIALIZED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sep->se_state, ==, SFXGE_EVQ_STARTED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Zero the memory */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore bzero(esmp->esm_base, EFX_RXQ_SIZE(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Program the buffer table */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_sram_buf_tbl_set(sp, srp->sr_id, esmp,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore EFX_RXQ_NBUFS(sp->s_rxq_size))) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Create the receive queue */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = efx_rx_qcreate(enp, index, index, EFX_RXQ_TYPE_DEFAULT,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore esmp, sp->s_rxq_size, srp->sr_id, sep->se_eep, &(srp->sr_erp)))
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Enable the receive queue */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_rx_qenable(srp->sr_erp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Set the water marks */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_hiwat = EFX_RXQ_LIMIT(sp->s_rxq_size) * 9 / 10;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_lowat = srp->sr_hiwat / 2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_state = SFXGE_RXQ_STARTED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_flush = SFXGE_FLUSH_INACTIVE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qpoll_start(srp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Try to fill the queue from the pool */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qrefill(srp, EFX_RXQ_LIMIT(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * If there were insufficient buffers in the pool to reach the at
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * least a batch then allocate some.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore level = srp->sr_added - srp->sr_completed;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (level < SFXGE_RX_BATCH)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qfill(srp, SFXGE_RX_BATCH);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(sep->se_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Clear entries from the buffer table */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_sram_buf_tbl_clear(sp, srp->sr_id,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore EFX_RXQ_NBUFS(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(sep->se_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qflow_complete(sfxge_rxq_t *srp, sfxge_rx_flow_t *srfp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct ether_header *etherhp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct ip *iphp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct tcphdr *thp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_mp == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp = srfp->srf_mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore etherhp = srfp->srf_etherhp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore iphp = srfp->srf_iphp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore thp = srfp->srf_last_thp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(((etherhp->ether_type == htons(ETHERTYPE_VLAN)) ?
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sizeof (struct ether_vlan_header) :
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sizeof (struct ether_header)) +
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_len, ==, msgdsize(mp));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srfp->srf_len & 0xffff, ==, srfp->srf_len);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore iphp->ip_len = htons(srfp->srf_len);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_first_thp->th_ack = thp->th_ack;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_first_thp->th_win = thp->th_win;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_first_thp->th_flags = thp->th_flags;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE2(flow_complete, uint32_t, srfp->srf_tag,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t, srfp->srf_len);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_mp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_len = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mp->b_next == NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *(srp->sr_mpp) = mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_mpp = &(mp->b_next);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic boolean_t
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qflow_add(sfxge_rxq_t *srp, sfxge_rx_flow_t *srfp,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_packet_t *srpp, clock_t now)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct ether_header *etherhp = srpp->srp_etherhp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct ip *iphp = srpp->srp_iphp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct tcphdr *thp = srpp->srp_thp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t off = srpp->srp_off;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t size = (size_t)(srpp->srp_size);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *mp = srpp->srp_mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore uint32_t seq;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int shift;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(MBLKL(mp), ==, off + size);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(DB_CKSUMFLAGS(mp), ==,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore HCK_FULLCKSUM | HCK_FULLCKSUM_OK | HCK_IPV4_HDRCKSUM);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore seq = htonl(thp->th_seq);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * If the time between this segment and the last is greater than RTO
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * then consider this a new flow.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (now - srfp->srf_lbolt > srp->sr_rto) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_count = 1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_seq = seq + size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (seq != srfp->srf_seq) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_count > SFXGE_SLOW_START)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_count = SFXGE_SLOW_START;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_count >>= 1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_count++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_seq = seq + size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Update the in-order segment count and sequence number */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_count++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_seq = seq + size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Don't merge across pure ACK, URG, SYN or RST segments */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (size == 0 || thp->th_flags & (TH_URG | TH_SYN | TH_RST) ||
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore thp->th_urp != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * If the in-order segment count has not yet reached the slow-start
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * threshold then we cannot coalesce.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_count < SFXGE_SLOW_START)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail4;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Scale up the packet size from 4k (the maximum being 64k) */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srfp->srf_count, >=, SFXGE_SLOW_START);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore shift = MIN(srfp->srf_count - SFXGE_SLOW_START + 12, 16);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_len + size >= (1 << shift))
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qflow_complete(srp, srfp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mp->b_cont == NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_mp == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* First packet in this flow */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_etherhp = etherhp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_iphp = iphp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_first_thp = srfp->srf_last_thp = thp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(mp->b_cont, ==, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_mp = mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_mpp = &(mp->b_cont);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_len = ntohs(iphp->ip_len);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * If the flow is not already in the list of occupied flows then
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * add it.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_next == NULL &&
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_srfpp != &(srfp->srf_next)) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *(srp->sr_srfpp) = srfp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_srfpp = &(srfp->srf_next);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore } else {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Later packet in this flow - skip TCP header */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_last_thp = thp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp->b_rptr += off;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(MBLKL(mp), ==, size);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(mp->b_cont, ==, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *(srfp->srf_mpp) = mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_mpp = &(mp->b_cont);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_len += size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(srfp->srf_next != NULL ||
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_srfpp == &(srfp->srf_next));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE2(flow_add, uint32_t, srfp->srf_tag, size_t, size);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Try to align coalesced segments on push boundaries, unless they
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * are too frequent.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_rx_coalesce_mode == SFXGE_RX_COALESCE_ALLOW_PUSH &&
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore thp->th_flags & TH_PUSH)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qflow_complete(srp, srfp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_lbolt = now;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (B_TRUE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail4:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail3:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qflow_complete(srp, srfp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_lbolt = now;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (B_FALSE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorevoid
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qpacket_coalesce(sfxge_rxq_t *srp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore clock_t now;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_flow_t *srfp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(sp->s_rx_coalesce_mode != SFXGE_RX_COALESCE_OFF);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore now = ddi_get_lbolt();
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp = srp->sr_mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_mp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_mpp = &(srp->sr_mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Start with the last flow to be appended to */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp = *(srp->sr_srfpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (mp != NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore frtn_t *freep;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_packet_t *srpp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct ether_header *etherhp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct ip *iphp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct tcphdr *thp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t off;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore uint16_t ether_tci;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore uint32_t hash;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore uint32_t tag;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_packet_type_t pkt_type;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore uint16_t sport, dport;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore next = mp->b_next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp->b_next = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (next != NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore prefetch_read_many(next);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freep = DB_FRTNP(mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*LINTED*/
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp = (sfxge_rx_packet_t *)(freep->free_arg);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(srpp->srp_mp, ==, mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* If the packet is not TCP then we cannot coalesce it */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (~(srpp->srp_flags) & EFX_PKT_TCP)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto reject;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * If the packet is not fully checksummed then we cannot
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * coalesce it.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (~(srpp->srp_flags) & (EFX_CKSUM_TCPUDP | EFX_CKSUM_IPV4))
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto reject;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Parse the TCP header */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore pkt_type = sfxge_pkthdr_parse(mp, &etherhp, &iphp, &thp, &off,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore &size, &sport, &dport);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(pkt_type == SFXGE_PACKET_TYPE_IPV4_TCP);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(etherhp != NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(iphp != NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(thp != NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(off != 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((iphp->ip_off & ~htons(IP_DF)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto reject;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (etherhp->ether_type == htons(ETHERTYPE_VLAN)) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct ether_vlan_header *ethervhp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ethervhp = (struct ether_vlan_header *)etherhp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ether_tci = ethervhp->ether_tci;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore } else {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ether_tci = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Make sure any minimum length padding is stripped
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * before we try to add the packet to a flow.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sp->s_rx_prefix_size + MBLKL(mp), ==,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (size_t)(srpp->srp_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sp->s_rx_prefix_size + off + size, <=,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (size_t)(srpp->srp_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_rx_prefix_size + off + size <
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (size_t)(srpp->srp_size))
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp->b_wptr = mp->b_rptr + off + size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * If there is no current flow, or the segment does not match
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * the current flow then we must attempt to look up the
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * correct flow in the table.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto lookup;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_saddr != iphp->ip_src.s_addr ||
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_daddr != iphp->ip_dst.s_addr)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto lookup;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_sport != thp->th_sport ||
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_dport != thp->th_dport)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto lookup;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_tci != ether_tci)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto lookup;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreadd:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(srfp != NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_etherhp = etherhp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_iphp = iphp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_thp = thp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_off = off;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(size, <, (1 << 16));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_size = (uint16_t)size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Try to append the packet to the flow */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (!sfxge_rx_qflow_add(srp, srfp, srpp, now))
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto reject;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp = next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore continue;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorelookup:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * If there is a prefix area then read the hash from that,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * otherwise calculate it.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_rx_prefix_size != 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore hash = efx_psuedo_hdr_hash_get(sp->s_enp,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore EFX_RX_HASHALG_TOEPLITZ,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DB_BASE(mp));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore } else {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_TCP_HASH(sp,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore &iphp->ip_src.s_addr,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore thp->th_sport,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore &iphp->ip_dst.s_addr,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore thp->th_dport,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore hash);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp = &(srp->sr_flow[(hash >> 6) % SFXGE_MAX_FLOW]);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore tag = hash + 1; /* Make sure it's not zero */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * If the flow we have found does not match the hash then
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * it may be an unused flow, or it may be stale.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (tag != srfp->srf_tag) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_count != 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (now - srfp->srf_lbolt <= srp->sr_rto)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto reject;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_mp != NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto reject;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Start a new flow */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(srfp->srf_next == NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_tag = tag;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_saddr = iphp->ip_src.s_addr;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_daddr = iphp->ip_dst.s_addr;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_sport = thp->th_sport;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_dport = thp->th_dport;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_tci = ether_tci;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_count = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_seq = ntohl(thp->th_seq);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_lbolt = now;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto add;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * If the flow we have found does match the hash then it could
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * still be an alias.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_saddr != iphp->ip_src.s_addr ||
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_daddr != iphp->ip_dst.s_addr)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto reject;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_sport != thp->th_sport ||
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_dport != thp->th_dport)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto reject;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srfp->srf_tci != ether_tci)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto reject;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto add;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorereject:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *(srp->sr_mpp) = mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_mpp = &(mp->b_next);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp = next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorevoid
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qcomplete(sfxge_rxq_t *srp, boolean_t eop)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index = srp->sr_index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int completed;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fpp_t *srfppp = &(srp->sr_fpp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int level;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sep->se_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(srp->sr_mp == NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(srp->sr_mpp == &(srp->sr_mp));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore completed = srp->sr_completed;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (completed != srp->sr_pending) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int id;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_packet_t *srpp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore uint16_t flags;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore id = completed++ & (sp->s_rxq_size - 1);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srp->sr_pending - completed >= 4) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int prefetch;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore prefetch = (id + 4) & (sp->s_rxq_size - 1);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp = srp->sr_srpp[prefetch];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(srpp != NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp = srpp->srp_mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore prefetch_read_many(mp->b_datap);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore } else if (completed == srp->sr_pending) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore prefetch_read_many(srp->sr_mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp = srp->sr_srpp[id];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(srpp != NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_srpp[id] = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp = srpp->srp_mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mp->b_cont == NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* when called from sfxge_rx_qstop() */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srp->sr_state != SFXGE_RXQ_STARTED)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto discard;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srpp->srp_flags & (EFX_ADDR_MISMATCH | EFX_DISCARD))
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto discard;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Make the data visible to the kernel */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ddi_dma_sync(srpp->srp_dma_handle, 0,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_buffer_size, DDI_DMA_SYNC_FORKERNEL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(rc, ==, DDI_SUCCESS);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Read the length from the psuedo header if required */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srpp->srp_flags & EFX_PKT_PREFIX_LEN) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = efx_psuedo_hdr_pkt_length_get(sp->s_enp,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp->b_rptr,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore &srpp->srp_size);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(rc, ==, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_size += sp->s_rx_prefix_size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Set up the packet length */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(mp->b_rptr, ==, DB_BASE(mp));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp->b_rptr += sp->s_rx_prefix_size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore prefetch_read_many(mp->b_rptr);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(mp->b_wptr, ==, DB_BASE(mp));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp->b_wptr += (size_t)(srpp->srp_size);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3P(mp->b_wptr, <=, DB_LIM(mp));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Calculate the maximum packet size */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size = sp->s_mtu;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size += (srpp->srp_flags & EFX_PKT_VLAN_TAGGED) ?
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sizeof (struct ether_vlan_header) :
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sizeof (struct ether_header);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (MBLKL(mp) > size)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto discard;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Check for loopback packets */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (!(srpp->srp_flags & EFX_PKT_IPV4) &&
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore !(srpp->srp_flags & EFX_PKT_IPV6)) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct ether_header *etherhp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*LINTED*/
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore etherhp = (struct ether_header *)(mp->b_rptr);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (etherhp->ether_type ==
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore htons(SFXGE_ETHERTYPE_LOOPBACK)) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(loopback);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_loopback++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto discard;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Set up the checksum information */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore flags = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srpp->srp_flags & EFX_CKSUM_IPV4) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(srpp->srp_flags & EFX_PKT_IPV4);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore flags |= HCK_IPV4_HDRCKSUM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srpp->srp_flags & EFX_CKSUM_TCPUDP) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(srpp->srp_flags & EFX_PKT_TCP ||
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srpp->srp_flags & EFX_PKT_UDP);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore flags |= HCK_FULLCKSUM | HCK_FULLCKSUM_OK;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DB_CKSUMSTART(mp) = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DB_CKSUMSTUFF(mp) = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DB_CKSUMEND(mp) = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DB_CKSUMFLAGS(mp) = flags;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DB_CKSUM16(mp) = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Add the packet to the tail of the chain */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_loaned++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mp->b_next == NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *(srp->sr_mpp) = mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_mpp = &(mp->b_next);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore continue;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorediscard:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Return the packet to the pool */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfppp->srfpp_loaned++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freeb(mp); /* Equivalent to freemsg() as b_cont==0 */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_completed = completed;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Attempt to coalesce any TCP packets */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_rx_coalesce_mode != SFXGE_RX_COALESCE_OFF)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qpacket_coalesce(srp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * If there are any pending flows and this is the end of the
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * poll then they must be completed.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srp->sr_srfp != NULL && eop) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_flow_t *srfp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp = srp->sr_srfp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_srfp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_srfpp = &(srp->sr_srfp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore do {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_flow_t *next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore next = srfp->srf_next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp->srf_next = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qflow_complete(srp, srfp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srfp = next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore } while (srfp != NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore level = srp->sr_pushed - srp->sr_completed;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* If there are any packets then pass them up the stack */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srp->sr_mp != NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mp = srp->sr_mp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_mp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_mpp = &(srp->sr_mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (level == 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Try to refill ASAP */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qrefill(srp, EFX_RXQ_LIMIT(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore level = srp->sr_pushed - srp->sr_completed;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * If the RXQ is still empty, discard and recycle the
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * current entry to ensure that the ring always
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * contains at least one descriptor. This ensures that
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * the next hardware RX will trigger an event
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * (possibly delayed by interrupt moderation) and
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * trigger another refill/fill attempt.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Note this drops a complete LRO fragment from the
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * start of the batch.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Note also that copymsgchain() does not help with
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * resource starvation here, unless we are short of DMA
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * mappings.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (level == 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mblk_t *nmp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_kstat.srk_rxq_empty_discard++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(rxq_empty_discard, int, index);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore nmp = mp->b_next;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (nmp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_gld_rx_post(sp, index, nmp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* as level==0 will swizzle,rxpost below */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freemsg(mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore } else {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_gld_rx_post(sp, index, mp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Top up the queue if necessary */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (level < srp->sr_hiwat) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qrefill(srp, EFX_RXQ_LIMIT(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore level = srp->sr_added - srp->sr_completed;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (level < srp->sr_lowat)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qfill(srp, EFX_RXQ_LIMIT(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorevoid
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qflush_done(sfxge_rxq_t *srp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index = srp->sr_index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore boolean_t flush_pending;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sep->se_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Flush successful: wakeup sfxge_rx_qstop() if flush is pending.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * A delayed flush event received after RxQ stop has timed out
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * will be ignored, as then the flush state will not be PENDING
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * (see SFCbug22989).
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore flush_pending = (srp->sr_flush == SFXGE_FLUSH_PENDING);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_flush = SFXGE_FLUSH_DONE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (flush_pending)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore cv_broadcast(&(srp->sr_flush_kv));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorevoid
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qflush_failed(sfxge_rxq_t *srp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = srp->sr_sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index = srp->sr_index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore boolean_t flush_pending;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sep->se_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Flush failed: wakeup sfxge_rx_qstop() if flush is pending.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * A delayed flush event received after RxQ stop has timed out
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * will be ignored, as then the flush state will not be PENDING
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * (see SFCbug22989).
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore flush_pending = (srp->sr_flush == SFXGE_FLUSH_PENDING);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_flush = SFXGE_FLUSH_FAILED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (flush_pending)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore cv_broadcast(&(srp->sr_flush_kv));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qstop(sfxge_t *sp, unsigned int index)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_info_t *dip = sp->s_dip;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rxq_t *srp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore clock_t timeout;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int flush_tries = SFXGE_RX_QFLUSH_TRIES;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sp->s_state_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(sep->se_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp = sp->s_srp[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_STARTED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qpoll_stop(srp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Further packets are discarded by sfxge_rx_qcomplete() */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_state = SFXGE_RXQ_INITIALIZED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_hw_err != SFXGE_HW_OK) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Flag indicates possible hardware failure.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Attempt flush but do not wait for it to complete.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_flush = SFXGE_FLUSH_DONE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) efx_rx_qflush(srp->sr_erp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Wait upto 2sec for queue flushing to complete */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore timeout = ddi_get_lbolt() + drv_usectohz(SFXGE_RX_QFLUSH_USEC);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (srp->sr_flush != SFXGE_FLUSH_DONE && flush_tries-- > 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = efx_rx_qflush(srp->sr_erp)) != 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (rc == EALREADY)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_flush = SFXGE_FLUSH_DONE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore else
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_flush = SFXGE_FLUSH_FAILED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_flush = SFXGE_FLUSH_PENDING;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (cv_timedwait(&(srp->sr_flush_kv), &(sep->se_lock),
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore timeout) < 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Timeout waiting for successful or failed flush */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_err(dip, CE_NOTE,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_CMN_ERR "rxq[%d] flush timeout", index);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srp->sr_flush == SFXGE_FLUSH_FAILED)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_err(dip, CE_NOTE,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_CMN_ERR "rxq[%d] flush failed", index);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(flush, sfxge_flush_state_t, srp->sr_flush);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_flush = SFXGE_FLUSH_DONE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Destroy the receive queue */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_rx_qdestroy(srp->sr_erp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_erp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Clear entries from the buffer table */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_sram_buf_tbl_clear(sp, srp->sr_id,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore EFX_RXQ_NBUFS(sp->s_rxq_size));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Free any unused RX packets which had descriptors on the RXQ
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Packets will be discard as state != STARTED
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_pending = srp->sr_added;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qcomplete(srp, B_TRUE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srp->sr_completed, ==, srp->sr_pending);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_added = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_pushed = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_pending = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_completed = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_loopback = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_lowat = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_hiwat = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(sep->se_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_kstat_fini(sfxge_rxq_t *srp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_delete(srp->sr_ksp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_ksp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_qfini(sfxge_t *sp, unsigned int index)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rxq_t *srp = sp->s_srp[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srp->sr_state, ==, SFXGE_RXQ_INITIALIZED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_srp[index] = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_state = SFXGE_RXQ_UNINITIALIZED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_kstat_fini(srp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Empty the pool */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qfpp_empty(srp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srp->sr_index = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_cache_free(sp->s_rqc, srp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_scale_kstat_update(kstat_t *ksp, int rw)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = ksp->ks_private;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_t *sip = &(sp->s_intr);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_t *knp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int entry;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int *freq;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(srsp->srs_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (rw != KSTAT_READ) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = EACCES;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((freq = kmem_zalloc(sizeof (unsigned int) * sip->si_nalloc,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore KM_NOSLEEP)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (entry = 0; entry < SFXGE_RX_SCALE_MAX; entry++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore index = srsp->srs_tbl[entry];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore freq[index]++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp = ksp->ks_data;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (index = 0; index < sip->si_nalloc; index++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp->value.ui64 = freq[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp->value.ui64 = srsp->srs_count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(freq, sizeof (unsigned int) * sip->si_nalloc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_scale_kstat_init(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_info_t *dip = sp->s_dip;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_t *sip = &(sp->s_intr);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore char name[MAXNAMELEN];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_t *ksp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_t *knp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Create the set */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) snprintf(name, MAXNAMELEN - 1, "%s_rss", ddi_driver_name(dip));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((ksp = kstat_create((char *)ddi_driver_name(dip),
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_get_instance(dip), name, "rss", KSTAT_TYPE_NAMED,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sip->si_nalloc + 1, 0)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_ksp = ksp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ksp->ks_update = sfxge_rx_scale_kstat_update;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ksp->ks_private = sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ksp->ks_lock = &(srsp->srs_lock);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Initialise the named stats */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp = ksp->ks_data;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (index = 0; index < sip->si_nalloc; index++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore char name[MAXNAMELEN];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) snprintf(name, MAXNAMELEN - 1, "evq%04d_count", index);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_init(knp, name, KSTAT_DATA_UINT64);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_init(knp, "scale", KSTAT_DATA_UINT64);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_install(ksp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_scale_kstat_fini(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Destroy the set */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_delete(srsp->srs_ksp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_ksp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreunsigned int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_scale_prop_get(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rx_scale;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rx_scale = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_PROP_DONTPASS, "rx_scale_count", SFXGE_RX_SCALE_MAX);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* 0 and all -ve numbers sets to number of logical CPUs */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (rx_scale <= 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rx_scale = ncpus;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rx_scale);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_scale_init(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_t *sip = &(sp->s_intr);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srsp->srs_state, ==, SFXGE_RX_SCALE_UNINITIALIZED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Create tables for CPU, core, cache and chip counts */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_cpu = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_init(&(srsp->srs_lock), NULL, MUTEX_DRIVER, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* We need at least one event queue */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_count = sfxge_rx_scale_prop_get(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srsp->srs_count > sip->si_nalloc)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_count = sip->si_nalloc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srsp->srs_count < 1)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_count = 1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Set up the kstats */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_rx_scale_kstat_init(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_state = SFXGE_RX_SCALE_INITIALIZED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_destroy(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorevoid
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_scale_update(void *arg)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = arg;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_t *sip;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore processorid_t id;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int *tbl;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int *rating;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int entry;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srsp->srs_state != SFXGE_RX_SCALE_STARTED) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = EFAULT;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((tbl = kmem_zalloc(sizeof (unsigned int) * SFXGE_RX_SCALE_MAX,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore KM_NOSLEEP)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sip = &(sp->s_intr);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rating = kmem_zalloc(sizeof (unsigned int) * sip->si_nalloc,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore KM_NOSLEEP)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&cpu_lock);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Substract any current CPU, core, cache and chip usage from the
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * global contention tables.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (id = 0; id < NCPU; id++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sfxge_cpu[id], >=, srsp->srs_cpu[id]);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_cpu[id] -= srsp->srs_cpu[id];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_cpu[id] = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(srsp->srs_count != 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Choose as many event queues as we need */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (count = 0; count < srsp->srs_count; count++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int choice;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int choice_rating;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore bzero(rating, sizeof (unsigned int) * sip->si_nalloc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Rate each event queue on its global level of CPU
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * contention.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (index = 0; index < sip->si_nalloc; index++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sep = sp->s_sep[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore id = sep->se_cpu_id;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rating[index] += sfxge_cpu[id];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Choose the queue with the lowest CPU contention */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore choice = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore choice_rating = rating[0];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (index = 1; index < sip->si_nalloc; index++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (rating[index] < choice_rating) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore choice = index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore choice_rating = rating[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Add our choice to the condensed RSS table */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore tbl[count] = choice;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Add information to the global contention tables */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sep = sp->s_sep[choice];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore id = sep->se_cpu_id;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_cpu[id]++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_cpu[id]++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&cpu_lock);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Build the expanded RSS table */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore count = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (entry = 0; entry < SFXGE_RX_SCALE_MAX; entry++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore index = tbl[count];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore count = (count + 1) % srsp->srs_count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_tbl[entry] = index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Program the expanded RSS table into the hardware */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) efx_rx_scale_tbl_set(sp->s_enp, srsp->srs_tbl,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_RX_SCALE_MAX);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(rating, sizeof (unsigned int) * sip->si_nalloc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(tbl, sizeof (unsigned int) * SFXGE_RX_SCALE_MAX);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail3:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail3);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(tbl, sizeof (unsigned int) * SFXGE_RX_SCALE_MAX);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_scale_start(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srsp->srs_state, ==, SFXGE_RX_SCALE_INITIALIZED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Clear down the RSS table */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore bzero(srsp->srs_tbl, sizeof (unsigned int) * SFXGE_RX_SCALE_MAX);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) efx_rx_scale_tbl_set(sp->s_enp, srsp->srs_tbl,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_RX_SCALE_MAX);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_toeplitz_hash_init(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_state = SFXGE_RX_SCALE_STARTED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* sfxge_t->s_state_lock held */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) ddi_taskq_dispatch(sp->s_tqp, sfxge_rx_scale_update, sp,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_SLEEP);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreint
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_scale_count_get(sfxge_t *sp, unsigned int *countp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srsp->srs_state != SFXGE_RX_SCALE_INITIALIZED &&
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_state != SFXGE_RX_SCALE_STARTED) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOTSUP;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *countp = srsp->srs_count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreint
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_scale_count_set(sfxge_t *sp, unsigned int count)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_t *sip = &(sp->s_intr);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int dispatch = 1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (count < 1 || count > sip->si_nalloc) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = EINVAL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srsp->srs_state != SFXGE_RX_SCALE_INITIALIZED &&
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_state != SFXGE_RX_SCALE_STARTED) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOTSUP;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_count = count;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (srsp->srs_state != SFXGE_RX_SCALE_STARTED)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dispatch = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (dispatch)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* no locks held */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) ddi_taskq_dispatch(sp->s_tqp, sfxge_rx_scale_update, sp,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_SLEEP);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_scale_stop(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore processorid_t id;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srsp->srs_state, ==, SFXGE_RX_SCALE_STARTED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_state = SFXGE_RX_SCALE_INITIALIZED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&cpu_lock);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Substract any current CPU, core, cache and chip usage from the
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * global contention tables.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (id = 0; id < NCPU; id++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sfxge_cpu[id], >=, srsp->srs_cpu[id]);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_cpu[id] -= srsp->srs_cpu[id];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_cpu[id] = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&cpu_lock);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Clear down the RSS table */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore bzero(srsp->srs_tbl, sizeof (unsigned int) * SFXGE_RX_SCALE_MAX);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) efx_rx_scale_tbl_set(sp->s_enp, srsp->srs_tbl,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_RX_SCALE_MAX);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_scale_fini(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_t *srsp = &(sp->s_rx_scale);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(srsp->srs_state, ==, SFXGE_RX_SCALE_INITIALIZED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_state = SFXGE_RX_SCALE_UNINITIALIZED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Tear down the kstats */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_kstat_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_count = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_destroy(&(srsp->srs_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Destroy tables */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(srsp->srs_cpu, sizeof (unsigned int) * NCPU);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore srsp->srs_cpu = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_toeplitz_hash_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreint
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_init(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_t *sip = &(sp->s_intr);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore char name[MAXNAMELEN];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sip->si_state == SFXGE_INTR_UNINITIALIZED) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = EINVAL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_rx_scale_init(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) snprintf(name, MAXNAMELEN - 1, "%s%d_rx_packet_cache",
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rpc = kmem_cache_create(name, sizeof (sfxge_rx_packet_t),
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_CPU_CACHE_SIZE, sfxge_rx_packet_ctor, sfxge_rx_packet_dtor,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore NULL, sp, NULL, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(sp->s_rpc != NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) snprintf(name, MAXNAMELEN - 1, "%s%d_rxq_cache",
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rqc = kmem_cache_create(name, sizeof (sfxge_rxq_t),
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_CPU_CACHE_SIZE, sfxge_rx_qctor, sfxge_rx_qdtor, NULL, sp,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore NULL, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(sp->s_rqc != NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_pkt_mem_max = ddi_prop_get_int64(DDI_DEV_T_ANY, sp->s_dip,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_PROP_DONTPASS, "rx_pkt_mem_max", 0); /* disabled */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Initialize the receive queue(s) */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (index = 0; index < sip->si_nalloc; index++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_rx_qinit(sp, index)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_coalesce_mode = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_PROP_DONTPASS, "rx_coalesce_mode", SFXGE_RX_COALESCE_OFF);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail3:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail3);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Tear down the receive queue(s) */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (--index >= 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qfini(sp, index);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_cache_destroy(sp->s_rqc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rqc = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_cache_destroy(sp->s_rpc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rpc = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreint
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_start(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_mac_t *smp = &(sp->s_mac);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_t *sip;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const efx_nic_cfg_t *encp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t hdrlen, align;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(smp->sm_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Calculate the receive packet buffer size and alignment */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_buffer_size = EFX_MAC_PDU(sp->s_mtu);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore encp = efx_nic_cfg_get(sp->s_enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Packet buffer allocations are cache line aligned */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore EFSYS_ASSERT3U(encp->enc_rx_buf_align_start, <=, SFXGE_CPU_CACHE_SIZE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_family == EFX_FAMILY_HUNTINGTON) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_prefix_size = encp->enc_rx_prefix_size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore hdrlen = sp->s_rx_prefix_size + sizeof (struct ether_header);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Ensure IP headers are 32bit aligned */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_buffer_align = P2ROUNDUP(hdrlen, 4) - hdrlen;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_buffer_size += sp->s_rx_buffer_align;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore } else if (encp->enc_features & EFX_FEATURE_LFSR_HASH_INSERT) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_prefix_size = encp->enc_rx_prefix_size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Place the start of the buffer a prefix length minus 2
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * before the start of a cache line. This ensures that the
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * last two bytes of the prefix (which is where the LFSR hash
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * is located) are in the same cache line as the headers, and
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * the IP header is 32-bit aligned.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_buffer_align =
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_CPU_CACHE_SIZE - (encp->enc_rx_prefix_size - 2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_buffer_size += sp->s_rx_buffer_align;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore } else {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_prefix_size = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Place the start of the buffer 2 bytes after a cache line
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * boundary so that the headers fit into the cache line and
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * the IP header is 32-bit aligned.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore hdrlen = sp->s_rx_prefix_size + sizeof (struct ether_header);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_buffer_align = P2ROUNDUP(hdrlen, 4) - hdrlen;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_buffer_size += sp->s_rx_buffer_align;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Align end of packet buffer for RX DMA end padding */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore align = MAX(1, encp->enc_rx_buf_align_end);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore EFSYS_ASSERT(ISP2(align));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_buffer_size = P2ROUNDUP(sp->s_rx_buffer_size, align);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Initialize the receive module */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = efx_rx_init(sp->s_enp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(smp->sm_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_rx_scale_start(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Start the receive queue(s) */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sip = &(sp->s_intr);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (index = 0; index < sip->si_nalloc; index++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_rx_qstart(sp, index)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sp->s_srp[0]->sr_state, ==, SFXGE_RXQ_STARTED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* It is sufficient to have Rx scale initialized */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sp->s_rx_scale.srs_state, ==, SFXGE_RX_SCALE_STARTED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = efx_mac_filter_default_rxq_set(sp->s_enp, sp->s_srp[0]->sr_erp,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_scale.srs_count > 1);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (rc != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail4;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail4:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail4);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail3:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail3);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Stop the receive queue(s) */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (--index >= 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qstop(sp, index);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(smp->sm_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Tear down the receive module */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_rx_fini(sp->s_enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(smp->sm_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorevoid
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_coalesce_mode_get(sfxge_t *sp, sfxge_rx_coalesce_mode_t *modep)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *modep = sp->s_rx_coalesce_mode;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreint
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_coalesce_mode_set(sfxge_t *sp, sfxge_rx_coalesce_mode_t mode)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore switch (mode) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case SFXGE_RX_COALESCE_OFF:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case SFXGE_RX_COALESCE_DISALLOW_PUSH:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case SFXGE_RX_COALESCE_ALLOW_PUSH:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore default:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = EINVAL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_coalesce_mode = mode;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorevoid
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_stop(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_mac_t *smp = &(sp->s_mac);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_t *sip = &(sp->s_intr);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nic_t *enp = sp->s_enp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sp->s_state_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_mac_filter_default_rxq_clear(enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Stop the receive queue(s) */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore index = sip->si_nalloc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (--index >= 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* TBD: Flush RXQs in parallel; HW has limit + may need retry */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qstop(sp, index);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(smp->sm_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Tear down the receive module */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_rx_fini(enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_buffer_align = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_prefix_size = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_buffer_size = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(smp->sm_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreunsigned int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_loaned(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_t *sip = &(sp->s_intr);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int loaned;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sip->si_state, ==, SFXGE_INTR_INITIALIZED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore loaned = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore for (index = 0; index < sip->si_nalloc; index++) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rxq_t *srp = sp->s_srp[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_evq_t *sep = sp->s_sep[srp->sr_index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(sep->se_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore loaned += sfxge_rx_qfpp_swizzle(srp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(sep->se_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (loaned);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorevoid
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_rx_fini(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_t *sip = &(sp->s_intr);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sip->si_state, ==, SFXGE_INTR_INITIALIZED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rx_coalesce_mode = SFXGE_RX_COALESCE_OFF;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Tear down the receive queue(s) */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore index = sip->si_nalloc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (--index >= 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_qfini(sp, index);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sp->s_rx_pkt_mem_alloc, ==, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_cache_destroy(sp->s_rqc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rqc = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_cache_destroy(sp->s_rpc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rpc = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_scale_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}