d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * CDDL HEADER START
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * The contents of this file are subject to the terms of the
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Common Development and Distribution License (the "License").
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * You may not use this file except in compliance with the License.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * or http://www.opensolaris.org/os/licensing.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * See the License for the specific language governing permissions
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * and limitations under the License.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * When distributing Covered Code, include this CDDL HEADER in each
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * If applicable, add the following below this CDDL HEADER, with the
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * fields enclosed by brackets "[]" replaced with your own identifying
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * information: Portions Copyright [yyyy] [name of copyright owner]
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * CDDL HEADER END
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Use is subject to license terms.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * This file is part of the Chelsio T1 Ethernet driver.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Copyright (C) 2003-2005 Chelsio Communications. All rights reserved.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#pragma ident "%Z%%M% %I% %E% SMI"
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/types.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/param.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/cmn_err.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/sunddi.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/kmem.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/cmn_err.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/byteorder.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/atomic.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/stropts.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/stream.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/strsubr.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/dlpi.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/kstat.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/ethernet.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <netinet/in.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <netinet/udp.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <inet/common.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <inet/nd.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <inet/ip.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <inet/tcp.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <netinet/udp.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <sys/gld.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include "ostypes.h"
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include "common.h"
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef CONFIG_CHELSIO_T1_1G
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include "fpga_defs.h"
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include "regs.h"
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include "suni1x10gexp_regs.h"
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include "sge.h"
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include "espi.h"
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include "ch.h"
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwextern uint32_t buffers_in_use[];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwuint32_t sge_cmdq0_cnt = SGE_CMDQ0_E_N;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwuint32_t sge_cmdq1_cnt = SGE_CMDQ1_E_N;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwuint32_t sge_flq0_cnt = SGE_FREELQ0_E_N;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwuint32_t sge_flq1_cnt = SGE_FREELQ1_E_N;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwuint32_t sge_respq_cnt = SGE_RESPQ_E_N;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwuint32_t sge_cmdq0_cnt_orig = SGE_CMDQ0_E_N;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwuint32_t sge_cmdq1_cnt_orig = SGE_CMDQ1_E_N;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwuint32_t sge_flq0_cnt_orig = SGE_FREELQ0_E_N;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwuint32_t sge_flq1_cnt_orig = SGE_FREELQ1_E_N;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwuint32_t sge_respq_cnt_orig = SGE_RESPQ_E_N;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef HOST_PAUSE
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwuint32_t do_host_pause = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwuint32_t flq_pause_window = 64;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic uint64_t os_freelist_buffer_alloc(ch_t *sa, int sz, mblk_t **mb,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ulong_t *dh);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwvoid pe_os_free_contig(ch_t *, size_t, void *, uint64_t, ulong_t, ulong_t);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic inline uint32_t t1_sge_rx(pesge *sge, freelQ_t *Q,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw unsigned int len, unsigned int offload);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef HOST_PAUSE
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void t1_sge_check_pause(pesge *sge, struct freelQ *Q);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void alloc_freelQ_buffers(pesge *sge, struct freelQ *Q);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void freelQs_empty(pesge *sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void free_cmdQ_buffers(pesge *sge, cmdQ_t *Q, uint32_t credits_pend);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic int alloc_rx_resources(pesge *sge, struct sge_params *p);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic int alloc_tx_resources(pesge *sge, struct sge_params *p);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic inline void setup_ring_params(ch_t *adapter, u64 addr, u32 size,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int base_reg_lo, int base_reg_hi, int size_reg);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void configure_sge(pesge *sge, struct sge_params *p);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void free_freelQ_buffers(pesge *sge, struct freelQ *Q);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void free_rx_resources(pesge *sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void free_tx_resources(pesge *sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic inline unsigned int jumbo_payload_capacity(pesge *sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef SUN_KSTATS
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic int sge_kstat_setup(pesge *);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void sge_kstat_remove(pesge *);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic int sge_kstat_update(p_kstat_t, int);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic uint16_t calc_ocsum(mblk_t *, int);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Local routines.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic inline void sge_ring_doorbell(pesge *sge, u32 control_reg);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic inline void
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwsge_ring_doorbell(pesge *sge, u32 control_reg)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw membar_producer();
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(sge->obj, A_SG_DOORBELL, control_reg);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * DESC:
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * NOTES: Must have at least 1 command queue and 1 freelist queue.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwpesge *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_sge_create(ch_t *sa, struct sge_params *p)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pesge *sge;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge = t1_os_malloc_wait_zero(sizeof (pesge));
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (sge == NULL)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw goto error_no_mem;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw memset(sge, 0, sizeof (*sge));
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * PR2928 & PR3309
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * set default timeout value - 20 msec
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * we set the initial value to 2 which gurantees at least one tick.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (is_T2(sa))
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->ptimeout = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->obj = sa;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef SUN_KSTATS
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (sge_kstat_setup(sge) != 0)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw goto t1_sge_create_fail1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw p->cmdQ_size[0] = sge_cmdq0_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw p->cmdQ_size[1] = sge_cmdq1_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* note that jumbo frame index is inverted for T2 */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (is_T2(sa)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw p->freelQ_size[1] = sge_flq0_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw p->freelQ_size[0] = sge_flq1_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw p->freelQ_size[0] = sge_flq0_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw p->freelQ_size[1] = sge_flq1_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#if CH_DEBUG
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* DEBUG only */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmn_err(CE_NOTE, "sge: %p\n", sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmn_err(CE_NOTE, "&sge->cmdQ[0]: %p\n", &sge->cmdQ[0]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmn_err(CE_NOTE, "&sge->freelQ[0]: %p\n", &sge->freelQ[0]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmn_err(CE_NOTE, "&sge->freelQ[1]: %p\n", &sge->freelQ[1]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmn_err(CE_NOTE, "&sge->respQ: %p\n", &sge->respQ);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmn_err(CE_NOTE, "&sge->intr_cnt: %p\n", &sge->intr_cnt);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef SUN_KSTATS
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw goto error_no_mem;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_sge_create_fail1:
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_os_free(sge, sizeof (pesge));
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge = NULL;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwerror_no_mem:
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwint
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_sge_destroy(pesge* sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (sge != NULL) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free_tx_resources(sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free_rx_resources(sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* PR2928 & PR3309 */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((is_T2(sge->obj)) && (sge->pskb))
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pe_free_fake_arp(sge->pskb);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef SUN_KSTATS
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge_kstat_remove(sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_os_free(sge, sizeof (pesge));
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * PR2928 & PR3309
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * call out event from timeout
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * there is a potential race between the timeout and the close.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * unless we protect the timeout, the close could occur at the
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * same time. Then if the timeout service routine was slow or
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * interrupted, the sge_stop() could complete with a timeoutID
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * that has expired, thus letting another timeout occur. If the
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * service routine was delayed still further, a detach could occur.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * the second time could then end up accessing memory that has been
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * released back to the system. Bad things could then occur. We
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * set a flag in sge_stop() to tell the service routine not to
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * issue further timeouts. sge_stop() will block until a timeout
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * has occured. If the command Q is full then we shouldn't put out
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * an arp.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwvoid
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_espi_workaround(ch_t *adapter)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pesge *sge = adapter->sge;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_t *chp = (ch_t *)sge->obj;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int rv = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((chp->ch_state == PERUNNING) &&
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_read(&sge->cmdQ[0].cq_asleep)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw u32 seop;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw seop = t1_espi_get_mon(adapter, 0x930, 0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((seop & 0xfff0fff) == 0xfff) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* after first arp */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (sge->pskb)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw rv = pe_start(adapter, (mblk_t *)sge->pskb,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw CH_ARP);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (!rv)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.arp_sent++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef HOST_PAUSE
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * If we are already in sge_data_in, then we can skip calling
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * t1_sge_check_pause() this clock cycle. lockstat showed that
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * we were blocking on the mutex ~ 2% of the time.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (mutex_tryenter(&adapter->ch_intr)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_sge_check_pause(sge, &sge->freelQ[0]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_sge_check_pause(sge, &sge->freelQ[1]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mutex_exit(&adapter->ch_intr);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwint
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwsge_start(pesge *sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(sge->obj, A_SG_CONTROL, sge->sge_control);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* PR2928 & PR3309, also need to avoid Pause deadlock */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_init_cyclic(sge->obj, &sge->espi_wa_cyclic,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void (*)(void *))t1_espi_workaround, sge->obj);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_start_cyclic(&sge->espi_wa_cyclic, sge->ptimeout);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Disables SGE queues.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwint
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwsge_stop(pesge *sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t status;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int loops;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw DBGASSERT(sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* PR2928 & PR3309, also need to avoid Pause deadlock */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(sge->obj, A_SG_CONTROL, 0x0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* wait until there's no more outstanding interrupts pending */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw loops = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw do {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw status = t1_read_reg_4(sge->obj, A_SG_INT_CAUSE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(sge->obj, A_SG_INT_CAUSE, status);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw drv_usecwait(125);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw loops++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } while (status && (loops < 1000));
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_stop_cyclic(&sge->espi_wa_cyclic);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwuint32_t sge_cmdq_send_fail;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwint
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwsge_data_out(pesge* sge, int qid, mblk_t *m0,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmdQ_ce_t *cmp, int count, uint32_t flg)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct cmdQ *Q = &sge->cmdQ[qid];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ddi_dma_handle_t dh = (ddi_dma_handle_t)sge->cmdQ[qid].cq_dh;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw spinlock_t *qlock = &Q->cq_qlock;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmdQ_e *e;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmdQ_e *q = Q->cq_entries;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t credits;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t pidx;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t genbit;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t entries_n = Q->cq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmdQ_ce_t *ce;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmdQ_ce_t *cq = Q->cq_centries;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw dma_addr_t mapping;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t j = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t offset;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#if defined(TX_CKSUM_FIX)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint16_t csum;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint16_t *csum_loc;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef TX_THREAD_RECLAIM
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t reclaim_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * We must exit if we don't have enough free command queue entries
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * available.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw spin_lock(qlock);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#if defined(TX_CKSUM_FIX)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * This checksum fix will address a fragmented datagram
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * checksum error. Which will lead to the next packet after
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * the last packet with the More fragment bit set having its
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * checksum corrupted. When the packet reaches this point
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * the 'flg' variable indicates whether a checksum is needed
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * or not. The algorithm is as follows, if the current packet
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * is a More fragment set the count of packets to be checksummed
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * after it to 3. If it't not and the count of is more than 0
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * then calculate the checksum in software, if a hardware checksum
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * was requested. Then decrment the count. Same algorithm applies
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * to TCP.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (flg & CH_UDP_MF) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->do_udp_csum = 3;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else if ((flg & CH_UDP) && (sge->do_udp_csum != 0)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((flg & CH_NO_HWCKSUM) == 0) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Calc Checksum here.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw csum = calc_ocsum(m0,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sizeof (struct ether_header) + CPL_FORMAT_0_SIZE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw csum_loc = (uint16_t *)(m0->b_rptr +
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sizeof (struct ether_header) + CPL_FORMAT_0_SIZE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw csum_loc += (((*(char *)csum_loc) & 0x0f) << 1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.tx_soft_cksums++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ((struct udphdr *)(csum_loc))->uh_sum = csum;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ((struct cpl_tx_pkt *)m0->b_rptr)->l4_csum_dis = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->do_udp_csum--;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else if (flg & CH_TCP_MF) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->do_tcp_csum = 3;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else if (sge->do_tcp_csum != 0) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((flg & CH_NO_HWCKSUM) == 0) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.tx_soft_cksums++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Calc Checksum here.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->do_tcp_csum--;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif /* TX_CKSUM_FIX */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef TX_THREAD_RECLAIM
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw reclaim_cnt = Q->cq_complete;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (reclaim_cnt > SGE_BATCH_THRESH) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.tx_reclaims[qid]++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free_cmdQ_buffers(sge, Q, reclaim_cnt);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->cq_complete = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw genbit = Q->cq_genbit;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pidx = Q->cq_pidx;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw credits = Q->cq_credits;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((credits - 1) < count) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw spin_unlock(qlock);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.cmdQ_full[qid]++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_sub(count, &Q->cq_credits);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->cq_pidx += count;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (Q->cq_pidx >= entries_n) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->cq_pidx -= entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->cq_genbit ^= 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw spin_unlock(qlock);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef SUN_KSTATS
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (count > MBLK_MAX)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.tx_descs[MBLK_MAX - 1]++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw else
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.tx_descs[count]++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce = &cq[pidx];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *ce = *cmp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mapping = cmp->ce_pa;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw j++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e = &q[pidx];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw offset = (caddr_t)e - (caddr_t)q;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->Sop = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->DataValid = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->BufferLength = cmp->ce_len;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->AddrHigh = ((u64)mapping >> 32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->AddrLow = ((u64)mapping & 0xffffffff);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw --count;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (count > 0) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw unsigned int i;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->Eop = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw wmb();
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->GenerationBit = e->GenerationBit2 = genbit;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw for (i = 0; i < count; i++) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmp++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (++pidx == entries_n) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pidx = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw genbit ^= 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* sync from offset to end of cmdQ */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void) ddi_dma_sync(dh, (off_t)(offset),
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw j*sizeof (*e), DDI_DMA_SYNC_FORDEV);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw offset = j = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce = cq;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e = q;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *ce = *cmp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mapping = cmp->ce_pa;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw j++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->Sop = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->DataValid = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->BufferLength = cmp->ce_len;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->AddrHigh = ((u64)mapping >> 32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->AddrLow = ((u64)mapping & 0xffffffff);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (i < (count - 1)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->Eop = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw wmb();
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->GenerationBit = e->GenerationBit2 = genbit;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce->ce_mp = m0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->Eop = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw wmb();
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->GenerationBit = e->GenerationBit2 = genbit;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void) ddi_dma_sync(dh, (off_t)(offset), j*sizeof (*e),
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw DDI_DMA_SYNC_FORDEV);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * We always ring the doorbell for cmdQ1. For cmdQ0, we only ring
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * the doorbell if the Q is asleep. There is a natural race, where
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * the hardware is going to sleep just after we checked, however,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * then the interrupt handler will detect the outstanding TX packet
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * and ring the doorbell for us.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (qid) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw doorbell_pio(sge, F_CMDQ1_ENABLE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (atomic_read(Q->cq_asleep)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_set(&Q->cq_asleep, 0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/* NOT YET doorbell_pio(sge, F_CMDQ0_ENABLE); */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_set(&Q->cq_pio_pidx, Q->cq_pidx);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw doorbell_pio(sge, F_CMDQ0_ENABLE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#define SGE_PL_INTR_MASK (F_PL_INTR_SGE_ERR | F_PL_INTR_SGE_DATA)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Disable SGE error interrupts.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwint
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_sge_intr_disable(pesge* sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw u32 val = t1_read_reg_4(sge->obj, A_PL_ENABLE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(sge->obj, A_PL_ENABLE, val & ~SGE_PL_INTR_MASK);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(sge->obj, A_SG_INT_ENABLE, 0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#define SGE_INT_ENABLE (F_RESPQ_EXHAUSTED | F_RESPQ_OVERFLOW | \
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw F_FL_EXHAUSTED | F_PACKET_TOO_BIG | F_PACKET_MISMATCH)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Enable SGE error interrupts.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwint
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_sge_intr_enable(pesge* sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw u32 en = SGE_INT_ENABLE;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw u32 val = t1_read_reg_4(sge->obj, A_PL_ENABLE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(sge->obj, A_PL_ENABLE, val | SGE_PL_INTR_MASK);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (sge->obj->ch_flags & TSO_CAPABLE)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw en &= ~F_PACKET_TOO_BIG;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(sge->obj, A_SG_INT_ENABLE, en);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Clear SGE error interrupts.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwint
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_sge_intr_clear(pesge* sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(sge->obj, A_PL_CAUSE, SGE_PL_INTR_MASK);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(sge->obj, A_SG_INT_CAUSE, 0xffffffff);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#define SGE_INT_FATAL (F_RESPQ_OVERFLOW | F_PACKET_TOO_BIG | F_PACKET_MISMATCH)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwint
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_sge_intr_error_handler(pesge *sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw peobj *obj = sge->obj;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw u32 cause = t1_read_reg_4(obj, A_SG_INT_CAUSE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (cause & F_RESPQ_EXHAUSTED)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.respQ_empty++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (cause & F_RESPQ_OVERFLOW) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.respQ_overflow++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmn_err(CE_WARN, "%s: SGE response queue overflow\n",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw obj->ch_name);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (cause & F_FL_EXHAUSTED) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.freelistQ_empty++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw freelQs_empty(sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (cause & F_PACKET_TOO_BIG) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.pkt_too_big++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmn_err(CE_WARN, "%s: SGE max packet size exceeded\n",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw obj->ch_name);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (cause & F_PACKET_MISMATCH) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.pkt_mismatch++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmn_err(CE_WARN, "%s: SGE packet mismatch\n",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw obj->ch_name);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (cause & SGE_INT_FATAL)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_fatal_err(obj);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(obj, A_SG_INT_CAUSE, cause);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * PARAM: sge - SGE instance pointer.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwint
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwsge_data_in(pesge *sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw peobj *adapter = sge->obj;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct respQ *Q = &sge->respQ;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw respQ_e *e; /* response queue entry */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw respQ_e *q = Q->rq_entries; /* base response queue */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t cidx = Q->rq_cidx;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t genbit = Q->rq_genbit;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t entries_n = Q->rq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t credits = Q->rq_credits;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t credits_thresh = Q->rq_credits_thresh;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t ret = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifndef TX_THREAD_RECLAIM
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t credits_pend[2] = {0, 0};
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t flags = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t flagt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ddi_dma_handle_t dh = (ddi_dma_handle_t)Q->rq_dh;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(adapter, A_PL_CAUSE, F_PL_INTR_SGE_DATA);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Catch the case where an interrupt arrives
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * early.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((q == NULL) || (dh == NULL)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw goto check_slow_ints;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* initial response queue entry */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e = &q[cidx];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* pull physical memory of response queue entry into cache */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void) ddi_dma_sync(dh, (off_t)((caddr_t)e - (caddr_t)q),
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sizeof (*e), DDI_DMA_SYNC_FORKERNEL);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw while (e->GenerationBit == genbit) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (--credits < credits_thresh) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t n = entries_n - credits - 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(adapter, A_SG_RSPQUEUECREDIT, n);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw credits += n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (likely(e->DataValid)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void) t1_sge_rx(sge, &sge->freelQ[e->FreelistQid],
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->BufferLength, e->Offload);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((e->Sop != 1) || (e->Eop != 1)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_badEopSop++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmn_err(CE_WARN, "bad Sop %d or Eop %d: %d",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->Sop, e->Eop, e->BufferLength);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw flagt = e->Qsleeping;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw flags |= flagt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (flagt & F_CMDQ0_ENABLE)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_cmdq0++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (flagt & F_CMDQ1_ENABLE)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_cmdq1++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (flagt & F_FL0_ENABLE)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_flq0++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (flagt & F_FL1_ENABLE)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_flq1++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef TX_THREAD_RECLAIM
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw spin_lock(&sge->cmdQ[0].cq_qlock);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->cmdQ[0].cq_complete += e->Cmdq0CreditReturn;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw spin_unlock(&sge->cmdQ[0].cq_qlock);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw spin_lock(&sge->cmdQ[1].cq_qlock);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->cmdQ[1].cq_complete += e->Cmdq1CreditReturn;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((adapter->ch_blked) &&
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (sge->cmdQ[0].cq_complete +
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->cmdQ[1].cq_complete) > 16) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw adapter->ch_blked = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_gld_ok(adapter);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw spin_unlock(&sge->cmdQ[1].cq_qlock);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#else
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw credits_pend[0] += e->Cmdq0CreditReturn;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw credits_pend[1] += e->Cmdq1CreditReturn;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef CONFIG_SMP
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (unlikely(credits_pend[0] > SGE_BATCH_THRESH)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free_cmdQ_buffers(sge, &sge->cmdQ[0], credits_pend[0]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw credits_pend[0] = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (unlikely(credits_pend[1] > SGE_BATCH_THRESH)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free_cmdQ_buffers(sge, &sge->cmdQ[1], credits_pend[1]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw credits_pend[1] = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef HOST_PAUSE
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_sge_check_pause(sge, &sge->freelQ[e->FreelistQid]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (unlikely(++cidx == entries_n)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cidx = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw genbit ^= 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e = q;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* pull physical memory of response queue entry into cache */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void) ddi_dma_sync(dh, (off_t)((caddr_t)e - (caddr_t)q),
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sizeof (*e), DDI_DMA_SYNC_FORKERNEL);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ret = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifndef TX_THREAD_RECLAIM
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (credits_pend[0])
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free_cmdQ_buffers(sge, &sge->cmdQ[0], credits_pend[0]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (credits_pend[1])
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free_cmdQ_buffers(sge, &sge->cmdQ[1], credits_pend[1]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (flags & F_CMDQ0_ENABLE) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct cmdQ *cmdQ = &sge->cmdQ[0];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_set(&cmdQ->cq_asleep, 1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (atomic_read(cmdQ->cq_pio_pidx) != cmdQ->cq_pidx) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw doorbell_pio(sge, F_CMDQ0_ENABLE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_set(&cmdQ->cq_pio_pidx, cmdQ->cq_pidx);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* the SGE told us one of the free lists is empty */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (unlikely(flags & (F_FL0_ENABLE | F_FL1_ENABLE)))
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw freelQs_empty(sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef CONFIG_CHELSIO_T1_OFFLOAD
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (adapter->ch_tx_overflow_mutex)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mutex_enter(adapter->ch_tx_overflow_mutex);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (adapter->ch_blked &&
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (sge->cmdQ[0].cq_credits > (sge->cmdQ[0].cq_entries_n>>2)) &&
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (sge->cmdQ[1].cq_credits > (sge->cmdQ[1].cq_entries_n>>2))) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw adapter->ch_blked = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (adapter->ch_tx_overflow_cv)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cv_broadcast(adapter->ch_tx_overflow_cv);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_gld_ok(adapter);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (adapter->ch_tx_overflow_mutex)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mutex_exit(adapter->ch_tx_overflow_mutex);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#else
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifndef TX_THREAD_RECLAIM
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (adapter->ch_blked &&
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (sge->cmdQ[0].cq_credits > (sge->cmdQ[0].cq_entries_n>>1)) &&
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (sge->cmdQ[1].cq_credits > (sge->cmdQ[1].cq_entries_n>>1))) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw adapter->ch_blked = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_gld_ok(adapter);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif /* CONFIG_CHELSIO_T1_OFFLOAD */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->rq_genbit = genbit;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->rq_cidx = cidx;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->rq_credits = credits;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(adapter, A_SG_SLEEPING, cidx);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwcheck_slow_ints:
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* handle non-data interrupts */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (unlikely(!ret))
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ret = t1_slow_intr_handler(adapter);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (ret);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * allocate a mblk with DMA mapped mblk.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * When checksum offload is enabled, we start the DMA at a 2 byte offset so
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * the IP header will be aligned. We do this for sparc only.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic uint64_t
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwos_freelist_buffer_alloc(ch_t *sa, int sz, mblk_t **mb, ulong_t *dh)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_esb_t *ch_get_small_rbuf(ch_t *sa);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_esb_t *ch_get_big_rbuf(ch_t *sa);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_esb_t *rbp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t rxoff = sa->sge->rx_offset;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (sz == SGE_SM_BUF_SZ(sa)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* get pre-mapped buffer */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((rbp = ch_get_small_rbuf(sa)) == NULL) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sa->norcvbuf++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return ((uint64_t)0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *mb = desballoc((unsigned char *)rbp->cs_buf + rxoff,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw SGE_SM_BUF_SZ(sa)-rxoff, BPRI_MED, &rbp->cs_frtn);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (*mb == NULL) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mutex_enter(&sa->ch_small_esbl);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw rbp->cs_next = sa->ch_small_esb_free;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sa->ch_small_esb_free = rbp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mutex_exit(&sa->ch_small_esbl);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return ((uint64_t)0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *dh = rbp->cs_dh;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (rbp->cs_pa + rxoff);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* get pre-mapped buffer */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((rbp = ch_get_big_rbuf(sa)) == NULL) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sa->norcvbuf++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return ((uint64_t)0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *mb = desballoc((unsigned char *)rbp->cs_buf + rxoff,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw SGE_BG_BUF_SZ(sa)-rxoff, BPRI_MED, &rbp->cs_frtn);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (*mb == NULL) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mutex_enter(&sa->ch_big_esbl);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw rbp->cs_next = sa->ch_big_esb_free;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sa->ch_big_esb_free = rbp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mutex_exit(&sa->ch_big_esbl);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return ((uint64_t)0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *dh = rbp->cs_dh;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (rbp->cs_pa + rxoff);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic inline unsigned int
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_sge_rx(pesge *sge, struct freelQ *Q, unsigned int len, unsigned int offload)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mblk_t *skb;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw peobj *adapter = sge->obj;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct freelQ_ce *cq = Q->fq_centries;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct freelQ_ce *ce = &cq[Q->fq_cidx];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ddi_dma_handle_t dh = (ddi_dma_handle_t)ce->fe_dh;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t cidx = Q->fq_cidx;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t entries_n = Q->fq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t sz = Q->fq_rx_buffer_size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t useit = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t rxoff = sge->rx_offset;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef CONFIG_CHELSIO_T1_OFFLOAD
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t rv;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (Q->fq_id)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_flq1_cnt++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw else
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_flq0_cnt++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * If pkt size falls below threshold, then we'll copy data to
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * an blk and reuse mblk.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * NOTE that rxoff is 2 for T1 adapters. We align the the start
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * of the DMA buffer begin at rxoff offset for T1 cards instead of
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * at the beginning of the buffer, thus the length of the received
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * data does not include this offset. We therefore always add
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * SGE_RX_OFFSET to the allocb size so we have space to provide the
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * offset for the copied data.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef HOST_PAUSE
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * If we have Host pause compiled in, then we look at the
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * free list, if the pause is on and we're not in offload
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * mode then we drop packets, this is designed to avoid
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * overwhelming the machine. If the machine is powerfull enough
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * this will not happen. The 'rx_pkt_drops' will show when
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * packets are being dropped and how much.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((offload == 0) && adapter->pause_on) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw freelQ_e *e;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* Ditch the packet and reuse original buffer */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e = &Q->fq_entries[cidx];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->GenerationBit ^= 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->GenerationBit2 ^= 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_pkt_drops++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw goto rx_entry_consumed;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else if (((adapter->pause_on ||
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (len <= SGE_RX_COPY_THRESHOLD)) &&
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (skb = allocb(len + SGE_RX_OFFSET, BPRI_HI))))
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#else
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((len <= SGE_RX_COPY_THRESHOLD) &&
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (skb = allocb(len + SGE_RX_OFFSET, BPRI_HI)))
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw freelQ_e *e;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw char *src = (char *)((mblk_t *)ce->fe_mp)->b_rptr;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * pull physical memory of pkt data into cache
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Note that len does not include offset for T1.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void) ddi_dma_sync(dh, (off_t)(rxoff), len,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw DDI_DMA_SYNC_FORKERNEL);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (offload == 0) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * create 2 byte offset so IP header aligned on
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * 4 byte boundry
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw skb_reserve(skb, SGE_RX_OFFSET);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * if hardware inserted 2 byte offset then need to
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * start copying with extra offset
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw src += sge->rx_pkt_pad;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw memcpy(skb->b_rptr, src, len);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw useit = 0; /* mblk copy, don't inc esballoc in use cnt */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* so we can reuse original buffer */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e = &Q->fq_entries[cidx];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->GenerationBit ^= 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->GenerationBit2 ^= 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_pkt_copied++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* consume buffer off the ring */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw skb = ce->fe_mp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce->fe_mp = NULL;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * if not offload (tunneled pkt), & hardward padded, then
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * adjust start of pkt to point to start of data i.e.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * skip pad (2 bytes).
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (!offload && sge->rx_pkt_pad)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw __skb_pull(skb, SGE_RX_OFFSET);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * pull physical memory of pkt data into cache
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Note that len does not include offset for T1.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void) ddi_dma_sync(dh, (off_t)(rxoff), len,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw DDI_DMA_SYNC_FORKERNEL);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* set length of data in skb */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw skb_put(skb, len);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef CONFIG_CHELSIO_T1_OFFLOAD
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (likely(offload)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (likely(toe_running(adapter))) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* sends pkt upstream to toe layer */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (useit) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (sz == SGE_SM_BUF_SZ(adapter)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_add(1,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw &buffers_in_use[adapter->ch_sm_index]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_add(1,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw &buffers_in_use[adapter->ch_big_index]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (adapter->toe_rcv)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw adapter->toe_rcv(adapter->ch_toeinst, skb);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw else
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw freemsg(skb);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmn_err(CE_WARN,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw "%s: unexpected offloaded packet, cmd %u\n",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw adapter->ch_name, *skb->b_rptr);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* discard packet */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw freemsg(skb);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#else
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (unlikely(offload)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cmn_err(CE_WARN,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw "%s: unexpected offloaded packet, cmd %u\n",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw adapter->ch_name, *skb->b_rptr);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* discard paket */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw freemsg(skb);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw else {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct cpl_rx_pkt *p = (struct cpl_rx_pkt *)skb->b_rptr;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int flg = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t cksum;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* adjust beginning of data to skip CPL header */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw skb_pull(skb, SZ_CPL_RX_PKT);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* extract checksum from CPL header here */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * bump count of mlbks in used by protocol stack(s)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (useit) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (sz == SGE_SM_BUF_SZ(adapter)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_add(1,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw &buffers_in_use[adapter->ch_sm_index]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_add(1,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw &buffers_in_use[adapter->ch_big_index]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef CONFIG_CHELSIO_T1_OFFLOAD
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * let the TOE layer have a crack at the packet first.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (adapter->toe_tunnel) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw rv = adapter->toe_tunnel(adapter->ch_toeinst, skb);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * The TOE may have consumed the packet.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (rv)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw goto rx_entry_consumed;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif /* CONFIG_CHELSIO_T1_OFFLOAD */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cksum = p->csum;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * NOTE: 14+9 = size of MAC + offset to IP protocol field
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (adapter->ch_config.cksum_enabled &&
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (ntohs(((struct ether_header *)skb->b_rptr)->ether_type) ==
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ETHERTYPE_IP) &&
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ((skb->b_rptr[14+9] == IPPROTO_TCP) ||
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (skb->b_rptr[14+9] == IPPROTO_UDP))) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw flg = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_send_up(adapter, skb, cksum, flg);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwrx_entry_consumed:
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (++cidx == entries_n)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cidx = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_cidx = cidx;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (unlikely(--Q->fq_credits < (entries_n>>2)))
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* allocate new buffers on the free list */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw alloc_freelQ_buffers(sge, Q);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef HOST_PAUSE
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_sge_check_pause(pesge *sge, struct freelQ *Q)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw peobj *adapter = sge->obj;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * If the number of available credits shrinks below
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * the Pause on threshold then enable the pause and
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * try and allocate more buffers.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * On the next pass, if there's more credits returned
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * then check that you've went above the pause
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * threshold and then disable the pause.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (Q->fq_credits < Q->fq_pause_on_thresh) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (do_host_pause) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_pause_on++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw adapter->txxg_cfg1 |=
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw SUNI1x10GEXP_BITMSK_TXXG_HOSTPAUSE;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void) t1_tpi_write(adapter,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw SUNI1x10GEXP_REG_TXXG_CONFIG_1 << 2,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw adapter->txxg_cfg1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw adapter->pause_on = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw adapter->pause_time = gethrtime();
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw alloc_freelQ_buffers(sge, Q);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else if ((adapter->pause_on) &&
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (Q->fq_credits > Q->fq_pause_off_thresh)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw hrtime_t time;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_pause_off++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw adapter->txxg_cfg1 &= ~SUNI1x10GEXP_BITMSK_TXXG_HOSTPAUSE;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void) t1_tpi_write(adapter,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw SUNI1x10GEXP_REG_TXXG_CONFIG_1 << 2,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw adapter->txxg_cfg1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw adapter->pause_on = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw time = (gethrtime() - adapter->pause_time)/1000;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_pause_ms += time;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (time > sge->intr_cnt.rx_pause_spike)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_pause_spike = (uint32_t)time;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_fl_credits = Q->fq_credits;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif /* HOST_PAUSE */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwalloc_freelQ_buffers(pesge *sge, struct freelQ *Q)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t pidx = Q->fq_pidx;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct freelQ_ce *ce = &Q->fq_centries[pidx];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw freelQ_e *fq = Q->fq_entries; /* base of freelist Q */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw freelQ_e *e = &Q->fq_entries[pidx];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t sz = Q->fq_rx_buffer_size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t rxoff = sge->rx_offset;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t credits = Q->fq_credits;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t entries_n = Q->fq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t genbit = Q->fq_genbit;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ddi_dma_handle_t th = (ddi_dma_handle_t)Q->fq_dh;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ulong_t dh;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint64_t mapping;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw off_t offset = (off_t)((caddr_t)e - (caddr_t)fq);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size_t len = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw while (credits < entries_n) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (e->GenerationBit != genbit) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mblk_t *skb;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mapping = os_freelist_buffer_alloc(sge->obj, sz,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw &skb, &dh);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (mapping == 0) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_flbuf_fails++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw break;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_flbuf_allocs++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce->fe_mp = skb;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce->fe_dh = dh;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Note that for T1, we've started the beginning of
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * of the buffer by an offset of 2 bytes. We thus
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * decrement the length to account for this.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->AddrLow = (u32)mapping;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->AddrHigh = (u64)mapping >> 32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->BufferLength = sz - rxoff;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw wmb();
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e->GenerationBit = e->GenerationBit2 = genbit;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw len += sizeof (*e);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw credits++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (++pidx == entries_n) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * sync freelist entries to physical memory up to
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * end of the table.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void) ddi_dma_sync(th, offset, len,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw DDI_DMA_SYNC_FORDEV);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw offset = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw len = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pidx = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw genbit ^= 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce = Q->fq_centries;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw e = Q->fq_entries;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* sync freelist entries that have been modified. */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (len)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void) ddi_dma_sync(th, offset, len, DDI_DMA_SYNC_FORDEV);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_genbit = genbit;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_pidx = pidx;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_credits = credits;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwfreelQs_empty(pesge *sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw u32 irq_reg = t1_read_reg_4(sge->obj, A_SG_INT_ENABLE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw u32 irqholdoff_reg;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw alloc_freelQ_buffers(sge, &sge->freelQ[0]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw alloc_freelQ_buffers(sge, &sge->freelQ[1]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((sge->freelQ[0].fq_credits > sge->freelQ[0].fq_entries_n >> 2) &&
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (sge->freelQ[1].fq_credits > sge->freelQ[1].fq_entries_n >> 2)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw irq_reg |= F_FL_EXHAUSTED;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw irqholdoff_reg = sge->intrtimer[sge->currIndex];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* Clear the F_FL_EXHAUSTED interrupts for now */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw irq_reg &= ~F_FL_EXHAUSTED;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw irqholdoff_reg = sge->intrtimer_nres;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(sge->obj, A_SG_INTRTIMER, irqholdoff_reg);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(sge->obj, A_SG_INT_ENABLE, irq_reg);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* We reenable the Qs to force an Freelist GTS interrupt later */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw doorbell_pio(sge, F_FL0_ENABLE | F_FL1_ENABLE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Frees 'credits_pend' TX buffers and returns the credits to Q->credits.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Free xmit buffers
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwfree_cmdQ_buffers(pesge *sge, struct cmdQ *Q, unsigned int credits_pend)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mblk_t *skb;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct cmdQ_ce *ce;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct cmdQ_ce *cq = Q->cq_centries;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t entries_n = Q->cq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t cidx = Q->cq_cidx;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t i = credits_pend;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef CONFIG_CHELSIO_T1_OFFLOAD
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_t *chp = sge->obj;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce = &cq[cidx];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw while (i--) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef CONFIG_CHELSIO_T1_OFFLOAD
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* if flag set, then toe buffer */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw switch (ce->ce_flg & 0x7) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw case DH_DMA:
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (ce->ce_dh) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_unbind_dma_handle(sge->obj, ce->ce_dh);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce->ce_dh = NULL; /* may not be needed */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw skb = ce->ce_mp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (skb && ((ce->ce_flg & CH_ARP) == NULL)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw freemsg(skb);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce->ce_mp = NULL;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw break;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#if defined(__sparc)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw case DH_DVMA:
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (ce->ce_dh) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_unbind_dvma_handle(sge->obj, ce->ce_dh);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce->ce_dh = NULL; /* may not be needed */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw skb = ce->ce_mp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (skb && ((ce->ce_flg & CH_ARP) == NULL)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw freemsg(skb);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce->ce_mp = NULL;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw break;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif /* __sparc */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw case DH_TOE:
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chp->toe_free(chp->ch_toeinst, (tbuf_t *)(ce->ce_mp));
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce->ce_mp = NULL;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw break;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#else /* CONFIG_CHELSIO_T1_OFFLOAD */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (ce->ce_dh) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((ce->ce_flg & 7) == DH_DMA) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_unbind_dma_handle(sge->obj, ce->ce_dh);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#if defined(__sparc)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw else {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_unbind_dvma_handle(sge->obj, ce->ce_dh);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif /* __sparc */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce->ce_dh = NULL; /* may not be needed */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw skb = ce->ce_mp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (skb && ((ce->ce_flg & CH_ARP) == NULL)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw freemsg(skb);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce->ce_mp = NULL;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif /* !CONFIG_CHELSIO_T1_OFFLOAD */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (++cidx == entries_n) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cidx = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce = cq;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->cq_cidx = cidx;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_add(credits_pend, &Q->cq_credits);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstruct sge_intr_counts *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwsge_get_stat(pesge *sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (&sge->intr_cnt);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Allocates both RX and TX resources and configures the SGE. However,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * the hardware is not enabled yet.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * rx_pkt_pad is set, if the hardware supports aligning non-offload traffic.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * jumbo_fl is set to the index of the freelist containing the jumbo buffers.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwint
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_sge_configure(pesge *sge, struct sge_params *p)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->rx_pkt_pad = t1_is_T1B(sge->obj) ? 0 : SGE_RX_OFFSET;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->jumbo_fl = t1_is_T1B(sge->obj) ? 1 : 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* if we're a T2 card, then we have hardware offset support */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->rx_offset = t1_is_T1B(sge->obj) ? SGE_RX_OFFSET: 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (alloc_rx_resources(sge, p))
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (-ENOMEM);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (alloc_tx_resources(sge, p)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free_rx_resources(sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (-ENOMEM);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw configure_sge(sge, p);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Now that we have sized the free lists calculate the payload
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * capacity of the large buffers. Other parts of the driver use
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * this to set the max offload coalescing size so that RX packets
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * do not overflow our large buffers.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw p->large_buf_capacity = jumbo_payload_capacity(sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Allocates basic RX resources, consisting of memory mapped freelist Qs and a
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * response Q.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic int
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwalloc_rx_resources(pesge *sge, struct sge_params *p)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw unsigned int size, i;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw for (i = 0; i < SGE_FREELQ_N; i++) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct freelQ *Q = &sge->freelQ[i];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_id = i;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_genbit = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_entries_n = p->freelQ_size[i];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef HOST_PAUSE
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_pause_on_thresh = flq_pause_window;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_pause_off_thresh = Q->fq_entries_n >> 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size = sizeof (freelQ_e) * Q->fq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_entries = pe_os_malloc_contig_wait_zero(sge->obj,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size, &Q->fq_pa, &Q->fq_dh, &Q->fq_ah, DMA_OUT);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (!Q->fq_entries)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw goto err_no_mem;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw memset(Q->fq_entries, 0, size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size = sizeof (struct freelQ_ce) * Q->fq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_centries = t1_os_malloc_wait_zero(size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (!Q->fq_centries)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw goto err_no_mem;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw memset(Q->fq_centries, 0, size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Calculate the buffer sizes for the two free lists. FL0 accommodates
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * regular sized Ethernet frames, FL1 is sized not to exceed 16K,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * including all the sk_buff overhead.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * For T1C FL0 and FL1 are reversed.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef NOTYET
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->freelQ[1 ^ sge->jumbo_fl].fq_rx_buffer_size = SGE_RX_SM_BUF_SIZE +
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sizeof (struct cpl_rx_data) +
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw SGE_RX_OFFSET - sge->rx_pkt_pad;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#else
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->freelQ[1 ^ sge->jumbo_fl].fq_rx_buffer_size =
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->obj->ch_sm_buf_sz;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (is_T2(sge->obj))
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_flq1_sz = sge->obj->ch_sm_buf_sz;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw else
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_flq0_sz = sge->obj->ch_sm_buf_sz;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef NOTYET
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->freelQ[sge->jumbo_fl].fq_rx_buffer_size = (16 * 1024) -
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw SKB_DATA_ALIGN(sizeof (struct skb_shared_info));
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#else
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->freelQ[sge->jumbo_fl].fq_rx_buffer_size = sge->obj->ch_bg_buf_sz;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (is_T2(sge->obj))
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_flq0_sz = sge->obj->ch_bg_buf_sz;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw else
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intr_cnt.rx_flq1_sz = sge->obj->ch_bg_buf_sz;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->respQ.rq_genbit = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->respQ.rq_entries_n = sge_respq_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->respQ.rq_credits = sge_respq_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->respQ.rq_credits_thresh = sge_respq_cnt - (sge_respq_cnt >> 2);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size = sizeof (respQ_e) * sge->respQ.rq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->respQ.rq_entries = pe_os_malloc_contig_wait_zero(sge->obj,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size, &(sge->respQ.rq_pa), &(sge->respQ.rq_dh),
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw &(sge->respQ.rq_ah), 0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (!sge->respQ.rq_entries)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw goto err_no_mem;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw memset(sge->respQ.rq_entries, 0, size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwerr_no_mem:
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free_rx_resources(sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Allocates basic TX resources, consisting of memory mapped command Qs.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic int
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwalloc_tx_resources(pesge *sge, struct sge_params *p)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw unsigned int size, i;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw for (i = 0; i < SGE_CMDQ_N; i++) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct cmdQ *Q = &sge->cmdQ[i];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->cq_genbit = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->cq_entries_n = p->cmdQ_size[i];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_set(&Q->cq_credits, Q->cq_entries_n);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_set(&Q->cq_asleep, 1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mutex_init(&Q->cq_qlock, NULL, MUTEX_DRIVER,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->obj->ch_icookp);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size = sizeof (cmdQ_e) * Q->cq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->cq_entries = pe_os_malloc_contig_wait_zero(sge->obj,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size, &Q->cq_pa, &Q->cq_dh, &Q->cq_ah, DMA_OUT);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (!Q->cq_entries)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw goto err_no_mem;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw memset(Q->cq_entries, 0, size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size = sizeof (struct cmdQ_ce) * Q->cq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->cq_centries = t1_os_malloc_wait_zero(size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (!Q->cq_centries)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw goto err_no_mem;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw memset(Q->cq_centries, 0, size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* allocate pre-mapped dma headers */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pe_dma_handle_init(sge->obj, Q->cq_entries_n);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwerr_no_mem:
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free_tx_resources(sge);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Sets the interrupt latency timer when the adaptive Rx coalescing
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * is turned off. Do nothing when it is turned on again.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * This routine relies on the fact that the caller has already set
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * the adaptive policy in adapter->sge_params before calling it.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwint
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_sge_set_coalesce_params(pesge *sge, struct sge_params *p)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (!p->coalesce_enable) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw u32 newTimer = p->rx_coalesce_usecs *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (board_info(sge->obj)->clock_core / 1000000);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(sge->obj, A_SG_INTRTIMER, newTimer);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Programs the various SGE registers. However, the engine is not yet enabled,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * but sge->sge_control is setup and ready to go.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwconfigure_sge(pesge *sge, struct sge_params *p)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_t *ap = sge->obj;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int i;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(ap, A_SG_CONTROL, 0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw setup_ring_params(ap, sge->cmdQ[0].cq_pa, sge->cmdQ[0].cq_entries_n,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw A_SG_CMD0BASELWR, A_SG_CMD0BASEUPR, A_SG_CMD0SIZE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw setup_ring_params(ap, sge->cmdQ[1].cq_pa, sge->cmdQ[1].cq_entries_n,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw A_SG_CMD1BASELWR, A_SG_CMD1BASEUPR, A_SG_CMD1SIZE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw setup_ring_params(ap, sge->freelQ[0].fq_pa,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->freelQ[0].fq_entries_n, A_SG_FL0BASELWR,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw A_SG_FL0BASEUPR, A_SG_FL0SIZE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw setup_ring_params(ap, sge->freelQ[1].fq_pa,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->freelQ[1].fq_entries_n, A_SG_FL1BASELWR,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw A_SG_FL1BASEUPR, A_SG_FL1SIZE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* The threshold comparison uses <. */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(ap, A_SG_FLTHRESHOLD, SGE_RX_SM_BUF_SIZE(ap) -
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw SZ_CPL_RX_PKT - sge->rx_pkt_pad - sge->rx_offset + 1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw setup_ring_params(ap, sge->respQ.rq_pa, sge->respQ.rq_entries_n,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw A_SG_RSPBASELWR, A_SG_RSPBASEUPR, A_SG_RSPSIZE);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(ap, A_SG_RSPQUEUECREDIT, (u32)sge->respQ.rq_entries_n);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->sge_control = F_CMDQ0_ENABLE | F_CMDQ1_ENABLE | F_FL0_ENABLE |
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw F_FL1_ENABLE | F_CPL_ENABLE | F_RESPONSE_QUEUE_ENABLE |
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw V_CMDQ_PRIORITY(2) | F_DISABLE_CMDQ1_GTS | F_ISCSI_COALESCE |
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#if 1
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * if the the following bit is not set, then we'll get an
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * interrupt everytime command Q 0 goes empty. Since we're
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * always ringing the doorbell, we can turn it on.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw F_DISABLE_CMDQ0_GTS |
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw V_RX_PKT_OFFSET(sge->rx_pkt_pad);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#if BYTE_ORDER == BIG_ENDIAN
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->sge_control |= F_ENABLE_BIG_ENDIAN;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Initialize the SGE Interrupt Timer arrray:
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * intrtimer[0] = (SGE_INTRTIMER0) usec
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * intrtimer[0<i<10] = (SGE_INTRTIMER0 + 2*i) usec
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * intrtimer[10] = (SGE_INTRTIMER1) usec
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intrtimer[0] = board_info(sge->obj)->clock_core / 1000000;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw for (i = 1; i < SGE_INTR_MAXBUCKETS - 1; ++i) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intrtimer[i] = SGE_INTRTIMER0 + (2 * i);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intrtimer[i] *= sge->intrtimer[0];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intrtimer[SGE_INTR_MAXBUCKETS - 1] =
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intrtimer[0] * SGE_INTRTIMER1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* Initialize resource timer */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intrtimer_nres = (uint32_t)(sge->intrtimer[0] *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw SGE_INTRTIMER_NRES);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* Finally finish initialization of intrtimer[0] */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intrtimer[0] = (uint32_t)(sge->intrtimer[0] * SGE_INTRTIMER0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* Initialize for a throughput oriented workload */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->currIndex = SGE_INTR_MAXBUCKETS - 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (p->coalesce_enable)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(ap, A_SG_INTRTIMER,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->intrtimer[sge->currIndex]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw else
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void) t1_sge_set_coalesce_params(sge, p);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic inline void
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwsetup_ring_params(ch_t *adapter, u64 addr, u32 size, int base_reg_lo,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int base_reg_hi, int size_reg)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(adapter, base_reg_lo, (u32)addr);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(adapter, base_reg_hi, addr >> 32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_write_reg_4(adapter, size_reg, size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Frees RX resources.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwfree_rx_resources(pesge *sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw unsigned int size, i;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (sge->respQ.rq_entries) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size = sizeof (respQ_e) * sge->respQ.rq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pe_os_free_contig(sge->obj, size, sge->respQ.rq_entries,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->respQ.rq_pa, sge->respQ.rq_dh, sge->respQ.rq_ah);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw for (i = 0; i < SGE_FREELQ_N; i++) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct freelQ *Q = &sge->freelQ[i];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (Q->fq_centries) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free_freelQ_buffers(sge, Q);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_os_free(Q->fq_centries,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_entries_n * sizeof (freelQ_ce_t));
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (Q->fq_entries) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size = sizeof (freelQ_e) * Q->fq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* free the freelist queue */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pe_os_free_contig(sge->obj, size, Q->fq_entries,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_pa, Q->fq_dh, Q->fq_ah);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Frees all RX buffers on the freelist Q. The caller must make sure that
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * the SGE is turned off before calling this function.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwfree_freelQ_buffers(pesge *sge, struct freelQ *Q)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct freelQ_ce *ce;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct freelQ_ce *cq = Q->fq_centries;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t credits = Q->fq_credits;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t entries_n = Q->fq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t cidx = Q->fq_cidx;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t i = Q->fq_id;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce = &cq[cidx];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw credits = entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw while (credits--) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mblk_t *mp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((mp = ce->fe_mp) != NULL) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* bump in-use count of receive buffers */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (i != sge->jumbo_fl) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_add(1,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw &buffers_in_use[sge->obj->ch_sm_index]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_add(1,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw &buffers_in_use[sge->obj->ch_big_index]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * note. freeb() callback of esb-alloced mblk will
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * cause receive buffer to be put back on sa free list.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw freeb(mp);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce->fe_mp = NULL;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (++cidx == entries_n) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw cidx = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ce = cq;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_cidx = cidx;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->fq_credits = credits;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Free TX resources.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw *
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Assumes that SGE is stopped and all interrupts are disabled.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwfree_tx_resources(pesge *sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw unsigned int size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t i;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw for (i = 0; i < SGE_CMDQ_N; i++) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct cmdQ *Q = &sge->cmdQ[i];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (Q->cq_centries) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw unsigned int pending = Q->cq_entries_n -
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw atomic_read(Q->cq_credits);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mutex_destroy(&Q->cq_qlock);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (pending)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free_cmdQ_buffers(sge, Q, pending);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size = sizeof (struct cmdQ_ce) * Q->cq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw t1_os_free(Q->cq_centries, size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (Q->cq_entries) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size = sizeof (cmdQ_e) * Q->cq_entries_n;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pe_os_free_contig(sge->obj, size, Q->cq_entries,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Q->cq_pa, Q->cq_dh, Q->cq_ah);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw * Return the payload capacity of the jumbo free-list buffers.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic inline unsigned int jumbo_payload_capacity(pesge *sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (sge->freelQ[sge->jumbo_fl].fq_rx_buffer_size -
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sizeof (struct cpl_rx_data) - sge->rx_pkt_pad - sge->rx_offset);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/* PR2928 & PR3309 */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwvoid
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_sge_set_ptimeout(adapter_t *adapter, u32 val)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pesge *sge = adapter->sge;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (is_T2(adapter))
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->ptimeout = max(val, 1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/* PR2928 & PR3309 */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwu32
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwt1_sge_get_ptimeout(adapter_t *adapter)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pesge *sge = adapter->sge;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (is_T2(adapter) ? sge->ptimeout : 0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwvoid
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwsge_add_fake_arp(pesge *sge, void *bp)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->pskb = bp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef SUN_KSTATS
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic int
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwsge_kstat_setup(pesge *sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int status;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw p_kstat_t ksp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size_t ch_kstat_sz;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw p_ch_kstat_t chkp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw char kstat_name[32];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int instance;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int i;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw status = -1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_kstat_sz = sizeof (ch_kstat_t);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw instance = ddi_get_instance(sge->obj->ch_dip);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if ((ksp = kstat_create(CHNAME "_debug", instance,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw NULL, "net_debug", KSTAT_TYPE_NAMED,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ch_kstat_sz / sizeof (kstat_named_t), 0)) == NULL)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw goto sge_kstat_setup_exit;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp = (p_ch_kstat_t)ksp->ks_data;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->respQ_empty, "respQ_empty",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->respQ_overflow, "respQ_overflow",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->freelistQ_empty, "freelistQ_empty",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->pkt_too_big, "pkt_too_big",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->pkt_mismatch, "pkt_mismatch",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->cmdQ_full[0], "cmdQ_full[0]",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->cmdQ_full[1], "cmdQ_full[1]",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_reclaims[0], "tx_reclaims[0]",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_reclaims[1], "tx_reclaims[1]",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_msg_pullups, "tx_msg_pullups",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_hdr_pullups, "tx_hdr_pullups",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_tcp_ip_frag, "tx_tcp_ip_frag",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_udp_ip_frag, "tx_udp_ip_frag",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_soft_cksums, "tx_soft_cksums",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_need_cpl_space, "tx_need_cpl_space",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_multi_mblks, "tx_multi_mblks",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_no_dvma1, "tx_num_multi_dvma_fails",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_no_dvma2, "tx_num_single_dvma_fails",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_no_dma1, "tx_num_multi_dma_fails",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_no_dma2, "tx_num_single_dma_fails",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_cmdq0, "rx_cmdq0",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_cmdq1, "rx_cmdq1",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_flq0, "rx_flq0",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_flq1, "rx_flq1",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_flq0_sz, "rx_flq0_buffer_sz",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_flq1_sz, "rx_flq1_buffer_sz",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_pkt_drops, "rx_pkt_drops",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_pkt_copied, "rx_pkt_copied",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_pause_on, "rx_pause_on",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_pause_off, "rx_pause_off",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_pause_ms, "rx_pause_ms",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_pause_spike, "rx_pause_spike",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_fl_credits, "rx_fl_credits",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_flbuf_fails, "rx_flbuf_fails",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_flbuf_allocs, "rx_flbuf_allocs",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_badEopSop, "rx_badEopSop",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_flq0_cnt, "rx_flq0_cnt",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->rx_flq1_cnt, "rx_flq1_cnt",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->arp_sent, "arp_sent",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_doorbells, "tx_doorbells",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->intr_doorbells, "intr_doorbells",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->intr1_doorbells, "intr1_doorbells",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->sleep_cnt, "sleep_cnt",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->pe_allocb_cnt, "pe_allocb_cnt",
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw for (i = 0; i < MBLK_MAX; i++) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (void) sprintf(kstat_name, "tx_descs[%02d]", i);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_named_init(&chkp->tx_descs[i],
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_name, KSTAT_DATA_UINT32);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ksp->ks_update = sge_kstat_update;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ksp->ks_private = (void *)sge;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge->ksp = ksp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_install(ksp);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw status = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwsge_kstat_setup_exit:
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (status);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwsge_kstat_remove(pesge *sge)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (sge->ksp)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw kstat_delete(sge->ksp);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic int
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwsge_kstat_update(p_kstat_t ksp, int rw)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pesge *sge;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw p_ch_stats_t statsp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw p_ch_kstat_t chkp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int i;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sge = (pesge *)ksp->ks_private;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp = (p_ch_stats_t)&sge->intr_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp = (p_ch_kstat_t)ksp->ks_data;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (rw == KSTAT_WRITE) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->respQ_empty = chkp->respQ_empty.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->respQ_overflow = chkp->respQ_overflow.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->freelistQ_empty = chkp->freelistQ_empty.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->pkt_too_big = chkp->pkt_too_big.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->pkt_mismatch = chkp->pkt_mismatch.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->cmdQ_full[0] = chkp->cmdQ_full[0].value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->cmdQ_full[1] = chkp->cmdQ_full[1].value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_reclaims[0] = chkp->tx_reclaims[0].value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_reclaims[1] = chkp->tx_reclaims[1].value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_msg_pullups = chkp->tx_msg_pullups.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_hdr_pullups = chkp->tx_hdr_pullups.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_tcp_ip_frag = chkp->tx_tcp_ip_frag.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_udp_ip_frag = chkp->tx_udp_ip_frag.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_soft_cksums = chkp->tx_soft_cksums.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_need_cpl_space
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw = chkp->tx_need_cpl_space.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_multi_mblks = chkp->tx_multi_mblks.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_no_dvma1 = chkp->tx_no_dvma1.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_no_dvma2 = chkp->tx_no_dvma2.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_no_dma1 = chkp->tx_no_dma1.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_no_dma2 = chkp->tx_no_dma2.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_cmdq0 = chkp->rx_cmdq0.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_cmdq1 = chkp->rx_cmdq1.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_flq0 = chkp->rx_flq0.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_flq1 = chkp->rx_flq1.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_flq0_sz = chkp->rx_flq0_sz.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_flq1_sz = chkp->rx_flq1_sz.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_pkt_drops = chkp->rx_pkt_drops.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_pkt_copied = chkp->rx_pkt_copied.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_pause_on = chkp->rx_pause_on.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_pause_off = chkp->rx_pause_off.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_pause_ms = chkp->rx_pause_ms.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_pause_spike = chkp->rx_pause_spike.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_fl_credits = chkp->rx_fl_credits.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_flbuf_fails = chkp->rx_flbuf_fails.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_flbuf_allocs = chkp->rx_flbuf_allocs.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_badEopSop = chkp->rx_badEopSop.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_flq0_cnt = chkp->rx_flq0_cnt.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->rx_flq1_cnt = chkp->rx_flq1_cnt.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->arp_sent = chkp->arp_sent.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_doorbells = chkp->tx_doorbells.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->intr_doorbells = chkp->intr_doorbells.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->intr1_doorbells = chkp->intr1_doorbells.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->sleep_cnt = chkp->sleep_cnt.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->pe_allocb_cnt = chkp->pe_allocb_cnt.value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw for (i = 0; i < MBLK_MAX; i++) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw statsp->tx_descs[i] = chkp->tx_descs[i].value.ui32;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->respQ_empty.value.ui32 = statsp->respQ_empty;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->respQ_overflow.value.ui32 = statsp->respQ_overflow;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->freelistQ_empty.value.ui32
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw = statsp->freelistQ_empty;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->pkt_too_big.value.ui32 = statsp->pkt_too_big;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->pkt_mismatch.value.ui32 = statsp->pkt_mismatch;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->cmdQ_full[0].value.ui32 = statsp->cmdQ_full[0];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->cmdQ_full[1].value.ui32 = statsp->cmdQ_full[1];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_reclaims[0].value.ui32 = statsp->tx_reclaims[0];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_reclaims[1].value.ui32 = statsp->tx_reclaims[1];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_msg_pullups.value.ui32 = statsp->tx_msg_pullups;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_hdr_pullups.value.ui32 = statsp->tx_hdr_pullups;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_tcp_ip_frag.value.ui32 = statsp->tx_tcp_ip_frag;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_udp_ip_frag.value.ui32 = statsp->tx_udp_ip_frag;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_soft_cksums.value.ui32 = statsp->tx_soft_cksums;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_need_cpl_space.value.ui32
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw = statsp->tx_need_cpl_space;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_multi_mblks.value.ui32 = statsp->tx_multi_mblks;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_no_dvma1.value.ui32 = statsp->tx_no_dvma1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_no_dvma2.value.ui32 = statsp->tx_no_dvma2;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_no_dma1.value.ui32 = statsp->tx_no_dma1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_no_dma2.value.ui32 = statsp->tx_no_dma2;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_cmdq0.value.ui32 = statsp->rx_cmdq0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_cmdq1.value.ui32 = statsp->rx_cmdq1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_flq0.value.ui32 = statsp->rx_flq0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_flq1.value.ui32 = statsp->rx_flq1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_flq0_sz.value.ui32 = statsp->rx_flq0_sz;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_flq1_sz.value.ui32 = statsp->rx_flq1_sz;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_pkt_drops.value.ui32 = statsp->rx_pkt_drops;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_pkt_copied.value.ui32 = statsp->rx_pkt_copied;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_pause_on.value.ui32 = statsp->rx_pause_on;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_pause_off.value.ui32 = statsp->rx_pause_off;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_pause_ms.value.ui32 = statsp->rx_pause_ms;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_pause_spike.value.ui32 = statsp->rx_pause_spike;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_fl_credits.value.ui32 = statsp->rx_fl_credits;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_flbuf_fails.value.ui32
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw = statsp->rx_flbuf_fails;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_flbuf_allocs.value.ui32
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw = statsp->rx_flbuf_allocs;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_badEopSop.value.ui32 = statsp->rx_badEopSop;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_flq0_cnt.value.ui32 = statsp->rx_flq0_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->rx_flq1_cnt.value.ui32 = statsp->rx_flq1_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->arp_sent.value.ui32 = statsp->arp_sent;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_doorbells.value.ui32 = statsp->tx_doorbells;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->intr_doorbells.value.ui32 = statsp->intr_doorbells;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->intr1_doorbells.value.ui32
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw = statsp->intr1_doorbells;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->sleep_cnt.value.ui32 = statsp->sleep_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->pe_allocb_cnt.value.ui32 = statsp->pe_allocb_cnt;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw for (i = 0; i < MBLK_MAX; i++) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw chkp->tx_descs[i].value.ui32 = statsp->tx_descs[i];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (0);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic uint16_t
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwcalc_ocsum(mblk_t *mp, int offset)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint8_t *addrp;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t src;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t dst;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ipha_t *ihdr = (ipha_t *)(mp->b_rptr + offset);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uint32_t sum;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int iplen = IPH_HDR_LENGTH(ihdr);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct udphdr *udpp = (struct udphdr *)(mp->b_rptr + offset + iplen);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw uchar_t *byte;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int len;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw addrp = (uint8_t *)&ihdr->ipha_src;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw src = ((uint32_t)(addrp[0]) << 24) | ((uint32_t)(addrp[1]) << 16) |
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ((uint32_t)(addrp[2]) << 8) | (uint32_t)(addrp[3]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw addrp = (uint8_t *)&ihdr->ipha_dst;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw dst = ((uint32_t)(addrp[0]) << 24) | ((uint32_t)(addrp[1]) << 16) |
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ((uint32_t)(addrp[2]) << 8) | (uint32_t)(addrp[3]);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sum = (uint16_t)(src >> 16) +
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (uint16_t)(src) +
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (uint16_t)(dst >> 16) +
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw (uint16_t)(dst) + (udpp->uh_ulen + htons(IPPROTO_UDP));
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sum = (uint16_t)(sum >> 16) + (uint16_t)(sum);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (sum > 0xffff)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sum -= 0xffff;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw udpp->uh_sum = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw byte = mp->b_rptr + offset + iplen;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw do {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw len = (mp->b_wptr - byte);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sum = bcksum(byte, len, sum);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (sum > 0xffff)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sum -= 0xffff;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mp = mp->b_cont;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (mp)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw byte = mp->b_rptr;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } while (mp);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw sum = ~sum & 0xffff;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (sum);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}