a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * CDDL HEADER START
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * The contents of this file are subject to the terms of the
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Common Development and Distribution License (the "License").
a23fd118e437af0a7877dd313db8fdaa3537c675yl * You may not use this file except in compliance with the License.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a23fd118e437af0a7877dd313db8fdaa3537c675yl * or http://www.opensolaris.org/os/licensing.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * See the License for the specific language governing permissions
a23fd118e437af0a7877dd313db8fdaa3537c675yl * and limitations under the License.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * When distributing Covered Code, include this CDDL HEADER in each
a23fd118e437af0a7877dd313db8fdaa3537c675yl * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * If applicable, add the following below this CDDL HEADER, with the
a23fd118e437af0a7877dd313db8fdaa3537c675yl * fields enclosed by brackets "[]" replaced with your own identifying
a23fd118e437af0a7877dd313db8fdaa3537c675yl * information: Portions Copyright [yyyy] [name of copyright owner]
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * CDDL HEADER END
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Use is subject to license terms.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
f30c160edf27c0e40a231331fc03b8eae12e8f40Roamer * Copyright (c) 2002-2009 Neterion, Inc.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * All right Reserved.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * FileName : xgell.c
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Description: Xge Link Layer data path implementation
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl#include "xgell.h"
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl#include <netinet/ip.h>
a23fd118e437af0a7877dd313db8fdaa3537c675yl#include <netinet/tcp.h>
8347601bcb0a439f6e50fc36b4039a73d08700e1yl#include <netinet/udp.h>
a23fd118e437af0a7877dd313db8fdaa3537c675yl
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb#define XGELL_MAX_FRAME_SIZE(hldev) ((hldev)->config.mtu + \
a23fd118e437af0a7877dd313db8fdaa3537c675yl sizeof (struct ether_vlan_header))
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl#define HEADROOM 2 /* for DIX-only packets */
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylvoid header_free_func(void *arg) { }
a23fd118e437af0a7877dd313db8fdaa3537c675ylfrtn_t header_frtn = {header_free_func, NULL};
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/* DMA attributes used for Tx side */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic struct ddi_dma_attr tx_dma_attr = {
a23fd118e437af0a7877dd313db8fdaa3537c675yl DMA_ATTR_V0, /* dma_attr_version */
a23fd118e437af0a7877dd313db8fdaa3537c675yl 0x0ULL, /* dma_attr_addr_lo */
a23fd118e437af0a7877dd313db8fdaa3537c675yl 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_addr_hi */
7eced415e5dd557aef2d78483b5a7785f0e13670xw 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_count_max */
7eced415e5dd557aef2d78483b5a7785f0e13670xw#if defined(__sparc)
7eced415e5dd557aef2d78483b5a7785f0e13670xw 0x2000, /* dma_attr_align */
7eced415e5dd557aef2d78483b5a7785f0e13670xw#else
7eced415e5dd557aef2d78483b5a7785f0e13670xw 0x1000, /* dma_attr_align */
7eced415e5dd557aef2d78483b5a7785f0e13670xw#endif
7eced415e5dd557aef2d78483b5a7785f0e13670xw 0xFC00FC, /* dma_attr_burstsizes */
7eced415e5dd557aef2d78483b5a7785f0e13670xw 0x1, /* dma_attr_minxfer */
7eced415e5dd557aef2d78483b5a7785f0e13670xw 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_maxxfer */
a23fd118e437af0a7877dd313db8fdaa3537c675yl 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_seg */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl 18, /* dma_attr_sgllen */
7eced415e5dd557aef2d78483b5a7785f0e13670xw (unsigned int)1, /* dma_attr_granular */
a23fd118e437af0a7877dd313db8fdaa3537c675yl 0 /* dma_attr_flags */
a23fd118e437af0a7877dd313db8fdaa3537c675yl};
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * DMA attributes used when using ddi_dma_mem_alloc to
a23fd118e437af0a7877dd313db8fdaa3537c675yl * allocat HAL descriptors and Rx buffers during replenish
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic struct ddi_dma_attr hal_dma_attr = {
a23fd118e437af0a7877dd313db8fdaa3537c675yl DMA_ATTR_V0, /* dma_attr_version */
a23fd118e437af0a7877dd313db8fdaa3537c675yl 0x0ULL, /* dma_attr_addr_lo */
a23fd118e437af0a7877dd313db8fdaa3537c675yl 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_addr_hi */
7eced415e5dd557aef2d78483b5a7785f0e13670xw 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_count_max */
7eced415e5dd557aef2d78483b5a7785f0e13670xw#if defined(__sparc)
7eced415e5dd557aef2d78483b5a7785f0e13670xw 0x2000, /* dma_attr_align */
7eced415e5dd557aef2d78483b5a7785f0e13670xw#else
7eced415e5dd557aef2d78483b5a7785f0e13670xw 0x1000, /* dma_attr_align */
7eced415e5dd557aef2d78483b5a7785f0e13670xw#endif
7eced415e5dd557aef2d78483b5a7785f0e13670xw 0xFC00FC, /* dma_attr_burstsizes */
7eced415e5dd557aef2d78483b5a7785f0e13670xw 0x1, /* dma_attr_minxfer */
7eced415e5dd557aef2d78483b5a7785f0e13670xw 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_maxxfer */
a23fd118e437af0a7877dd313db8fdaa3537c675yl 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_seg */
a23fd118e437af0a7877dd313db8fdaa3537c675yl 1, /* dma_attr_sgllen */
7eced415e5dd557aef2d78483b5a7785f0e13670xw (unsigned int)1, /* dma_attr_sgllen */
7eced415e5dd557aef2d78483b5a7785f0e13670xw DDI_DMA_RELAXED_ORDERING /* dma_attr_flags */
a23fd118e437af0a7877dd313db8fdaa3537c675yl};
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylstruct ddi_dma_attr *p_hal_dma_attr = &hal_dma_attr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic int xgell_m_stat(void *, uint_t, uint64_t *);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic int xgell_m_start(void *);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic void xgell_m_stop(void *);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic int xgell_m_promisc(void *, boolean_t);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic int xgell_m_multicst(void *, boolean_t, const uint8_t *);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic void xgell_m_ioctl(void *, queue_t *, mblk_t *);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic boolean_t xgell_m_getcapab(void *, mac_capab_t, void *);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb#define XGELL_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB)
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic mac_callbacks_t xgell_m_callbacks = {
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb XGELL_M_CALLBACK_FLAGS,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb xgell_m_stat,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb xgell_m_start,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb xgell_m_stop,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb xgell_m_promisc,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb xgell_m_multicst,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng NULL,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb NULL,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer NULL,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb xgell_m_ioctl,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb xgell_m_getcapab
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb};
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_device_poll
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Timeout should call me every 1s. xge_callback_event_queued should call me
a23fd118e437af0a7877dd313db8fdaa3537c675yl * when HAL hope event was rescheduled.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*ARGSUSED*/
a23fd118e437af0a7877dd313db8fdaa3537c675ylvoid
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_device_poll(void *data)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgelldev_t *lldev = xge_hal_device_private(data);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_enter(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (lldev->is_initialized) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_poll(data);
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->timeout_id = timeout(xge_device_poll, data,
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGE_DEV_POLL_TICKS);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl } else if (lldev->in_reset == 1) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lldev->timeout_id = timeout(xge_device_poll, data,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl XGE_DEV_POLL_TICKS);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl } else {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lldev->timeout_id = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xge_device_poll_now
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Will call xge_device_poll() immediately
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylvoid
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_device_poll_now(void *data)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgelldev_t *lldev = xge_hal_device_private(data);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_enter(&lldev->genlock);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (lldev->is_initialized) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_device_poll(data);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_callback_link_up
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * This function called by HAL to notify HW link up state change.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylvoid
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_callback_link_up(void *userdata)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgelldev_t *lldev = (xgelldev_t *)userdata;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb mac_link_update(lldev->mh, LINK_STATE_UP);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_callback_link_down
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * This function called by HAL to notify HW link down state change.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylvoid
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_callback_link_down(void *userdata)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgelldev_t *lldev = (xgelldev_t *)userdata;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb mac_link_update(lldev->mh, LINK_STATE_DOWN);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_rx_buffer_replenish_all
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * To replenish all freed dtr(s) with buffers in free pool. It's called by
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * xgell_rx_buffer_recycle() or xgell_rx_1b_callback().
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Must be called with pool_lock held.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_buffer_replenish_all(xgell_rx_ring_t *ring)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_dtr_h dtr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rx_buffer_t *rx_buffer;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rxd_priv_t *rxd_priv;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_assert(mutex_owned(&bf_pool->pool_lock));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng while ((bf_pool->free > 0) &&
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (xge_hal_ring_dtr_reserve(ring->channelh, &dtr) == XGE_HAL_OK)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_assert(bf_pool->head);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_buffer = bf_pool->head;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->head = rx_buffer->next;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->free--;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_assert(rx_buffer->dma_addr);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl rxd_priv = (xgell_rxd_priv_t *)
7eced415e5dd557aef2d78483b5a7785f0e13670xw xge_hal_ring_dtr_private(ring->channelh, dtr);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_ring_dtr_1b_set(dtr, rx_buffer->dma_addr,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->size);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl rxd_priv->rx_buffer = rx_buffer;
7eced415e5dd557aef2d78483b5a7785f0e13670xw xge_hal_ring_dtr_post(ring->channelh, dtr);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_rx_buffer_release
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * The only thing done here is to put the buffer back to the pool.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Calling this function need be protected by mutex, bf_pool.pool_lock.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_rx_buffer_release(xgell_rx_buffer_t *rx_buffer)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *ring = rx_buffer->ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_assert(mutex_owned(&bf_pool->pool_lock));
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* Put the buffer back to pool */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_buffer->next = bf_pool->head;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->head = rx_buffer;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->free++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_rx_buffer_recycle
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Called by desballoc() to "free" the resource.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * We will try to replenish all descripters.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
7eced415e5dd557aef2d78483b5a7785f0e13670xw
7eced415e5dd557aef2d78483b5a7785f0e13670xw/*
7eced415e5dd557aef2d78483b5a7785f0e13670xw * Previously there were much lock contention between xgell_rx_1b_compl() and
7eced415e5dd557aef2d78483b5a7785f0e13670xw * xgell_rx_buffer_recycle(), which consumed a lot of CPU resources and had bad
7eced415e5dd557aef2d78483b5a7785f0e13670xw * effect on rx performance. A separate recycle list is introduced to overcome
7eced415e5dd557aef2d78483b5a7785f0e13670xw * this. The recycle list is used to record the rx buffer that has been recycled
7eced415e5dd557aef2d78483b5a7785f0e13670xw * and these buffers will be retuned back to the free list in bulk instead of
7eced415e5dd557aef2d78483b5a7785f0e13670xw * one-by-one.
7eced415e5dd557aef2d78483b5a7785f0e13670xw */
7eced415e5dd557aef2d78483b5a7785f0e13670xw
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_rx_buffer_recycle(char *arg)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rx_buffer_t *rx_buffer = (xgell_rx_buffer_t *)arg;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *ring = rx_buffer->ring;
7eced415e5dd557aef2d78483b5a7785f0e13670xw xgelldev_t *lldev = ring->lldev;
7eced415e5dd557aef2d78483b5a7785f0e13670xw xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw mutex_enter(&bf_pool->recycle_lock);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw rx_buffer->next = bf_pool->recycle_head;
7eced415e5dd557aef2d78483b5a7785f0e13670xw bf_pool->recycle_head = rx_buffer;
7eced415e5dd557aef2d78483b5a7785f0e13670xw if (bf_pool->recycle_tail == NULL)
7eced415e5dd557aef2d78483b5a7785f0e13670xw bf_pool->recycle_tail = rx_buffer;
7eced415e5dd557aef2d78483b5a7785f0e13670xw bf_pool->recycle++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Before finding a good way to set this hiwat, just always call to
a23fd118e437af0a7877dd313db8fdaa3537c675yl * replenish_all. *TODO*
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if ((lldev->is_initialized != 0) && (ring->live) &&
7eced415e5dd557aef2d78483b5a7785f0e13670xw (bf_pool->recycle >= XGELL_RX_BUFFER_RECYCLE_CACHE)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&bf_pool->pool_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->recycle_tail->next = bf_pool->head;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->head = bf_pool->recycle_head;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->recycle_head = bf_pool->recycle_tail = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->post -= bf_pool->recycle;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->free += bf_pool->recycle;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->recycle = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_buffer_replenish_all(ring);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&bf_pool->pool_lock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw mutex_exit(&bf_pool->recycle_lock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_rx_buffer_alloc
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Allocate one rx buffer and return with the pointer to the buffer.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Return NULL if failed.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic xgell_rx_buffer_t *
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_buffer_alloc(xgell_rx_ring_t *ring)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgelldev_t *lldev = ring->lldev;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_t *hldev;
a23fd118e437af0a7877dd313db8fdaa3537c675yl void *vaddr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_handle_t dma_handle;
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_acc_handle_t dma_acch;
a23fd118e437af0a7877dd313db8fdaa3537c675yl dma_addr_t dma_addr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl uint_t ncookies;
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_cookie_t dma_cookie;
a23fd118e437af0a7877dd313db8fdaa3537c675yl size_t real_size;
a23fd118e437af0a7877dd313db8fdaa3537c675yl extern ddi_device_acc_attr_t *p_xge_dev_attr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rx_buffer_t *rx_buffer;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hldev = (xge_hal_device_t *)lldev->devh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (ddi_dma_alloc_handle(hldev->pdev, p_hal_dma_attr, DDI_DMA_SLEEP,
a23fd118e437af0a7877dd313db8fdaa3537c675yl 0, &dma_handle) != DDI_SUCCESS) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: can not allocate DMA handle",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl goto handle_failed;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* reserve some space at the end of the buffer for recycling */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ddi_dma_mem_alloc(dma_handle, HEADROOM + bf_pool->size +
a23fd118e437af0a7877dd313db8fdaa3537c675yl sizeof (xgell_rx_buffer_t), p_xge_dev_attr, DDI_DMA_STREAMING,
a23fd118e437af0a7877dd313db8fdaa3537c675yl DDI_DMA_SLEEP, 0, (caddr_t *)&vaddr, &real_size, &dma_acch) !=
a23fd118e437af0a7877dd313db8fdaa3537c675yl DDI_SUCCESS) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: can not allocate DMA-able memory",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl goto mem_failed;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (HEADROOM + bf_pool->size + sizeof (xgell_rx_buffer_t) >
a23fd118e437af0a7877dd313db8fdaa3537c675yl real_size) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: can not allocate DMA-able memory",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl goto bind_failed;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (ddi_dma_addr_bind_handle(dma_handle, NULL, (char *)vaddr + HEADROOM,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->size, DDI_DMA_READ | DDI_DMA_STREAMING,
a23fd118e437af0a7877dd313db8fdaa3537c675yl DDI_DMA_SLEEP, 0, &dma_cookie, &ncookies) != DDI_SUCCESS) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: out of mapping for mblk",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl goto bind_failed;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ncookies != 1 || dma_cookie.dmac_size < bf_pool->size) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: can not handle partial DMA",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl goto check_failed;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl dma_addr = dma_cookie.dmac_laddress;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl rx_buffer = (xgell_rx_buffer_t *)((char *)vaddr + real_size -
a23fd118e437af0a7877dd313db8fdaa3537c675yl sizeof (xgell_rx_buffer_t));
a23fd118e437af0a7877dd313db8fdaa3537c675yl rx_buffer->next = NULL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl rx_buffer->vaddr = vaddr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl rx_buffer->dma_addr = dma_addr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl rx_buffer->dma_handle = dma_handle;
a23fd118e437af0a7877dd313db8fdaa3537c675yl rx_buffer->dma_acch = dma_acch;
7eced415e5dd557aef2d78483b5a7785f0e13670xw rx_buffer->ring = ring;
a23fd118e437af0a7877dd313db8fdaa3537c675yl rx_buffer->frtn.free_func = xgell_rx_buffer_recycle;
a23fd118e437af0a7877dd313db8fdaa3537c675yl rx_buffer->frtn.free_arg = (void *)rx_buffer;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (rx_buffer);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylcheck_failed:
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) ddi_dma_unbind_handle(dma_handle);
a23fd118e437af0a7877dd313db8fdaa3537c675ylbind_failed:
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGE_OS_MEMORY_CHECK_FREE(vaddr, 0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_mem_free(&dma_acch);
a23fd118e437af0a7877dd313db8fdaa3537c675ylmem_failed:
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_free_handle(&dma_handle);
a23fd118e437af0a7877dd313db8fdaa3537c675ylhandle_failed:
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (NULL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_rx_destroy_buffer_pool
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Destroy buffer pool. If there is still any buffer hold by upper layer,
a23fd118e437af0a7877dd313db8fdaa3537c675yl * recorded by bf_pool.post, return DDI_FAILURE to reject to be unloaded.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic boolean_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_destroy_buffer_pool(xgell_rx_ring_t *ring)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgelldev_t *lldev = ring->lldev;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rx_buffer_t *rx_buffer;
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_handle_t dma_handle;
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_acc_handle_t dma_acch;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int i;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If the pool has been destroied, just return B_TRUE
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!bf_pool->live)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_TRUE);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&bf_pool->recycle_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (bf_pool->recycle > 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&bf_pool->pool_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->recycle_tail->next = bf_pool->head;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->head = bf_pool->recycle_head;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->recycle_tail = bf_pool->recycle_head = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->post -= bf_pool->recycle;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->free += bf_pool->recycle;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->recycle = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&bf_pool->pool_lock);
7eced415e5dd557aef2d78483b5a7785f0e13670xw }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&bf_pool->recycle_lock);
7eced415e5dd557aef2d78483b5a7785f0e13670xw
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * If there is any posted buffer, the driver should reject to be
a23fd118e437af0a7877dd313db8fdaa3537c675yl * detached. Need notice upper layer to release them.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (bf_pool->post != 0) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR,
a23fd118e437af0a7877dd313db8fdaa3537c675yl "%s%d has some buffers not be recycled, try later!",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_FALSE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Release buffers one by one.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (i = bf_pool->total; i > 0; i--) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_buffer = bf_pool->head;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_assert(rx_buffer != NULL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->head = rx_buffer->next;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl dma_handle = rx_buffer->dma_handle;
a23fd118e437af0a7877dd313db8fdaa3537c675yl dma_acch = rx_buffer->dma_acch;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (ddi_dma_unbind_handle(dma_handle) != DDI_SUCCESS) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_ERR, "failed to unbind DMA handle!");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->head = rx_buffer;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_FALSE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_mem_free(&dma_acch);
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_free_handle(&dma_handle);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->total--;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->free--;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_assert(!mutex_owned(&bf_pool->pool_lock));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_destroy(&bf_pool->recycle_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_destroy(&bf_pool->pool_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->live = B_FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_TRUE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_rx_create_buffer_pool
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Initialize RX buffer pool for all RX rings. Refer to rx_buffer_pool_t.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic boolean_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_create_buffer_pool(xgell_rx_ring_t *ring)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgelldev_t *lldev = ring->lldev;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_t *hldev;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rx_buffer_t *rx_buffer;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int i;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (bf_pool->live)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_TRUE);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb hldev = (xge_hal_device_t *)lldev->devh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->total = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->size = XGELL_MAX_FRAME_SIZE(hldev);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->head = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->free = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->post = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->post_hiwat = lldev->config.rx_buffer_post_hiwat;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->recycle = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->recycle_head = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->recycle_tail = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->live = B_TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_init(&bf_pool->pool_lock, NULL, MUTEX_DRIVER,
7eced415e5dd557aef2d78483b5a7785f0e13670xw DDI_INTR_PRI(hldev->irqh));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_init(&bf_pool->recycle_lock, NULL, MUTEX_DRIVER,
7eced415e5dd557aef2d78483b5a7785f0e13670xw DDI_INTR_PRI(hldev->irqh));
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Allocate buffers one by one. If failed, destroy whole pool by
a23fd118e437af0a7877dd313db8fdaa3537c675yl * call to xgell_rx_destroy_buffer_pool().
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
7eced415e5dd557aef2d78483b5a7785f0e13670xw
a23fd118e437af0a7877dd313db8fdaa3537c675yl for (i = 0; i < lldev->config.rx_buffer_total; i++) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw if ((rx_buffer = xgell_rx_buffer_alloc(ring)) == NULL) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw (void) xgell_rx_destroy_buffer_pool(ring);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_FALSE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_buffer->next = bf_pool->head;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->head = rx_buffer;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->total++;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->free++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_TRUE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_rx_dtr_replenish
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Replenish descriptor with rx_buffer in RX buffer pool.
a23fd118e437af0a7877dd313db8fdaa3537c675yl * The dtr should be post right away.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylxge_hal_status_e
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_rx_dtr_replenish(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, int index,
a23fd118e437af0a7877dd313db8fdaa3537c675yl void *userdata, xge_hal_channel_reopen_e reopen)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *ring = userdata;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_buffer_pool_t *bf_pool = &ring->bf_pool;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rx_buffer_t *rx_buffer;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rxd_priv_t *rxd_priv;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&bf_pool->pool_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (bf_pool->head == NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_ERR, "no more available rx DMA buffer!");
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (XGE_HAL_FAIL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_buffer = bf_pool->head;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_assert(rx_buffer);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_assert(rx_buffer->dma_addr);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->head = rx_buffer->next;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng bf_pool->free--;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&bf_pool->pool_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
7eced415e5dd557aef2d78483b5a7785f0e13670xw rxd_priv = (xgell_rxd_priv_t *)xge_hal_ring_dtr_private(channelh, dtr);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_ring_dtr_1b_set(dtr, rx_buffer->dma_addr, bf_pool->size);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl rxd_priv->rx_buffer = rx_buffer;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (XGE_HAL_OK);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_get_ip_offset
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Calculate the offset to IP header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic inline int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_get_ip_offset(xge_hal_dtr_info_t *ext_info)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl int ip_off;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* get IP-header offset */
a23fd118e437af0a7877dd313db8fdaa3537c675yl switch (ext_info->frame) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl case XGE_HAL_FRAME_TYPE_DIX:
a23fd118e437af0a7877dd313db8fdaa3537c675yl ip_off = XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl case XGE_HAL_FRAME_TYPE_IPX:
a23fd118e437af0a7877dd313db8fdaa3537c675yl ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE +
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGE_HAL_HEADER_802_2_SIZE +
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGE_HAL_HEADER_SNAP_SIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl case XGE_HAL_FRAME_TYPE_LLC:
a23fd118e437af0a7877dd313db8fdaa3537c675yl ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE +
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGE_HAL_HEADER_802_2_SIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl case XGE_HAL_FRAME_TYPE_SNAP:
a23fd118e437af0a7877dd313db8fdaa3537c675yl ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE +
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGE_HAL_HEADER_SNAP_SIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl default:
a23fd118e437af0a7877dd313db8fdaa3537c675yl ip_off = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if ((ext_info->proto & XGE_HAL_FRAME_PROTO_IPV4 ||
a23fd118e437af0a7877dd313db8fdaa3537c675yl ext_info->proto & XGE_HAL_FRAME_PROTO_IPV6) &&
a23fd118e437af0a7877dd313db8fdaa3537c675yl (ext_info->proto & XGE_HAL_FRAME_PROTO_VLAN_TAGGED)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl ip_off += XGE_HAL_HEADER_VLAN_SIZE;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (ip_off);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_rx_hcksum_assoc
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Judge the packet type and then call to hcksum_assoc() to associate
a23fd118e437af0a7877dd313db8fdaa3537c675yl * h/w checksum information.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic inline void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_rx_hcksum_assoc(mblk_t *mp, char *vaddr, int pkt_length,
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_dtr_info_t *ext_info)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl int cksum_flags = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (!(ext_info->proto & XGE_HAL_FRAME_PROTO_IP_FRAGMENTED)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (ext_info->proto & XGE_HAL_FRAME_PROTO_TCP_OR_UDP) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (ext_info->l3_cksum == XGE_HAL_L3_CKSUM_OK) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer cksum_flags |= HCK_IPV4_HDRCKSUM_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (ext_info->l4_cksum == XGE_HAL_L4_CKSUM_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl cksum_flags |= HCK_FULLCKSUM_OK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer if (cksum_flags != 0) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_hcksum_set(mp, 0, 0, 0, 0, cksum_flags);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl } else if (ext_info->proto &
a23fd118e437af0a7877dd313db8fdaa3537c675yl (XGE_HAL_FRAME_PROTO_IPV4 | XGE_HAL_FRAME_PROTO_IPV6)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Just pass the partial cksum up to IP.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int ip_off = xgell_get_ip_offset(ext_info);
a23fd118e437af0a7877dd313db8fdaa3537c675yl int start, end = pkt_length - ip_off;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (ext_info->proto & XGE_HAL_FRAME_PROTO_IPV4) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl struct ip *ip =
a23fd118e437af0a7877dd313db8fdaa3537c675yl (struct ip *)(vaddr + ip_off);
f30c160edf27c0e40a231331fc03b8eae12e8f40Roamer start = ip->ip_hl * 4;
a23fd118e437af0a7877dd313db8fdaa3537c675yl } else {
f30c160edf27c0e40a231331fc03b8eae12e8f40Roamer start = 40;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl cksum_flags |= HCK_PARTIALCKSUM;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_hcksum_set(mp, start, 0, end,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ntohs(ext_info->l4_cksum), cksum_flags);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_rx_1b_msg_alloc
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Allocate message header for data buffer, and decide if copy the packet to
a23fd118e437af0a7877dd313db8fdaa3537c675yl * new data buffer to release big rx_buffer to save memory.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * If the pkt_length <= XGELL_RX_DMA_LOWAT, call allocb() to allocate
a23fd118e437af0a7877dd313db8fdaa3537c675yl * new message and copy the payload in.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic mblk_t *
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_1b_msg_alloc(xgell_rx_ring_t *ring, xgell_rx_buffer_t *rx_buffer,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int pkt_length, xge_hal_dtr_info_t *ext_info, boolean_t *copyit)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgelldev_t *lldev = ring->lldev;
a23fd118e437af0a7877dd313db8fdaa3537c675yl mblk_t *mp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl char *vaddr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl vaddr = (char *)rx_buffer->vaddr + HEADROOM;
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Copy packet into new allocated message buffer, if pkt_length
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * is less than XGELL_RX_DMA_LOWAT
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (*copyit || pkt_length <= lldev->config.rx_dma_lowat) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw if ((mp = allocb(pkt_length + HEADROOM, 0)) == NULL) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (NULL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
7eced415e5dd557aef2d78483b5a7785f0e13670xw mp->b_rptr += HEADROOM;
a23fd118e437af0a7877dd313db8fdaa3537c675yl bcopy(vaddr, mp->b_rptr, pkt_length);
a23fd118e437af0a7877dd313db8fdaa3537c675yl mp->b_wptr = mp->b_rptr + pkt_length;
a23fd118e437af0a7877dd313db8fdaa3537c675yl *copyit = B_TRUE;
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (mp);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Just allocate mblk for current data buffer
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
3c785c4c5ac4bb72eb0cff3cda1255dfc9613aa1yl if ((mp = (mblk_t *)desballoc((unsigned char *)vaddr, pkt_length, 0,
a23fd118e437af0a7877dd313db8fdaa3537c675yl &rx_buffer->frtn)) == NULL) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* Drop it */
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (NULL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
3c785c4c5ac4bb72eb0cff3cda1255dfc9613aa1yl * Adjust the b_rptr/b_wptr in the mblk_t structure.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
3c785c4c5ac4bb72eb0cff3cda1255dfc9613aa1yl mp->b_wptr += pkt_length;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (mp);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * xgell_rx_1b_callback
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * If the interrupt is because of a received frame or if the receive ring
a23fd118e437af0a7877dd313db8fdaa3537c675yl * contains fresh as yet un-processed frames, this function is called.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic xge_hal_status_e
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_1b_callback(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code,
a23fd118e437af0a7877dd313db8fdaa3537c675yl void *userdata)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *ring = (xgell_rx_ring_t *)userdata;
7eced415e5dd557aef2d78483b5a7785f0e13670xw xgelldev_t *lldev = ring->lldev;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rx_buffer_t *rx_buffer;
a23fd118e437af0a7877dd313db8fdaa3537c675yl mblk_t *mp_head = NULL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl mblk_t *mp_end = NULL;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int pkt_burst = 0;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_TRACE, "xgell_rx_1b_callback on ring %d", ring->index);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&ring->bf_pool.pool_lock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl do {
a23fd118e437af0a7877dd313db8fdaa3537c675yl int pkt_length;
a23fd118e437af0a7877dd313db8fdaa3537c675yl dma_addr_t dma_data;
a23fd118e437af0a7877dd313db8fdaa3537c675yl mblk_t *mp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl boolean_t copyit = B_FALSE;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rxd_priv_t *rxd_priv = ((xgell_rxd_priv_t *)
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_ring_dtr_private(channelh, dtr));
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_dtr_info_t ext_info;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl rx_buffer = rxd_priv->rx_buffer;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_ring_dtr_1b_get(channelh, dtr, &dma_data, &pkt_length);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_ring_dtr_info_get(channelh, dtr, &ext_info);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_assert(dma_data == rx_buffer->dma_addr);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (t_code != 0) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: rx: dtr 0x%"PRIx64
a23fd118e437af0a7877dd313db8fdaa3537c675yl " completed due to error t_code %01x", XGELL_IFNAME,
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->instance, (uint64_t)(uintptr_t)dtr, t_code);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) xge_hal_device_handle_tcode(channelh, dtr,
a23fd118e437af0a7877dd313db8fdaa3537c675yl t_code);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_ring_dtr_free(channelh, dtr); /* drop it */
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rx_buffer_release(rx_buffer);
a23fd118e437af0a7877dd313db8fdaa3537c675yl continue;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Sync the DMA memory
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (ddi_dma_sync(rx_buffer->dma_handle, 0, pkt_length,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl DDI_DMA_SYNC_FORKERNEL) != DDI_SUCCESS) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: rx: can not do DMA sync",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_ring_dtr_free(channelh, dtr); /* drop it */
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rx_buffer_release(rx_buffer);
a23fd118e437af0a7877dd313db8fdaa3537c675yl continue;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Allocate message for the packet.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
7eced415e5dd557aef2d78483b5a7785f0e13670xw if (ring->bf_pool.post > ring->bf_pool.post_hiwat) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl copyit = B_TRUE;
a23fd118e437af0a7877dd313db8fdaa3537c675yl } else {
a23fd118e437af0a7877dd313db8fdaa3537c675yl copyit = B_FALSE;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mp = xgell_rx_1b_msg_alloc(ring, rx_buffer, pkt_length,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl &ext_info, &copyit);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_ring_dtr_free(channelh, dtr);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Release the buffer and recycle it later
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl if ((mp == NULL) || copyit) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rx_buffer_release(rx_buffer);
a23fd118e437af0a7877dd313db8fdaa3537c675yl } else {
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Count it since the buffer should be loaned up.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
7eced415e5dd557aef2d78483b5a7785f0e13670xw ring->bf_pool.post++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (mp == NULL) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl "%s%d: rx: can not allocate mp mblk",
8347601bcb0a439f6e50fc36b4039a73d08700e1yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl continue;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Associate cksum_flags per packet type and h/w
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * cksum flags.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_hcksum_assoc(mp, (char *)rx_buffer->vaddr + HEADROOM,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng pkt_length, &ext_info);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ring->rx_pkts++;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ring->rx_bytes += pkt_length;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (mp_head == NULL) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl mp_head = mp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl mp_end = mp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl } else {
a23fd118e437af0a7877dd313db8fdaa3537c675yl mp_end->b_next = mp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl mp_end = mp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Inlined implemented polling function.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if ((ring->poll_mp == NULL) && (ring->poll_bytes > 0)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->poll_mp = mp_head;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ring->poll_mp != NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if ((ring->poll_bytes -= pkt_length) <= 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* have polled enough packets. */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng break;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* continue polling packets. */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng continue;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * We're not in polling mode, so try to chain more messages
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * or send the chain up according to pkt_burst.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (++pkt_burst < lldev->config.rx_pkt_burst)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl continue;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw if (ring->bf_pool.post > ring->bf_pool.post_hiwat) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* Replenish rx buffers */
7eced415e5dd557aef2d78483b5a7785f0e13670xw xgell_rx_buffer_replenish_all(ring);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
7eced415e5dd557aef2d78483b5a7785f0e13670xw mutex_exit(&ring->bf_pool.pool_lock);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (mp_head != NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_rx_ring(lldev->mh, ring->ring_handle, mp_head,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->ring_gen_num);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl mp_head = mp_end = NULL;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl pkt_burst = 0;
7eced415e5dd557aef2d78483b5a7785f0e13670xw mutex_enter(&ring->bf_pool.pool_lock);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl } while (xge_hal_ring_dtr_next_completed(channelh, &dtr, &t_code) ==
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGE_HAL_OK);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Always call replenish_all to recycle rx_buffers.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
7eced415e5dd557aef2d78483b5a7785f0e13670xw xgell_rx_buffer_replenish_all(ring);
7eced415e5dd557aef2d78483b5a7785f0e13670xw mutex_exit(&ring->bf_pool.pool_lock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If we're not in polling cycle, call mac_rx(), otherwise
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * just return while leaving packets chained to ring->poll_mp.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if ((ring->poll_mp == NULL) && (mp_head != NULL)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_rx_ring(lldev->mh, ring->ring_handle, mp_head,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->ring_gen_num);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (XGE_HAL_OK);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmblk_t *
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_poll(void *arg, int bytes_to_pickup)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *ring = (xgell_rx_ring_t *)arg;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int got_rx = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mblk_t *mp;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_TRACE, "xgell_rx_poll on ring %d", ring->index);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->poll_mp = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->poll_bytes = bytes_to_pickup;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) xge_hal_device_poll_rx_channel(ring->channelh, &got_rx);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mp = ring->poll_mp;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->poll_bytes = -1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->polled_bytes += got_rx;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->poll_mp = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (mp);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_xmit_compl
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * If an interrupt was raised to indicate DMA complete of the Tx packet,
a23fd118e437af0a7877dd313db8fdaa3537c675yl * this function is called. It identifies the last TxD whose buffer was
a23fd118e437af0a7877dd313db8fdaa3537c675yl * freed and frees all skbs whose data have already DMA'ed into the NICs
a23fd118e437af0a7877dd313db8fdaa3537c675yl * internal memory.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic xge_hal_status_e
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_xmit_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code,
a23fd118e437af0a7877dd313db8fdaa3537c675yl void *userdata)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_tx_ring_t *ring = userdata;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgelldev_t *lldev = ring->lldev;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl do {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_txd_priv_t *txd_priv = ((xgell_txd_priv_t *)
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_fifo_dtr_private(dtr));
a23fd118e437af0a7877dd313db8fdaa3537c675yl int i;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (t_code) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "%s%d: tx: dtr 0x%"PRIx64
a23fd118e437af0a7877dd313db8fdaa3537c675yl " completed due to error t_code %01x", XGELL_IFNAME,
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->instance, (uint64_t)(uintptr_t)dtr, t_code);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) xge_hal_device_handle_tcode(channelh, dtr,
a23fd118e437af0a7877dd313db8fdaa3537c675yl t_code);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl for (i = 0; i < txd_priv->handle_cnt; i++) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw if (txd_priv->dma_handles[i] != NULL) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw xge_assert(txd_priv->dma_handles[i]);
7eced415e5dd557aef2d78483b5a7785f0e13670xw (void) ddi_dma_unbind_handle(
7eced415e5dd557aef2d78483b5a7785f0e13670xw txd_priv->dma_handles[i]);
7eced415e5dd557aef2d78483b5a7785f0e13670xw ddi_dma_free_handle(&txd_priv->dma_handles[i]);
7eced415e5dd557aef2d78483b5a7785f0e13670xw txd_priv->dma_handles[i] = 0;
7eced415e5dd557aef2d78483b5a7785f0e13670xw }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
7eced415e5dd557aef2d78483b5a7785f0e13670xw txd_priv->handle_cnt = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_fifo_dtr_free(channelh, dtr);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw if (txd_priv->mblk != NULL) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw freemsg(txd_priv->mblk);
7eced415e5dd557aef2d78483b5a7785f0e13670xw txd_priv->mblk = NULL;
7eced415e5dd557aef2d78483b5a7785f0e13670xw }
7eced415e5dd557aef2d78483b5a7785f0e13670xw
a23fd118e437af0a7877dd313db8fdaa3537c675yl } while (xge_hal_fifo_dtr_next_completed(channelh, &dtr, &t_code) ==
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGE_HAL_OK);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ring->need_resched)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_tx_ring_update(lldev->mh, ring->ring_handle);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (XGE_HAL_OK);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Chengmblk_t *
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_ring_tx(void *arg, mblk_t *mp)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_tx_ring_t *ring = (xgell_tx_ring_t *)arg;
a23fd118e437af0a7877dd313db8fdaa3537c675yl mblk_t *bp;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgelldev_t *lldev = ring->lldev;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_device_t *hldev = lldev->devh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_dtr_h dtr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_txd_priv_t *txd_priv;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl uint32_t hckflags;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng uint32_t lsoflags;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl uint32_t mss;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl int handle_cnt, frag_cnt, ret, i, copied;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl boolean_t used_copy;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer uint64_t sent_bytes;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl_begin:
a23fd118e437af0a7877dd313db8fdaa3537c675yl handle_cnt = frag_cnt = 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer sent_bytes = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (!lldev->is_initialized || lldev->in_reset)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (mp);
7eced415e5dd557aef2d78483b5a7785f0e13670xw
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * If the free Tx dtrs count reaches the lower threshold,
a23fd118e437af0a7877dd313db8fdaa3537c675yl * inform the gld to stop sending more packets till the free
a23fd118e437af0a7877dd313db8fdaa3537c675yl * dtrs count exceeds higher threshold. Driver informs the
a23fd118e437af0a7877dd313db8fdaa3537c675yl * gld through gld_sched call, when the free dtrs count exceeds
a23fd118e437af0a7877dd313db8fdaa3537c675yl * the higher threshold.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (xge_hal_channel_dtr_count(ring->channelh)
a23fd118e437af0a7877dd313db8fdaa3537c675yl <= XGELL_TX_LEVEL_LOW) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_TRACE, "%s%d: queue %d: err on xmit,"
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "free descriptors count at low threshold %d",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng XGELL_IFNAME, lldev->instance,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ((xge_hal_channel_t *)ring->channelh)->post_qid,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng XGELL_TX_LEVEL_LOW);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng goto _exit;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng status = xge_hal_fifo_dtr_reserve(ring->channelh, &dtr);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl switch (status) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl case XGE_HAL_INF_CHANNEL_IS_NOT_READY:
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR,
a23fd118e437af0a7877dd313db8fdaa3537c675yl "%s%d: channel %d is not ready.", XGELL_IFNAME,
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->instance,
a23fd118e437af0a7877dd313db8fdaa3537c675yl ((xge_hal_channel_t *)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->channelh)->post_qid);
a23fd118e437af0a7877dd313db8fdaa3537c675yl goto _exit;
a23fd118e437af0a7877dd313db8fdaa3537c675yl case XGE_HAL_INF_OUT_OF_DESCRIPTORS:
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "%s%d: queue %d: error in xmit,"
a23fd118e437af0a7877dd313db8fdaa3537c675yl " out of descriptors.", XGELL_IFNAME,
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->instance,
a23fd118e437af0a7877dd313db8fdaa3537c675yl ((xge_hal_channel_t *)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->channelh)->post_qid);
a23fd118e437af0a7877dd313db8fdaa3537c675yl goto _exit;
a23fd118e437af0a7877dd313db8fdaa3537c675yl default:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (mp);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl txd_priv = xge_hal_fifo_dtr_private(dtr);
a23fd118e437af0a7877dd313db8fdaa3537c675yl txd_priv->mblk = mp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * VLAN tag should be passed down along with MAC header, so h/w needn't
a23fd118e437af0a7877dd313db8fdaa3537c675yl * do insertion.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * For NIC driver that has to strip and re-insert VLAN tag, the example
a23fd118e437af0a7877dd313db8fdaa3537c675yl * is the other implementation for xge. The driver can simple bcopy()
a23fd118e437af0a7877dd313db8fdaa3537c675yl * ether_vlan_header to overwrite VLAN tag and let h/w insert the tag
a23fd118e437af0a7877dd313db8fdaa3537c675yl * automatically, since it's impossible that GLD sends down mp(s) with
a23fd118e437af0a7877dd313db8fdaa3537c675yl * splited ether_vlan_header.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * struct ether_vlan_header *evhp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl * uint16_t tci;
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * evhp = (struct ether_vlan_header *)mp->b_rptr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl * if (evhp->ether_tpid == htons(VLAN_TPID)) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * tci = ntohs(evhp->ether_tci);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * (void) bcopy(mp->b_rptr, mp->b_rptr + VLAN_TAGSZ,
a23fd118e437af0a7877dd313db8fdaa3537c675yl * 2 * ETHERADDRL);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * mp->b_rptr += VLAN_TAGSZ;
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * xge_hal_fifo_dtr_vlan_set(dtr, tci);
a23fd118e437af0a7877dd313db8fdaa3537c675yl * }
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl copied = 0;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl used_copy = B_FALSE;
a23fd118e437af0a7877dd313db8fdaa3537c675yl for (bp = mp; bp != NULL; bp = bp->b_cont) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl int mblen;
a23fd118e437af0a7877dd313db8fdaa3537c675yl uint_t ncookies;
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_cookie_t dma_cookie;
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_handle_t dma_handle;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* skip zero-length message blocks */
a23fd118e437af0a7877dd313db8fdaa3537c675yl mblen = MBLKL(bp);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (mblen == 0) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl continue;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer sent_bytes += mblen;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * Check the message length to decide to DMA or bcopy() data
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * to tx descriptor(s).
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (mblen < lldev->config.tx_dma_lowat &&
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (copied + mblen) < lldev->tx_copied_max) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_status_e rc;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rc = xge_hal_fifo_dtr_buffer_append(ring->channelh,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl dtr, bp->b_rptr, mblen);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (rc == XGE_HAL_OK) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl used_copy = B_TRUE;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl copied += mblen;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl continue;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl } else if (used_copy) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_fifo_dtr_buffer_finalize(
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->channelh, dtr, frag_cnt++);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl used_copy = B_FALSE;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl } else if (used_copy) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_fifo_dtr_buffer_finalize(ring->channelh,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl dtr, frag_cnt++);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl used_copy = B_FALSE;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb ret = ddi_dma_alloc_handle(lldev->dev_info, &tx_dma_attr,
a23fd118e437af0a7877dd313db8fdaa3537c675yl DDI_DMA_DONTWAIT, 0, &dma_handle);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (ret != DDI_SUCCESS) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl "%s%d: can not allocate dma handle", XGELL_IFNAME,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl goto _exit_cleanup;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl ret = ddi_dma_addr_bind_handle(dma_handle, NULL,
a23fd118e437af0a7877dd313db8fdaa3537c675yl (caddr_t)bp->b_rptr, mblen,
a23fd118e437af0a7877dd313db8fdaa3537c675yl DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 0,
a23fd118e437af0a7877dd313db8fdaa3537c675yl &dma_cookie, &ncookies);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl switch (ret) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl case DDI_DMA_MAPPED:
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* everything's fine */
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case DDI_DMA_NORESOURCES:
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR,
a23fd118e437af0a7877dd313db8fdaa3537c675yl "%s%d: can not bind dma address",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_free_handle(&dma_handle);
a23fd118e437af0a7877dd313db8fdaa3537c675yl goto _exit_cleanup;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case DDI_DMA_NOMAPPING:
a23fd118e437af0a7877dd313db8fdaa3537c675yl case DDI_DMA_INUSE:
a23fd118e437af0a7877dd313db8fdaa3537c675yl case DDI_DMA_TOOBIG:
a23fd118e437af0a7877dd313db8fdaa3537c675yl default:
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* drop packet, don't retry */
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR,
a23fd118e437af0a7877dd313db8fdaa3537c675yl "%s%d: can not map message buffer",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_free_handle(&dma_handle);
a23fd118e437af0a7877dd313db8fdaa3537c675yl goto _exit_cleanup;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (ncookies + frag_cnt > hldev->config.fifo.max_frags) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: too many fragments, "
a23fd118e437af0a7877dd313db8fdaa3537c675yl "requested c:%d+f:%d", XGELL_IFNAME,
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->instance, ncookies, frag_cnt);
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) ddi_dma_unbind_handle(dma_handle);
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_free_handle(&dma_handle);
a23fd118e437af0a7877dd313db8fdaa3537c675yl goto _exit_cleanup;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* setup the descriptors for this data buffer */
a23fd118e437af0a7877dd313db8fdaa3537c675yl while (ncookies) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_fifo_dtr_buffer_set(ring->channelh, dtr,
a23fd118e437af0a7877dd313db8fdaa3537c675yl frag_cnt++, dma_cookie.dmac_laddress,
a23fd118e437af0a7877dd313db8fdaa3537c675yl dma_cookie.dmac_size);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (--ncookies) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_nextcookie(dma_handle, &dma_cookie);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl txd_priv->dma_handles[handle_cnt++] = dma_handle;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (bp->b_cont &&
a23fd118e437af0a7877dd313db8fdaa3537c675yl (frag_cnt + XGE_HAL_DEFAULT_FIFO_FRAGS_THRESHOLD >=
7eced415e5dd557aef2d78483b5a7785f0e13670xw hldev->config.fifo.max_frags)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl mblk_t *nmp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE,
a23fd118e437af0a7877dd313db8fdaa3537c675yl "too many FRAGs [%d], pull up them", frag_cnt);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if ((nmp = msgpullup(bp->b_cont, -1)) == NULL) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* Drop packet, don't retry */
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR,
a23fd118e437af0a7877dd313db8fdaa3537c675yl "%s%d: can not pullup message buffer",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl goto _exit_cleanup;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl freemsg(bp->b_cont);
a23fd118e437af0a7877dd313db8fdaa3537c675yl bp->b_cont = nmp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* finalize unfinished copies */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (used_copy) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_fifo_dtr_buffer_finalize(ring->channelh, dtr,
8347601bcb0a439f6e50fc36b4039a73d08700e1yl frag_cnt++);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl txd_priv->handle_cnt = handle_cnt;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /*
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * If LSO is required, just call xge_hal_fifo_dtr_mss_set(dtr, mss) to
8347601bcb0a439f6e50fc36b4039a73d08700e1yl * do all necessary work.
8347601bcb0a439f6e50fc36b4039a73d08700e1yl */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_lso_get(mp, &mss, &lsoflags);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (lsoflags & HW_LSO) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_assert((mss != 0) && (mss <= XGE_HAL_DEFAULT_MTU));
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_fifo_dtr_mss_set(dtr, mss);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_hcksum_get(mp, NULL, NULL, NULL, NULL, &hckflags);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (hckflags & HCK_IPV4_HDRCKSUM) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_fifo_dtr_cksum_set_bits(dtr,
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGE_HAL_TXD_TX_CKO_IPV4_EN);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (hckflags & HCK_FULLCKSUM) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_fifo_dtr_cksum_set_bits(dtr, XGE_HAL_TXD_TX_CKO_TCP_EN |
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGE_HAL_TXD_TX_CKO_UDP_EN);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_fifo_dtr_post(ring->channelh, dtr);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer /* Update per-ring tx statistics */
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek atomic_inc_64(&ring->tx_pkts);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer atomic_add_64(&ring->tx_bytes, sent_bytes);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (NULL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl_exit_cleanup:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Could not successfully transmit but have changed the message,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * so just free it and return NULL
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
a23fd118e437af0a7877dd313db8fdaa3537c675yl for (i = 0; i < handle_cnt; i++) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) ddi_dma_unbind_handle(txd_priv->dma_handles[i]);
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_free_handle(&txd_priv->dma_handles[i]);
a23fd118e437af0a7877dd313db8fdaa3537c675yl txd_priv->dma_handles[i] = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_fifo_dtr_free(ring->channelh, dtr);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng freemsg(mp);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (NULL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl_exit:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->need_resched = B_TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (mp);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * xgell_ring_macaddr_init
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_ring_maddr_init(xgell_rx_ring_t *ring)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int i;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgelldev_t *lldev = ring->lldev;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_device_t *hldev = lldev->devh;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int slot_start;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_TRACE, "%s", "xgell_rx_ring_maddr_init");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->mmac.naddr = XGE_RX_MULTI_MAC_ADDRESSES_MAX;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->mmac.naddrfree = ring->mmac.naddr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * For the default rx ring, the first MAC address is the factory one.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * This will be set by the framework, so need to clear it for now.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) xge_hal_device_macaddr_clear(hldev, 0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Read the MAC address Configuration Memory from HAL.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * The first slot will hold a factory MAC address, contents in other
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * slots will be FF:FF:FF:FF:FF:FF.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng slot_start = ring->index * 32;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (i = 0; i < ring->mmac.naddr; i++) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) xge_hal_device_macaddr_get(hldev, slot_start + i,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->mmac.mac_addr + i);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->mmac.mac_addr_set[i] = B_FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic int xgell_maddr_set(xgelldev_t *, int, uint8_t *);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic int
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_addmac(void *arg, const uint8_t *mac_addr)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *ring = arg;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgelldev_t *lldev = ring->lldev;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_device_t *hldev = lldev->devh;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int slot;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int slot_start;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_TRACE, "%s", "xgell_addmac");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&lldev->genlock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ring->mmac.naddrfree == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&lldev->genlock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (ENOSPC);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* First slot is for factory MAC address */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (slot = 0; slot < ring->mmac.naddr; slot++) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (ring->mmac.mac_addr_set[slot] == B_FALSE) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ASSERT(slot < ring->mmac.naddr);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng slot_start = ring->index * 32;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (xgell_maddr_set(lldev, slot_start + slot, (uint8_t *)mac_addr) !=
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&lldev->genlock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (EIO);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Simply enable RTS for the whole section. */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) xge_hal_device_rts_section_enable(hldev, slot_start + slot);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Read back the MAC address from HAL to keep the array up to date.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (xge_hal_device_macaddr_get(hldev, slot_start + slot,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->mmac.mac_addr + slot) != XGE_HAL_OK) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) xge_hal_device_macaddr_clear(hldev, slot_start + slot);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (EIO);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->mmac.mac_addr_set[slot] = B_TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->mmac.naddrfree--;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&lldev->genlock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic int
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_remmac(void *arg, const uint8_t *mac_addr)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *ring = arg;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgelldev_t *lldev = ring->lldev;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_device_t *hldev = lldev->devh;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_status_e status;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int slot;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int slot_start;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_TRACE, "%s", "xgell_remmac");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng slot = xge_hal_device_macaddr_find(hldev, (uint8_t *)mac_addr);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (slot == -1)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (EINVAL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng slot_start = ring->index * 32;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Adjust slot to the offset in the MAC array of this ring (group).
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng slot -= slot_start;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Only can remove a pre-set MAC address for this ring (group).
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (slot < 0 || slot >= ring->mmac.naddr)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (EINVAL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_assert(ring->mmac.mac_addr_set[slot]);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&lldev->genlock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!ring->mmac.mac_addr_set[slot]) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&lldev->genlock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * The result will be unexpected when reach here. WARNING!
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_ERR,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "%s%d: caller is trying to remove an unset MAC address",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng XGELL_IFNAME, lldev->instance);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (ENXIO);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng status = xge_hal_device_macaddr_clear(hldev, slot_start + slot);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (status != XGE_HAL_OK) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&lldev->genlock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (EIO);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->mmac.mac_addr_set[slot] = B_FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->mmac.naddrfree++;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * TODO: Disable MAC RTS if all addresses have been cleared.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Read back the MAC address from HAL to keep the array up to date.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) xge_hal_device_macaddr_get(hldev, slot_start + slot,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ring->mmac.mac_addr + slot);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&lldev->genlock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Temporarily calling hal function.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * With MSI-X implementation, no lock is needed, so that the interrupt
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * handling could be faster.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengint
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_ring_intr_enable(mac_intr_handle_t ih)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *ring = (xgell_rx_ring_t *)ih;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&ring->ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_device_rx_channel_disable_polling(ring->channelh);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ring->ring_lock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengint
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_ring_intr_disable(mac_intr_handle_t ih)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *ring = (xgell_rx_ring_t *)ih;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_enter(&ring->ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_device_rx_channel_enable_polling(ring->channelh);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_exit(&ring->ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic int
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *rx_ring = (xgell_rx_ring_t *)rh;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->ring_gen_num = mr_gen_num;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*ARGSUSED*/
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_ring_stop(mac_ring_driver_t rh)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*ARGSUSED*/
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic int
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_tx_ring_start(mac_ring_driver_t rh, uint64_t useless)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*ARGSUSED*/
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_tx_ring_stop(mac_ring_driver_t rh)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Callback funtion for MAC layer to register all rings.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Xframe hardware doesn't support grouping explicitly, so the driver needs
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * to pretend having resource groups. We may also optionally group all 8 rx
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * rings into a single group for increased scalability on CMT architectures,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * or group one rx ring per group for maximum virtualization.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * TX grouping is actually done by framework, so, just register all TX
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * resources without grouping them.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng const int index, mac_ring_info_t *infop, mac_ring_handle_t rh)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgelldev_t *lldev = (xgelldev_t *)arg;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_intr_t *mintr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng switch (rtype) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng case MAC_RING_TYPE_RX: {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *rx_ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_assert(index < lldev->init_rx_rings);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_assert(rg_index < lldev->init_rx_groups);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Performance vs. Virtualization
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (lldev->init_rx_rings == lldev->init_rx_groups)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring = lldev->rx_ring + rg_index;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng else
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring = lldev->rx_ring + index;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->ring_handle = rh;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mri_driver = (mac_ring_driver_t)rx_ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mri_start = xgell_rx_ring_start;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mri_stop = xgell_rx_ring_stop;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mri_poll = xgell_rx_poll;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer infop->mri_stat = xgell_rx_ring_stat;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mintr = &infop->mri_intr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mintr->mi_handle = (mac_intr_handle_t)rx_ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mintr->mi_enable = xgell_rx_ring_intr_enable;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mintr->mi_disable = xgell_rx_ring_intr_disable;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng case MAC_RING_TYPE_TX: {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_tx_ring_t *tx_ring;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_assert(rg_index == -1);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_assert((index >= 0) && (index < lldev->init_tx_rings));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tx_ring = lldev->tx_ring + index;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tx_ring->ring_handle = rh;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mri_driver = (mac_ring_driver_t)tx_ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mri_start = xgell_tx_ring_start;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mri_stop = xgell_tx_ring_stop;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mri_tx = xgell_ring_tx;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer infop->mri_stat = xgell_tx_ring_stat;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng break;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng default:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng break;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_fill_group(void *arg, mac_ring_type_t rtype, const int index,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_group_info_t *infop, mac_group_handle_t gh)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgelldev_t *lldev = (xgelldev_t *)arg;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng switch (rtype) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng case MAC_RING_TYPE_RX: {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *rx_ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_assert(index < lldev->init_rx_groups);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring = lldev->rx_ring + index;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->group_handle = gh;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mgi_driver = (mac_group_driver_t)rx_ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mgi_start = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mgi_stop = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mgi_addmac = xgell_addmac;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mgi_remmac = xgell_remmac;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng infop->mgi_count = lldev->init_rx_rings / lldev->init_rx_groups;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng break;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng case MAC_RING_TYPE_TX:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_assert(0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng break;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng default:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng break;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * xgell_macaddr_set
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic int
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_maddr_set(xgelldev_t *lldev, int index, uint8_t *macaddr)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_device_t *hldev = lldev->devh;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_status_e status;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_TRACE, "%s", "xgell_maddr_set");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_TRACE,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "setting macaddr: 0x%02x-%02x-%02x-%02x-%02x-%02x",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng macaddr[0], macaddr[1], macaddr[2],
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng macaddr[3], macaddr[4], macaddr[5]);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng status = xge_hal_device_macaddr_set(hldev, index, (uchar_t *)macaddr);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (status != XGE_HAL_OK) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_ERR, "%s%d: can not set mac address",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng XGELL_IFNAME, lldev->instance);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (EIO);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_rx_dtr_term
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Function will be called by HAL to terminate all DTRs for
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Ring(s) type of channels.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_rx_dtr_term(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_dtr_state_e state, void *userdata, xge_hal_channel_reopen_e reopen)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rxd_priv_t *rxd_priv =
a23fd118e437af0a7877dd313db8fdaa3537c675yl ((xgell_rxd_priv_t *)xge_hal_ring_dtr_private(channelh, dtrh));
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rx_buffer_t *rx_buffer = rxd_priv->rx_buffer;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (state == XGE_HAL_DTR_STATE_POSTED) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *ring = rx_buffer->ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
7eced415e5dd557aef2d78483b5a7785f0e13670xw mutex_enter(&ring->bf_pool.pool_lock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_ring_dtr_free(channelh, dtrh);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_rx_buffer_release(rx_buffer);
7eced415e5dd557aef2d78483b5a7785f0e13670xw mutex_exit(&ring->bf_pool.pool_lock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * To open a rx ring.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic boolean_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_ring_open(xgell_rx_ring_t *rx_ring)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_status_e status;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_channel_attr_t attr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgelldev_t *lldev = rx_ring->lldev;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_device_t *hldev = lldev->devh;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (rx_ring->live)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_TRUE);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Create the buffer pool first */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!xgell_rx_create_buffer_pool(rx_ring)) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_ERR, "can not create buffer pool for ring: %d",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->index);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_FALSE);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* Default ring initialization */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng attr.post_qid = rx_ring->index;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng attr.compl_qid = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng attr.callback = xgell_rx_1b_callback;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng attr.per_dtr_space = sizeof (xgell_rxd_priv_t);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng attr.flags = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng attr.type = XGE_HAL_CHANNEL_TYPE_RING;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng attr.dtr_init = xgell_rx_dtr_replenish;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng attr.dtr_term = xgell_rx_dtr_term;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng attr.userdata = rx_ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng status = xge_hal_channel_open(lldev->devh, &attr, &rx_ring->channelh,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng XGE_HAL_CHANNEL_OC_NORMAL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (status != XGE_HAL_OK) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_ERR, "%s%d: cannot open Rx channel got status "
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng " code %d", XGELL_IFNAME, lldev->instance, status);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) xgell_rx_destroy_buffer_pool(rx_ring);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_FALSE);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_maddr_init(rx_ring);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_init(&rx_ring->ring_lock, NULL, MUTEX_DRIVER,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng DDI_INTR_PRI(hldev->irqh));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->poll_bytes = -1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->polled_bytes = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->poll_mp = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->live = B_TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_TRACE, "RX ring [%d] is opened successfully",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->index);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_TRUE);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_ring_close(xgell_rx_ring_t *rx_ring)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!rx_ring->live)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_channel_close(rx_ring->channelh, XGE_HAL_CHANNEL_OC_NORMAL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->channelh = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /* This may not clean up all used buffers, driver will handle it */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (xgell_rx_destroy_buffer_pool(rx_ring))
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->live = B_FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mutex_destroy(&rx_ring->ring_lock);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * xgell_rx_open
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * @lldev: the link layer object
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Initialize and open all RX channels.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic boolean_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_open(xgelldev_t *lldev)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *rx_ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int i;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (lldev->live_rx_rings != 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_TRUE);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng lldev->live_rx_rings = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Initialize all rings
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (i = 0; i < lldev->init_rx_rings; i++) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring = &lldev->rx_ring[i];
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->index = i;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->lldev = lldev;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring->live = B_FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!xgell_rx_ring_open(rx_ring))
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_FALSE);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng lldev->live_rx_rings++;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_TRUE);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_rx_close(xgelldev_t *lldev)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_t *rx_ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int i;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (lldev->live_rx_rings == 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Close all rx rings
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (i = 0; i < lldev->init_rx_rings; i++) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng rx_ring = &lldev->rx_ring[i];
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (rx_ring->live) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_ring_close(rx_ring);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng lldev->live_rx_rings--;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_assert(lldev->live_rx_rings == 0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_tx_term
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Function will be called by HAL to terminate all DTRs for
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Fifo(s) type of channels.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_tx_term(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh,
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_dtr_state_e state, void *userdata, xge_hal_channel_reopen_e reopen)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_txd_priv_t *txd_priv =
a23fd118e437af0a7877dd313db8fdaa3537c675yl ((xgell_txd_priv_t *)xge_hal_fifo_dtr_private(dtrh));
a23fd118e437af0a7877dd313db8fdaa3537c675yl mblk_t *mp = txd_priv->mblk;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int i;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * for Tx we must clean up the DTR *only* if it has been
a23fd118e437af0a7877dd313db8fdaa3537c675yl * posted!
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (state != XGE_HAL_DTR_STATE_POSTED) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl for (i = 0; i < txd_priv->handle_cnt; i++) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_assert(txd_priv->dma_handles[i]);
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) ddi_dma_unbind_handle(txd_priv->dma_handles[i]);
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_dma_free_handle(&txd_priv->dma_handles[i]);
a23fd118e437af0a7877dd313db8fdaa3537c675yl txd_priv->dma_handles[i] = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_fifo_dtr_free(channelh, dtrh);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw if (mp) {
7eced415e5dd557aef2d78483b5a7785f0e13670xw txd_priv->mblk = NULL;
7eced415e5dd557aef2d78483b5a7785f0e13670xw freemsg(mp);
7eced415e5dd557aef2d78483b5a7785f0e13670xw }
7eced415e5dd557aef2d78483b5a7785f0e13670xw}
7eced415e5dd557aef2d78483b5a7785f0e13670xw
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic boolean_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_tx_ring_open(xgell_tx_ring_t *tx_ring)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_channel_attr_t attr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgelldev_t *lldev = tx_ring->lldev;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (tx_ring->live)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_TRUE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng attr.post_qid = tx_ring->index;
a23fd118e437af0a7877dd313db8fdaa3537c675yl attr.compl_qid = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl attr.callback = xgell_xmit_compl;
a23fd118e437af0a7877dd313db8fdaa3537c675yl attr.per_dtr_space = sizeof (xgell_txd_priv_t);
a23fd118e437af0a7877dd313db8fdaa3537c675yl attr.flags = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl attr.type = XGE_HAL_CHANNEL_TYPE_FIFO;
a23fd118e437af0a7877dd313db8fdaa3537c675yl attr.dtr_init = NULL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl attr.dtr_term = xgell_tx_term;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng attr.userdata = tx_ring;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng status = xge_hal_channel_open(lldev->devh, &attr, &tx_ring->channelh,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng XGE_HAL_CHANNEL_OC_NORMAL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (status != XGE_HAL_OK) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_ERR, "%s%d: cannot open Tx channel got status "
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng "code %d", XGELL_IFNAME, lldev->instance, status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (B_FALSE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tx_ring->live = B_TRUE;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (B_TRUE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
7eced415e5dd557aef2d78483b5a7785f0e13670xwstatic void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_tx_ring_close(xgell_tx_ring_t *tx_ring)
7eced415e5dd557aef2d78483b5a7785f0e13670xw{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!tx_ring->live)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_hal_channel_close(tx_ring->channelh, XGE_HAL_CHANNEL_OC_NORMAL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tx_ring->live = B_FALSE;
7eced415e5dd557aef2d78483b5a7785f0e13670xw}
7eced415e5dd557aef2d78483b5a7785f0e13670xw
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * xgell_tx_open
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @lldev: the link layer object
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Initialize and open all TX channels.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic boolean_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_tx_open(xgelldev_t *lldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_tx_ring_t *tx_ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int i;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (lldev->live_tx_rings != 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (B_TRUE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng lldev->live_tx_rings = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Enable rings by reserve sequence to match the h/w sequences.
7eced415e5dd557aef2d78483b5a7785f0e13670xw */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (i = 0; i < lldev->init_tx_rings; i++) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tx_ring = &lldev->tx_ring[i];
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tx_ring->index = i;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tx_ring->lldev = lldev;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tx_ring->live = B_FALSE;
7eced415e5dd557aef2d78483b5a7785f0e13670xw
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!xgell_tx_ring_open(tx_ring))
7eced415e5dd557aef2d78483b5a7785f0e13670xw return (B_FALSE);
7eced415e5dd557aef2d78483b5a7785f0e13670xw
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng lldev->live_tx_rings++;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (B_TRUE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic void
da14cebe459d3275048785f25bd869cb09b5307fEric Chengxgell_tx_close(xgelldev_t *lldev)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_tx_ring_t *tx_ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int i;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (lldev->live_tx_rings == 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Enable rings by reserve sequence to match the h/w sequences.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (i = 0; i < lldev->init_tx_rings; i++) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng tx_ring = &lldev->tx_ring[i];
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (tx_ring->live) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_tx_ring_close(tx_ring);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng lldev->live_tx_rings--;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_initiate_start(xgelldev_t *lldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_t *hldev = lldev->devh;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb int maxpkt = hldev->config.mtu;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* check initial mtu before enabling the device */
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_device_mtu_check(lldev->devh, maxpkt);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: MTU size %d is invalid",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance, maxpkt);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* set initial mtu before enabling the device */
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_device_mtu_set(lldev->devh, maxpkt);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: can not set new MTU %d",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance, maxpkt);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EIO);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* tune jumbo/normal frame UFC counters */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng hldev->config.ring.queue[XGELL_RX_RING_MAIN].rti.ufc_b =
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (maxpkt > XGE_HAL_DEFAULT_MTU) ?
7eced415e5dd557aef2d78483b5a7785f0e13670xw XGE_HAL_DEFAULT_RX_UFC_B_J :
7eced415e5dd557aef2d78483b5a7785f0e13670xw XGE_HAL_DEFAULT_RX_UFC_B_N;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng hldev->config.ring.queue[XGELL_RX_RING_MAIN].rti.ufc_c =
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (maxpkt > XGE_HAL_DEFAULT_MTU) ?
7eced415e5dd557aef2d78483b5a7785f0e13670xw XGE_HAL_DEFAULT_RX_UFC_C_J :
7eced415e5dd557aef2d78483b5a7785f0e13670xw XGE_HAL_DEFAULT_RX_UFC_C_N;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* now, enable the device */
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_device_enable(lldev->devh);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: can not enable the device",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EIO);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (!xgell_rx_open(lldev)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_device_disable(lldev->devh);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl u64 adapter_status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) xge_hal_device_status(lldev->devh,
a23fd118e437af0a7877dd313db8fdaa3537c675yl &adapter_status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: can not safely disable "
a23fd118e437af0a7877dd313db8fdaa3537c675yl "the device. adaper status 0x%"PRIx64
a23fd118e437af0a7877dd313db8fdaa3537c675yl " returned status %d",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance,
a23fd118e437af0a7877dd313db8fdaa3537c675yl (uint64_t)adapter_status, status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_rx_close(lldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_os_mdelay(1500);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (ENOMEM);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (!xgell_tx_open(lldev)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_device_disable(lldev->devh);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl u64 adapter_status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) xge_hal_device_status(lldev->devh,
a23fd118e437af0a7877dd313db8fdaa3537c675yl &adapter_status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: can not safely disable "
a23fd118e437af0a7877dd313db8fdaa3537c675yl "the device. adaper status 0x%"PRIx64
a23fd118e437af0a7877dd313db8fdaa3537c675yl " returned status %d",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance,
a23fd118e437af0a7877dd313db8fdaa3537c675yl (uint64_t)adapter_status, status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xgell_tx_close(lldev);
7eced415e5dd557aef2d78483b5a7785f0e13670xw xgell_rx_close(lldev);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_os_mdelay(1500);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (ENOMEM);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* time to enable interrupts */
7eced415e5dd557aef2d78483b5a7785f0e13670xw (void) xge_enable_intrs(lldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_intr_enable(lldev->devh);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->is_initialized = 1;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_initiate_stop(xgelldev_t *lldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->is_initialized = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_device_disable(lldev->devh);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl u64 adapter_status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) xge_hal_device_status(lldev->devh, &adapter_status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: can not safely disable "
a23fd118e437af0a7877dd313db8fdaa3537c675yl "the device. adaper status 0x%"PRIx64" returned status %d",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance,
a23fd118e437af0a7877dd313db8fdaa3537c675yl (uint64_t)adapter_status, status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_intr_disable(lldev->devh);
7eced415e5dd557aef2d78483b5a7785f0e13670xw /* disable OS ISR's */
7eced415e5dd557aef2d78483b5a7785f0e13670xw xge_disable_intrs(lldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "%s",
a23fd118e437af0a7877dd313db8fdaa3537c675yl "waiting for device irq to become quiescent...");
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_os_mdelay(1500);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_queue_flush(xge_hal_device_queue(lldev->devh));
a23fd118e437af0a7877dd313db8fdaa3537c675yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw xgell_rx_close(lldev);
7eced415e5dd557aef2d78483b5a7785f0e13670xw xgell_tx_close(lldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_m_start
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @arg: pointer to device private strucutre(hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * This function is called by MAC Layer to enable the XFRAME
a23fd118e437af0a7877dd313db8fdaa3537c675yl * firmware to generate interrupts and also prepare the
a23fd118e437af0a7877dd313db8fdaa3537c675yl * driver to call mac_rx for delivering receive packets
a23fd118e437af0a7877dd313db8fdaa3537c675yl * to MAC Layer.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_m_start(void *arg)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xgelldev_t *lldev = arg;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_device_t *hldev = lldev->devh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int ret;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "%s%d: M_START", XGELL_IFNAME,
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_enter(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (lldev->is_initialized) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: device is already initialized",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl hldev->terminating = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (ret = xgell_initiate_start(lldev)) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (ret);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->timeout_id = timeout(xge_device_poll, hldev, XGE_DEV_POLL_TICKS);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_m_stop
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @arg: pointer to device private data (hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * This function is called by the MAC Layer to disable
a23fd118e437af0a7877dd313db8fdaa3537c675yl * the XFRAME firmware for generating any interrupts and
a23fd118e437af0a7877dd313db8fdaa3537c675yl * also stop the driver from calling mac_rx() for
a23fd118e437af0a7877dd313db8fdaa3537c675yl * delivering data packets to the MAC Layer.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_m_stop(void *arg)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xgelldev_t *lldev = arg;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_device_t *hldev = lldev->devh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "%s", "MAC_STOP");
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_enter(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (!lldev->is_initialized) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s", "device is not initialized...");
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_terminating(hldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_initiate_stop(lldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* reset device */
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) xge_hal_device_reset(lldev->devh);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (lldev->timeout_id != 0) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl (void) untimeout(lldev->timeout_id);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "%s", "returning back to MAC Layer...");
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_onerr_reset
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @lldev: pointer to xgelldev_t structure
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * This function is called by HAL Event framework to reset the HW
a23fd118e437af0a7877dd313db8fdaa3537c675yl * This function is must be called with genlock taken.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylint
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_onerr_reset(xgelldev_t *lldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl int rc = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (!lldev->is_initialized) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: can not reset",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (rc);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->in_reset = 1;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_initiate_stop(lldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* reset device */
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) xge_hal_device_reset(lldev->devh);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl rc = xgell_initiate_start(lldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->in_reset = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (rc);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_m_multicst
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @arg: pointer to device private strucutre(hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @add:
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @mc_addr:
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * This function is called by MAC Layer to enable or
a23fd118e437af0a7877dd313db8fdaa3537c675yl * disable device-level reception of specific multicast addresses.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_m_multicst(void *arg, boolean_t add, const uint8_t *mc_addr)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xgelldev_t *lldev = (xgelldev_t *)arg;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_device_t *hldev = lldev->devh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "M_MULTICAST add %d", add);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_enter(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (!lldev->is_initialized) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: can not set multicast",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EIO);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* FIXME: missing HAL functionality: enable_one() */
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = (add) ?
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_mcast_enable(hldev) :
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_mcast_disable(hldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "failed to %s multicast, status %d",
a23fd118e437af0a7877dd313db8fdaa3537c675yl add ? "enable" : "disable", status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EIO);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_m_promisc
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @arg: pointer to device private strucutre(hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @on:
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * This function is called by MAC Layer to enable or
a23fd118e437af0a7877dd313db8fdaa3537c675yl * disable the reception of all the packets on the medium
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_m_promisc(void *arg, boolean_t on)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xgelldev_t *lldev = (xgelldev_t *)arg;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_device_t *hldev = lldev->devh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_enter(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "%s", "MAC_PROMISC_SET");
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (!lldev->is_initialized) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "%s%d: can not set promiscuous",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EIO);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (on) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_promisc_enable(hldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl } else {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_promisc_disable(hldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb * xgell_m_stat
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @arg: pointer to device private strucutre(hldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb * This function is called by MAC Layer to get network statistics
a23fd118e437af0a7877dd313db8fdaa3537c675yl * from the driver.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic int
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebxgell_m_stat(void *arg, uint_t stat, uint64_t *val)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_stats_hw_info_t *hw_info;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xgelldev_t *lldev = (xgelldev_t *)arg;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xge_hal_device_t *hldev = lldev->devh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "%s", "MAC_STATS_GET");
a23fd118e437af0a7877dd313db8fdaa3537c675yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw mutex_enter(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (!lldev->is_initialized) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (EAGAIN);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (xge_hal_stats_hw(hldev, &hw_info) != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (EAGAIN);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl switch (stat) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl case MAC_STAT_IFSPEED:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb *val = 10000000000ull; /* 10G */
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case MAC_STAT_MULTIRCV:
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *val = ((u64) hw_info->rmac_vld_mcst_frms_oflow << 32) |
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hw_info->rmac_vld_mcst_frms;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case MAC_STAT_BRDCSTRCV:
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *val = ((u64) hw_info->rmac_vld_bcst_frms_oflow << 32) |
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hw_info->rmac_vld_bcst_frms;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case MAC_STAT_MULTIXMT:
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *val = ((u64) hw_info->tmac_mcst_frms_oflow << 32) |
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hw_info->tmac_mcst_frms;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case MAC_STAT_BRDCSTXMT:
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *val = ((u64) hw_info->tmac_bcst_frms_oflow << 32) |
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hw_info->tmac_bcst_frms;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case MAC_STAT_RBYTES:
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *val = ((u64) hw_info->rmac_ttl_octets_oflow << 32) |
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hw_info->rmac_ttl_octets;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case MAC_STAT_NORCVBUF:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb *val = hw_info->rmac_drop_frms;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case MAC_STAT_IERRORS:
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *val = ((u64) hw_info->rmac_discarded_frms_oflow << 32) |
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hw_info->rmac_discarded_frms;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case MAC_STAT_OBYTES:
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *val = ((u64) hw_info->tmac_ttl_octets_oflow << 32) |
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hw_info->tmac_ttl_octets;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case MAC_STAT_NOXMTBUF:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb *val = hw_info->tmac_drop_frms;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case MAC_STAT_OERRORS:
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *val = ((u64) hw_info->tmac_any_err_frms_oflow << 32) |
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hw_info->tmac_any_err_frms;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case MAC_STAT_IPACKETS:
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *val = ((u64) hw_info->rmac_vld_frms_oflow << 32) |
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hw_info->rmac_vld_frms;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case MAC_STAT_OPACKETS:
8347601bcb0a439f6e50fc36b4039a73d08700e1yl *val = ((u64) hw_info->tmac_frms_oflow << 32) |
8347601bcb0a439f6e50fc36b4039a73d08700e1yl hw_info->tmac_frms;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb break;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_FCS_ERRORS:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb *val = hw_info->rmac_fcs_err_frms;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_TOOLONG_ERRORS:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb *val = hw_info->rmac_long_frms;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case ETHER_STAT_LINK_DUPLEX:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb *val = LINK_DUPLEX_FULL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl default:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb mutex_exit(&lldev->genlock);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (ENOTSUP);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_exit(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer/*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Retrieve a value for one of the statistics for a particular rx ring
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerint
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerxgell_rx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer xgell_rx_ring_t *rx_ring = (xgell_rx_ring_t *)rh;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer switch (stat) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_STAT_RBYTES:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer *val = rx_ring->rx_bytes;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_STAT_IPACKETS:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer *val = rx_ring->rx_pkts;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer default:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer *val = 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return (ENOTSUP);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return (0);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer/*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Retrieve a value for one of the statistics for a particular tx ring
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerint
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerxgell_tx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer xgell_tx_ring_t *tx_ring = (xgell_tx_ring_t *)rh;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer switch (stat) {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_STAT_OBYTES:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer *val = tx_ring->tx_bytes;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer case MAC_STAT_OPACKETS:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer *val = tx_ring->tx_pkts;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer break;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer default:
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer *val = 0;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return (ENOTSUP);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer }
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer return (0);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_device_alloc - Allocate new LL device
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylint
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_device_alloc(xge_hal_device_h devh,
a23fd118e437af0a7877dd313db8fdaa3537c675yl dev_info_t *dev_info, xgelldev_t **lldev_out)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgelldev_t *lldev;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_t *hldev = (xge_hal_device_t *)devh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int instance = ddi_get_instance(dev_info);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl *lldev_out = NULL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "trying to register etherenet device %s%d...",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev = kmem_zalloc(sizeof (xgelldev_t), KM_SLEEP);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->devh = hldev;
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->instance = instance;
a23fd118e437af0a7877dd313db8fdaa3537c675yl lldev->dev_info = dev_info;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl *lldev_out = lldev;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl ddi_set_driver_private(dev_info, (caddr_t)hldev);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (DDI_SUCCESS);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_device_free
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylvoid
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_device_free(xgelldev_t *lldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "freeing device %s%d",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(lldev, sizeof (xgelldev_t));
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_ioctl
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic void
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xgelldev_t *lldev = arg;
a23fd118e437af0a7877dd313db8fdaa3537c675yl struct iocblk *iocp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int err = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int cmd;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int need_privilege = 1;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int ret = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl iocp = (struct iocblk *)mp->b_rptr;
a23fd118e437af0a7877dd313db8fdaa3537c675yl iocp->ioc_error = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl cmd = iocp->ioc_cmd;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "MAC_IOCTL cmd 0x%x", cmd);
a23fd118e437af0a7877dd313db8fdaa3537c675yl switch (cmd) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl case ND_GET:
a23fd118e437af0a7877dd313db8fdaa3537c675yl need_privilege = 0;
a23fd118e437af0a7877dd313db8fdaa3537c675yl /* FALLTHRU */
a23fd118e437af0a7877dd313db8fdaa3537c675yl case ND_SET:
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl default:
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "unknown cmd 0x%x", cmd);
a23fd118e437af0a7877dd313db8fdaa3537c675yl miocnak(wq, mp, 0, EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (need_privilege) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (err != 0) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR,
a23fd118e437af0a7877dd313db8fdaa3537c675yl "drv_priv(): rejected cmd 0x%x, err %d",
a23fd118e437af0a7877dd313db8fdaa3537c675yl cmd, err);
a23fd118e437af0a7877dd313db8fdaa3537c675yl miocnak(wq, mp, 0, err);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl switch (cmd) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl case ND_GET:
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * If nd_getset() returns B_FALSE, the command was
a23fd118e437af0a7877dd313db8fdaa3537c675yl * not valid (e.g. unknown name), so we just tell the
a23fd118e437af0a7877dd313db8fdaa3537c675yl * top-level ioctl code to send a NAK (with code EINVAL).
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * Otherwise, nd_getset() will have built the reply to
a23fd118e437af0a7877dd313db8fdaa3537c675yl * be sent (but not actually sent it), so we tell the
a23fd118e437af0a7877dd313db8fdaa3537c675yl * caller to send the prepared reply.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675yl ret = nd_getset(wq, lldev->ndp, mp);
7eced415e5dd557aef2d78483b5a7785f0e13670xw xge_debug_ll(XGE_TRACE, "%s", "got ndd get ioctl");
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl case ND_SET:
a23fd118e437af0a7877dd313db8fdaa3537c675yl ret = nd_getset(wq, lldev->ndp, mp);
7eced415e5dd557aef2d78483b5a7785f0e13670xw xge_debug_ll(XGE_TRACE, "%s", "got ndd set ioctl");
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl default:
a23fd118e437af0a7877dd313db8fdaa3537c675yl break;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (ret == B_FALSE) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR,
a23fd118e437af0a7877dd313db8fdaa3537c675yl "nd_getset(): rejected cmd 0x%x, err %d",
a23fd118e437af0a7877dd313db8fdaa3537c675yl cmd, err);
a23fd118e437af0a7877dd313db8fdaa3537c675yl miocnak(wq, mp, 0, EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl } else {
a23fd118e437af0a7877dd313db8fdaa3537c675yl mp->b_datap->db_type = iocp->ioc_error == 0 ?
a23fd118e437af0a7877dd313db8fdaa3537c675yl M_IOCACK : M_IOCNAK;
a23fd118e437af0a7877dd313db8fdaa3537c675yl qreply(wq, mp);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebstatic boolean_t
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebxgell_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl xgelldev_t *lldev = arg;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng xge_debug_ll(XGE_TRACE, "xgell_m_getcapab: %x", cap);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb switch (cap) {
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb case MAC_CAPAB_HCKSUM: {
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb uint32_t *hcksum_txflags = cap_data;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb *hcksum_txflags = HCKSUM_INET_FULL_V4 | HCKSUM_INET_FULL_V6 |
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb HCKSUM_IPHDRCKSUM;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb break;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl case MAC_CAPAB_LSO: {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl mac_capab_lso_t *cap_lso = cap_data;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (lldev->config.lso_enable) {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl cap_lso->lso_basic_tcp_ipv4.lso_max = XGELL_LSO_MAXLEN;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl break;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl } else {
8347601bcb0a439f6e50fc36b4039a73d08700e1yl return (B_FALSE);
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
8347601bcb0a439f6e50fc36b4039a73d08700e1yl }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng case MAC_CAPAB_RINGS: {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mac_capab_rings_t *cap_rings = cap_data;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng switch (cap_rings->mr_type) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng case MAC_RING_TYPE_RX:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cap_rings->mr_rnum = lldev->init_rx_rings;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cap_rings->mr_gnum = lldev->init_rx_groups;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cap_rings->mr_rget = xgell_fill_ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cap_rings->mr_gget = xgell_fill_group;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng break;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng case MAC_RING_TYPE_TX:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cap_rings->mr_rnum = lldev->init_tx_rings;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cap_rings->mr_gnum = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cap_rings->mr_rget = xgell_fill_ring;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cap_rings->mr_gget = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng break;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng default:
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng break;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng break;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb default:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (B_FALSE);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb }
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (B_TRUE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_stats_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgelldev_t *lldev = (xgelldev_t *)cp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int count = 0, retsize;
a23fd118e437af0a7877dd313db8fdaa3537c675yl char *buf;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl buf = kmem_alloc(XGELL_STATS_BUFSIZE, KM_SLEEP);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (buf == NULL) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (ENOSPC);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_aux_stats_tmac_read(lldev->devh, XGELL_STATS_BUFSIZE,
a23fd118e437af0a7877dd313db8fdaa3537c675yl buf, &retsize);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_STATS_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "tmac_read(): status %d", status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl count += retsize;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_aux_stats_rmac_read(lldev->devh,
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_STATS_BUFSIZE - count,
a23fd118e437af0a7877dd313db8fdaa3537c675yl buf+count, &retsize);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_STATS_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "rmac_read(): status %d", status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl count += retsize;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_aux_stats_pci_read(lldev->devh,
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_STATS_BUFSIZE - count, buf + count, &retsize);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_STATS_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "pci_read(): status %d", status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl count += retsize;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_aux_stats_sw_dev_read(lldev->devh,
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_STATS_BUFSIZE - count, buf + count, &retsize);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_STATS_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "sw_dev_read(): status %d", status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl count += retsize;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_aux_stats_hal_read(lldev->devh,
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_STATS_BUFSIZE - count, buf + count, &retsize);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_STATS_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "pci_read(): status %d", status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl count += retsize;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl *(buf + count - 1) = '\0'; /* remove last '\n' */
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) mi_mpprintf(mp, "%s", buf);
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_STATS_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_pciconf_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgelldev_t *lldev = (xgelldev_t *)cp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int retsize;
a23fd118e437af0a7877dd313db8fdaa3537c675yl char *buf;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl buf = kmem_alloc(XGELL_PCICONF_BUFSIZE, KM_SLEEP);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (buf == NULL) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (ENOSPC);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_aux_pci_config_read(lldev->devh, XGELL_PCICONF_BUFSIZE,
a23fd118e437af0a7877dd313db8fdaa3537c675yl buf, &retsize);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_PCICONF_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "pci_config_read(): status %d", status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl *(buf + retsize - 1) = '\0'; /* remove last '\n' */
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) mi_mpprintf(mp, "%s", buf);
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_PCICONF_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_about_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgelldev_t *lldev = (xgelldev_t *)cp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int retsize;
a23fd118e437af0a7877dd313db8fdaa3537c675yl char *buf;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl buf = kmem_alloc(XGELL_ABOUT_BUFSIZE, KM_SLEEP);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (buf == NULL) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (ENOSPC);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_aux_about_read(lldev->devh, XGELL_ABOUT_BUFSIZE,
a23fd118e437af0a7877dd313db8fdaa3537c675yl buf, &retsize);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_ABOUT_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "about_read(): status %d", status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl *(buf + retsize - 1) = '\0'; /* remove last '\n' */
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) mi_mpprintf(mp, "%s", buf);
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_ABOUT_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic unsigned long bar0_offset = 0x110; /* adapter_control */
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_bar0_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgelldev_t *lldev = (xgelldev_t *)cp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int retsize;
a23fd118e437af0a7877dd313db8fdaa3537c675yl char *buf;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl buf = kmem_alloc(XGELL_IOCTL_BUFSIZE, KM_SLEEP);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (buf == NULL) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (ENOSPC);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_aux_bar0_read(lldev->devh, bar0_offset,
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IOCTL_BUFSIZE, buf, &retsize);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_IOCTL_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "bar0_read(): status %d", status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl *(buf + retsize - 1) = '\0'; /* remove last '\n' */
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) mi_mpprintf(mp, "%s", buf);
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_IOCTL_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_bar0_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *credp)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl unsigned long old_offset = bar0_offset;
a23fd118e437af0a7877dd313db8fdaa3537c675yl char *end;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (value && *value == '0' &&
a23fd118e437af0a7877dd313db8fdaa3537c675yl (*(value + 1) == 'x' || *(value + 1) == 'X')) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl value += 2;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl bar0_offset = mi_strtol(value, &end, 16);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (end == value) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl bar0_offset = old_offset;
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "bar0: new value %s:%lX", value, bar0_offset);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_debug_level_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl char *buf;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl buf = kmem_alloc(XGELL_IOCTL_BUFSIZE, KM_SLEEP);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (buf == NULL) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (ENOSPC);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) mi_mpprintf(mp, "debug_level %d", xge_hal_driver_debug_level());
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_IOCTL_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_debug_level_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
a23fd118e437af0a7877dd313db8fdaa3537c675yl cred_t *credp)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl int level;
a23fd118e437af0a7877dd313db8fdaa3537c675yl char *end;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl level = mi_strtol(value, &end, 10);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (level < XGE_NONE || level > XGE_ERR || end == value) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_driver_debug_level_set(level);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_debug_module_mask_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl char *buf;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl buf = kmem_alloc(XGELL_IOCTL_BUFSIZE, KM_SLEEP);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (buf == NULL) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (ENOSPC);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) mi_mpprintf(mp, "debug_module_mask 0x%08x",
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_driver_debug_module_mask());
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_IOCTL_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_debug_module_mask_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
a23fd118e437af0a7877dd313db8fdaa3537c675yl cred_t *credp)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl u32 mask;
a23fd118e437af0a7877dd313db8fdaa3537c675yl char *end;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (value && *value == '0' &&
a23fd118e437af0a7877dd313db8fdaa3537c675yl (*(value + 1) == 'x' || *(value + 1) == 'X')) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl value += 2;
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl mask = mi_strtol(value, &end, 16);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (end == value) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_driver_debug_module_mask_set(mask);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675ylstatic int
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_devconfig_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgelldev_t *lldev = (xgelldev_t *)(void *)cp;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_status_e status;
a23fd118e437af0a7877dd313db8fdaa3537c675yl int retsize;
a23fd118e437af0a7877dd313db8fdaa3537c675yl char *buf;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl buf = kmem_alloc(XGELL_DEVCONF_BUFSIZE, KM_SLEEP);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (buf == NULL) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (ENOSPC);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl status = xge_hal_aux_device_config_read(lldev->devh,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng XGELL_DEVCONF_BUFSIZE, buf, &retsize);
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (status != XGE_HAL_OK) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_DEVCONF_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "device_config_read(): status %d",
a23fd118e437af0a7877dd313db8fdaa3537c675yl status);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (EINVAL);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl *(buf + retsize - 1) = '\0'; /* remove last '\n' */
a23fd118e437af0a7877dd313db8fdaa3537c675yl (void) mi_mpprintf(mp, "%s", buf);
a23fd118e437af0a7877dd313db8fdaa3537c675yl kmem_free(buf, XGELL_DEVCONF_BUFSIZE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (0);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_device_register
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @devh: pointer on HAL device
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @config: pointer on this network device configuration
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @ll_out: output pointer. Will be assigned to valid LL device.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * This function will allocate and register network device
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylint
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_device_register(xgelldev_t *lldev, xgell_config_t *config)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
8347601bcb0a439f6e50fc36b4039a73d08700e1yl mac_register_t *macp = NULL;
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_hal_device_t *hldev = (xge_hal_device_t *)lldev->devh;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Initialize some NDD interface for internal debug.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (nd_load(&lldev->ndp, "pciconf", xgell_pciconf_get, NULL,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb (caddr_t)lldev) == B_FALSE)
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb goto xgell_ndd_fail;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (nd_load(&lldev->ndp, "about", xgell_about_get, NULL,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb (caddr_t)lldev) == B_FALSE)
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb goto xgell_ndd_fail;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (nd_load(&lldev->ndp, "stats", xgell_stats_get, NULL,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb (caddr_t)lldev) == B_FALSE)
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb goto xgell_ndd_fail;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (nd_load(&lldev->ndp, "bar0", xgell_bar0_get, xgell_bar0_set,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb (caddr_t)lldev) == B_FALSE)
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb goto xgell_ndd_fail;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (nd_load(&lldev->ndp, "debug_level", xgell_debug_level_get,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb xgell_debug_level_set, (caddr_t)lldev) == B_FALSE)
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb goto xgell_ndd_fail;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (nd_load(&lldev->ndp, "debug_module_mask",
a23fd118e437af0a7877dd313db8fdaa3537c675yl xgell_debug_module_mask_get, xgell_debug_module_mask_set,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb (caddr_t)lldev) == B_FALSE)
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb goto xgell_ndd_fail;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl if (nd_load(&lldev->ndp, "devconfig", xgell_devconfig_get, NULL,
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb (caddr_t)lldev) == B_FALSE)
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb goto xgell_ndd_fail;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl bcopy(config, &lldev->config, sizeof (xgell_config_t));
a23fd118e437af0a7877dd313db8fdaa3537c675yl
7eced415e5dd557aef2d78483b5a7785f0e13670xw mutex_init(&lldev->genlock, NULL, MUTEX_DRIVER,
7eced415e5dd557aef2d78483b5a7785f0e13670xw DDI_INTR_PRI(hldev->irqh));
a23fd118e437af0a7877dd313db8fdaa3537c675yl
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb if ((macp = mac_alloc(MAC_VERSION)) == NULL)
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb goto xgell_register_fail;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl macp->m_driver = lldev;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_dip = lldev->dev_info;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_src_addr = hldev->macaddr[0];
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_callbacks = &xgell_m_callbacks;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_min_sdu = 0;
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb macp->m_max_sdu = hldev->config.mtu;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz macp->m_margin = VLAN_TAGSZ;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng macp->m_v12n = MAC_VIRT_LEVEL1;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
a23fd118e437af0a7877dd313db8fdaa3537c675yl /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * MAC Registration.
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (mac_register(macp, &lldev->mh) != 0)
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb goto xgell_register_fail;
a23fd118e437af0a7877dd313db8fdaa3537c675yl
3c785c4c5ac4bb72eb0cff3cda1255dfc9613aa1yl /* Always free the macp after register */
3c785c4c5ac4bb72eb0cff3cda1255dfc9613aa1yl if (macp != NULL)
3c785c4c5ac4bb72eb0cff3cda1255dfc9613aa1yl mac_free(macp);
3c785c4c5ac4bb72eb0cff3cda1255dfc9613aa1yl
8347601bcb0a439f6e50fc36b4039a73d08700e1yl /* Calculate tx_copied_max here ??? */
8347601bcb0a439f6e50fc36b4039a73d08700e1yl lldev->tx_copied_max = hldev->config.fifo.max_frags *
7eced415e5dd557aef2d78483b5a7785f0e13670xw hldev->config.fifo.alignment_size *
7eced415e5dd557aef2d78483b5a7785f0e13670xw hldev->config.fifo.max_aligned_frags;
8347601bcb0a439f6e50fc36b4039a73d08700e1yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "etherenet device %s%d registered",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (DDI_SUCCESS);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebxgell_ndd_fail:
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb nd_free(&lldev->ndp);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb xge_debug_ll(XGE_ERR, "%s", "unable to load ndd parameter");
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (DDI_FAILURE);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb
ba2e4443695ee6a6f420a35cd4fc3d3346d22932sebxgell_register_fail:
8347601bcb0a439f6e50fc36b4039a73d08700e1yl if (macp != NULL)
8347601bcb0a439f6e50fc36b4039a73d08700e1yl mac_free(macp);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb nd_free(&lldev->ndp);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb mutex_destroy(&lldev->genlock);
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb xge_debug_ll(XGE_ERR, "%s", "unable to register networking device");
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb return (DDI_FAILURE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl/*
a23fd118e437af0a7877dd313db8fdaa3537c675yl * xgell_device_unregister
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @devh: pointer on HAL device
a23fd118e437af0a7877dd313db8fdaa3537c675yl * @lldev: pointer to valid LL device.
a23fd118e437af0a7877dd313db8fdaa3537c675yl *
a23fd118e437af0a7877dd313db8fdaa3537c675yl * This function will unregister and free network device
a23fd118e437af0a7877dd313db8fdaa3537c675yl */
a23fd118e437af0a7877dd313db8fdaa3537c675ylint
a23fd118e437af0a7877dd313db8fdaa3537c675ylxgell_device_unregister(xgelldev_t *lldev)
a23fd118e437af0a7877dd313db8fdaa3537c675yl{
ba2e4443695ee6a6f420a35cd4fc3d3346d22932seb if (mac_unregister(lldev->mh) != 0) {
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_ERR, "unable to unregister device %s%d",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (DDI_FAILURE);
a23fd118e437af0a7877dd313db8fdaa3537c675yl }
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl mutex_destroy(&lldev->genlock);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl nd_free(&lldev->ndp);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl xge_debug_ll(XGE_TRACE, "etherenet device %s%d unregistered",
a23fd118e437af0a7877dd313db8fdaa3537c675yl XGELL_IFNAME, lldev->instance);
a23fd118e437af0a7877dd313db8fdaa3537c675yl
a23fd118e437af0a7877dd313db8fdaa3537c675yl return (DDI_SUCCESS);
a23fd118e437af0a7877dd313db8fdaa3537c675yl}