56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana/*
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * This file and its contents are supplied under the terms of the
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * Common Development and Distribution License ("CDDL"), version 1.0.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * You may only use this file in accordance with the terms of version
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * 1.0 of the CDDL.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana *
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * A full copy of the text of the CDDL should have accompanied this
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * source. A copy of the CDDL is also available via the Internet at
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * http://www.illumos.org/license/CDDL.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana/*
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * This file is part of the Chelsio T4 support code.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana *
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * Copyright (C) 2011-2013 Chelsio Communications. All rights reserved.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana *
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * This program is distributed in the hope that it will be useful, but WITHOUT
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * release for licensing terms and conditions.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana#include <sys/ddi.h>
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana#include <sys/sunddi.h>
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana#include <sys/atomic.h>
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana#include <sys/types.h>
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana#include <sys/kmem.h>
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana#include "osdep.h"
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana#include "shared.h"
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int rxbuf_ctor(void *, void *, int);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic void rxbuf_dtor(void *, void *);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanavoid
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanacxgb_printf(dev_info_t *dip, int level, char *f, ...)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana{
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana va_list list;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana char fmt[128];
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana (void) snprintf(fmt, sizeof (fmt), "%s%d: %s", ddi_driver_name(dip),
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana ddi_get_instance(dip), f);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana va_start(list, f);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana vcmn_err(level, fmt, list);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana va_end(list);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana}
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanakmem_cache_t *
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanarxbuf_cache_create(struct rxbuf_cache_params *p)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana{
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana char name[32];
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana (void) snprintf(name, sizeof (name), "%s%d_rxbuf_cache",
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana ddi_driver_name(p->dip), ddi_get_instance(p->dip));
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana return kmem_cache_create(name, sizeof (struct rxbuf), CACHE_LINE,
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rxbuf_ctor, rxbuf_dtor, NULL, p, NULL, 0);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana}
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanavoid
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanarxbuf_cache_destroy(kmem_cache_t *cache)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana{
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana kmem_cache_destroy(cache);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana}
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana/*
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * If ref_cnt is more than 1 then those many calls to rxbuf_free will
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * have to be made before the rxb is released back to the kmem_cache.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastruct rxbuf *
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanarxbuf_alloc(kmem_cache_t *cache, int kmflags, uint_t ref_cnt)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana{
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana struct rxbuf *rxb;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana ASSERT(ref_cnt > 0);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rxb = kmem_cache_alloc(cache, kmflags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (rxb != NULL) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rxb->ref_cnt = ref_cnt;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rxb->cache = cache;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana }
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana return (rxb);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana}
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana/*
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * This is normally called via the rxb's freefunc, when an mblk referencing the
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * rxb is freed.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanavoid
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanarxbuf_free(struct rxbuf *rxb)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana{
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (atomic_dec_uint_nv(&rxb->ref_cnt) == 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana kmem_cache_free(rxb->cache, rxb);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana}
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanarxbuf_ctor(void *arg1, void *arg2, int kmflag)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana{
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana struct rxbuf *rxb = arg1;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana struct rxbuf_cache_params *p = arg2;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana size_t real_len;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana ddi_dma_cookie_t cookie;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana uint_t ccount = 0;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana int (*callback)(caddr_t);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana int rc = ENOMEM;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (kmflag & KM_SLEEP)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana callback = DDI_DMA_SLEEP;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana else
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana callback = DDI_DMA_DONTWAIT;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = ddi_dma_alloc_handle(p->dip, &p->dma_attr_rx, callback, 0,
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana &rxb->dhdl);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (rc != DDI_SUCCESS)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana return (rc == DDI_DMA_BADATTR ? EINVAL : ENOMEM);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = ddi_dma_mem_alloc(rxb->dhdl, p->buf_size, &p->acc_attr_rx,
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana DDI_DMA_STREAMING, callback, 0, &rxb->va, &real_len, &rxb->ahdl);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (rc != DDI_SUCCESS) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = ENOMEM;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana goto fail1;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana }
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = ddi_dma_addr_bind_handle(rxb->dhdl, NULL, rxb->va, p->buf_size,
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana DDI_DMA_READ | DDI_DMA_STREAMING, NULL, NULL, &cookie, &ccount);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (rc != DDI_DMA_MAPPED) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (rc == DDI_DMA_INUSE)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = EBUSY;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana else if (rc == DDI_DMA_TOOBIG)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = E2BIG;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana else
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = ENOMEM;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana goto fail2;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana }
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ccount != 1) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = E2BIG;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana goto fail3;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana }
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rxb->ref_cnt = 0;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rxb->buf_size = p->buf_size;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rxb->freefunc.free_arg = (caddr_t)rxb;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rxb->freefunc.free_func = rxbuf_free;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rxb->ba = cookie.dmac_laddress;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana return (0);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanafail3: (void) ddi_dma_unbind_handle(rxb->dhdl);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanafail2: ddi_dma_mem_free(&rxb->ahdl);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanafail1: ddi_dma_free_handle(&rxb->dhdl);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana return (rc);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana}
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana/* ARGSUSED */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic void
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanarxbuf_dtor(void *arg1, void *arg2)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana{
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana struct rxbuf *rxb = arg1;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana (void) ddi_dma_unbind_handle(rxb->dhdl);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana ddi_dma_mem_free(&rxb->ahdl);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana ddi_dma_free_handle(&rxb->dhdl);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana}