xref: /titanic_50/usr/src/uts/common/io/cxgbe/shared/shared.c (revision 56b2bdd1f04d465cfe4a95b88ae5cba5884154e4)
1*56b2bdd1SGireesh Nagabhushana /*
2*56b2bdd1SGireesh Nagabhushana  * This file and its contents are supplied under the terms of the
3*56b2bdd1SGireesh Nagabhushana  * Common Development and Distribution License ("CDDL"), version 1.0.
4*56b2bdd1SGireesh Nagabhushana  * You may only use this file in accordance with the terms of version
5*56b2bdd1SGireesh Nagabhushana  * 1.0 of the CDDL.
6*56b2bdd1SGireesh Nagabhushana  *
7*56b2bdd1SGireesh Nagabhushana  * A full copy of the text of the CDDL should have accompanied this
8*56b2bdd1SGireesh Nagabhushana  * source. A copy of the CDDL is also available via the Internet at
9*56b2bdd1SGireesh Nagabhushana  * http://www.illumos.org/license/CDDL.
10*56b2bdd1SGireesh Nagabhushana  */
11*56b2bdd1SGireesh Nagabhushana 
12*56b2bdd1SGireesh Nagabhushana /*
13*56b2bdd1SGireesh Nagabhushana  * This file is part of the Chelsio T4 support code.
14*56b2bdd1SGireesh Nagabhushana  *
15*56b2bdd1SGireesh Nagabhushana  * Copyright (C) 2011-2013 Chelsio Communications.  All rights reserved.
16*56b2bdd1SGireesh Nagabhushana  *
17*56b2bdd1SGireesh Nagabhushana  * This program is distributed in the hope that it will be useful, but WITHOUT
18*56b2bdd1SGireesh Nagabhushana  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19*56b2bdd1SGireesh Nagabhushana  * FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE file included in this
20*56b2bdd1SGireesh Nagabhushana  * release for licensing terms and conditions.
21*56b2bdd1SGireesh Nagabhushana  */
22*56b2bdd1SGireesh Nagabhushana 
23*56b2bdd1SGireesh Nagabhushana #include <sys/ddi.h>
24*56b2bdd1SGireesh Nagabhushana #include <sys/sunddi.h>
25*56b2bdd1SGireesh Nagabhushana #include <sys/atomic.h>
26*56b2bdd1SGireesh Nagabhushana #include <sys/types.h>
27*56b2bdd1SGireesh Nagabhushana #include <sys/kmem.h>
28*56b2bdd1SGireesh Nagabhushana 
29*56b2bdd1SGireesh Nagabhushana #include "osdep.h"
30*56b2bdd1SGireesh Nagabhushana #include "shared.h"
31*56b2bdd1SGireesh Nagabhushana 
32*56b2bdd1SGireesh Nagabhushana static int rxbuf_ctor(void *, void *, int);
33*56b2bdd1SGireesh Nagabhushana static void rxbuf_dtor(void *, void *);
34*56b2bdd1SGireesh Nagabhushana 
35*56b2bdd1SGireesh Nagabhushana void
cxgb_printf(dev_info_t * dip,int level,char * f,...)36*56b2bdd1SGireesh Nagabhushana cxgb_printf(dev_info_t *dip, int level, char *f, ...)
37*56b2bdd1SGireesh Nagabhushana {
38*56b2bdd1SGireesh Nagabhushana 	va_list list;
39*56b2bdd1SGireesh Nagabhushana 	char fmt[128];
40*56b2bdd1SGireesh Nagabhushana 
41*56b2bdd1SGireesh Nagabhushana 	(void) snprintf(fmt, sizeof (fmt), "%s%d: %s", ddi_driver_name(dip),
42*56b2bdd1SGireesh Nagabhushana 	    ddi_get_instance(dip), f);
43*56b2bdd1SGireesh Nagabhushana 	va_start(list, f);
44*56b2bdd1SGireesh Nagabhushana 	vcmn_err(level, fmt, list);
45*56b2bdd1SGireesh Nagabhushana 	va_end(list);
46*56b2bdd1SGireesh Nagabhushana }
47*56b2bdd1SGireesh Nagabhushana 
48*56b2bdd1SGireesh Nagabhushana kmem_cache_t *
rxbuf_cache_create(struct rxbuf_cache_params * p)49*56b2bdd1SGireesh Nagabhushana rxbuf_cache_create(struct rxbuf_cache_params *p)
50*56b2bdd1SGireesh Nagabhushana {
51*56b2bdd1SGireesh Nagabhushana 	char name[32];
52*56b2bdd1SGireesh Nagabhushana 
53*56b2bdd1SGireesh Nagabhushana 	(void) snprintf(name, sizeof (name), "%s%d_rxbuf_cache",
54*56b2bdd1SGireesh Nagabhushana 	    ddi_driver_name(p->dip), ddi_get_instance(p->dip));
55*56b2bdd1SGireesh Nagabhushana 
56*56b2bdd1SGireesh Nagabhushana 	return kmem_cache_create(name, sizeof (struct rxbuf), CACHE_LINE,
57*56b2bdd1SGireesh Nagabhushana 	    rxbuf_ctor, rxbuf_dtor, NULL, p, NULL, 0);
58*56b2bdd1SGireesh Nagabhushana }
59*56b2bdd1SGireesh Nagabhushana 
60*56b2bdd1SGireesh Nagabhushana void
rxbuf_cache_destroy(kmem_cache_t * cache)61*56b2bdd1SGireesh Nagabhushana rxbuf_cache_destroy(kmem_cache_t *cache)
62*56b2bdd1SGireesh Nagabhushana {
63*56b2bdd1SGireesh Nagabhushana 	kmem_cache_destroy(cache);
64*56b2bdd1SGireesh Nagabhushana }
65*56b2bdd1SGireesh Nagabhushana 
66*56b2bdd1SGireesh Nagabhushana /*
67*56b2bdd1SGireesh Nagabhushana  * If ref_cnt is more than 1 then those many calls to rxbuf_free will
68*56b2bdd1SGireesh Nagabhushana  * have to be made before the rxb is released back to the kmem_cache.
69*56b2bdd1SGireesh Nagabhushana  */
70*56b2bdd1SGireesh Nagabhushana struct rxbuf *
rxbuf_alloc(kmem_cache_t * cache,int kmflags,uint_t ref_cnt)71*56b2bdd1SGireesh Nagabhushana rxbuf_alloc(kmem_cache_t *cache, int kmflags, uint_t ref_cnt)
72*56b2bdd1SGireesh Nagabhushana {
73*56b2bdd1SGireesh Nagabhushana 	struct rxbuf *rxb;
74*56b2bdd1SGireesh Nagabhushana 
75*56b2bdd1SGireesh Nagabhushana 	ASSERT(ref_cnt > 0);
76*56b2bdd1SGireesh Nagabhushana 
77*56b2bdd1SGireesh Nagabhushana 	rxb = kmem_cache_alloc(cache, kmflags);
78*56b2bdd1SGireesh Nagabhushana 	if (rxb != NULL) {
79*56b2bdd1SGireesh Nagabhushana 		rxb->ref_cnt = ref_cnt;
80*56b2bdd1SGireesh Nagabhushana 		rxb->cache = cache;
81*56b2bdd1SGireesh Nagabhushana 	}
82*56b2bdd1SGireesh Nagabhushana 
83*56b2bdd1SGireesh Nagabhushana 	return (rxb);
84*56b2bdd1SGireesh Nagabhushana }
85*56b2bdd1SGireesh Nagabhushana 
86*56b2bdd1SGireesh Nagabhushana /*
87*56b2bdd1SGireesh Nagabhushana  * This is normally called via the rxb's freefunc, when an mblk referencing the
88*56b2bdd1SGireesh Nagabhushana  * rxb is freed.
89*56b2bdd1SGireesh Nagabhushana  */
90*56b2bdd1SGireesh Nagabhushana void
rxbuf_free(struct rxbuf * rxb)91*56b2bdd1SGireesh Nagabhushana rxbuf_free(struct rxbuf *rxb)
92*56b2bdd1SGireesh Nagabhushana {
93*56b2bdd1SGireesh Nagabhushana 	if (atomic_dec_uint_nv(&rxb->ref_cnt) == 0)
94*56b2bdd1SGireesh Nagabhushana 		kmem_cache_free(rxb->cache, rxb);
95*56b2bdd1SGireesh Nagabhushana }
96*56b2bdd1SGireesh Nagabhushana 
97*56b2bdd1SGireesh Nagabhushana static int
rxbuf_ctor(void * arg1,void * arg2,int kmflag)98*56b2bdd1SGireesh Nagabhushana rxbuf_ctor(void *arg1, void *arg2, int kmflag)
99*56b2bdd1SGireesh Nagabhushana {
100*56b2bdd1SGireesh Nagabhushana 	struct rxbuf *rxb = arg1;
101*56b2bdd1SGireesh Nagabhushana 	struct rxbuf_cache_params *p = arg2;
102*56b2bdd1SGireesh Nagabhushana 	size_t real_len;
103*56b2bdd1SGireesh Nagabhushana 	ddi_dma_cookie_t cookie;
104*56b2bdd1SGireesh Nagabhushana 	uint_t ccount = 0;
105*56b2bdd1SGireesh Nagabhushana 	int (*callback)(caddr_t);
106*56b2bdd1SGireesh Nagabhushana 	int rc = ENOMEM;
107*56b2bdd1SGireesh Nagabhushana 
108*56b2bdd1SGireesh Nagabhushana 	if (kmflag & KM_SLEEP)
109*56b2bdd1SGireesh Nagabhushana 		callback = DDI_DMA_SLEEP;
110*56b2bdd1SGireesh Nagabhushana 	else
111*56b2bdd1SGireesh Nagabhushana 		callback = DDI_DMA_DONTWAIT;
112*56b2bdd1SGireesh Nagabhushana 
113*56b2bdd1SGireesh Nagabhushana 	rc = ddi_dma_alloc_handle(p->dip, &p->dma_attr_rx, callback, 0,
114*56b2bdd1SGireesh Nagabhushana 	    &rxb->dhdl);
115*56b2bdd1SGireesh Nagabhushana 	if (rc != DDI_SUCCESS)
116*56b2bdd1SGireesh Nagabhushana 		return (rc == DDI_DMA_BADATTR ? EINVAL : ENOMEM);
117*56b2bdd1SGireesh Nagabhushana 
118*56b2bdd1SGireesh Nagabhushana 	rc = ddi_dma_mem_alloc(rxb->dhdl, p->buf_size, &p->acc_attr_rx,
119*56b2bdd1SGireesh Nagabhushana 	    DDI_DMA_STREAMING, callback, 0, &rxb->va, &real_len, &rxb->ahdl);
120*56b2bdd1SGireesh Nagabhushana 	if (rc != DDI_SUCCESS) {
121*56b2bdd1SGireesh Nagabhushana 		rc = ENOMEM;
122*56b2bdd1SGireesh Nagabhushana 		goto fail1;
123*56b2bdd1SGireesh Nagabhushana 	}
124*56b2bdd1SGireesh Nagabhushana 
125*56b2bdd1SGireesh Nagabhushana 	rc = ddi_dma_addr_bind_handle(rxb->dhdl, NULL, rxb->va, p->buf_size,
126*56b2bdd1SGireesh Nagabhushana 	    DDI_DMA_READ | DDI_DMA_STREAMING, NULL, NULL, &cookie, &ccount);
127*56b2bdd1SGireesh Nagabhushana 	if (rc != DDI_DMA_MAPPED) {
128*56b2bdd1SGireesh Nagabhushana 		if (rc == DDI_DMA_INUSE)
129*56b2bdd1SGireesh Nagabhushana 			rc = EBUSY;
130*56b2bdd1SGireesh Nagabhushana 		else if (rc == DDI_DMA_TOOBIG)
131*56b2bdd1SGireesh Nagabhushana 			rc = E2BIG;
132*56b2bdd1SGireesh Nagabhushana 		else
133*56b2bdd1SGireesh Nagabhushana 			rc = ENOMEM;
134*56b2bdd1SGireesh Nagabhushana 		goto fail2;
135*56b2bdd1SGireesh Nagabhushana 	}
136*56b2bdd1SGireesh Nagabhushana 
137*56b2bdd1SGireesh Nagabhushana 	if (ccount != 1) {
138*56b2bdd1SGireesh Nagabhushana 		rc = E2BIG;
139*56b2bdd1SGireesh Nagabhushana 		goto fail3;
140*56b2bdd1SGireesh Nagabhushana 	}
141*56b2bdd1SGireesh Nagabhushana 
142*56b2bdd1SGireesh Nagabhushana 	rxb->ref_cnt = 0;
143*56b2bdd1SGireesh Nagabhushana 	rxb->buf_size = p->buf_size;
144*56b2bdd1SGireesh Nagabhushana 	rxb->freefunc.free_arg = (caddr_t)rxb;
145*56b2bdd1SGireesh Nagabhushana 	rxb->freefunc.free_func = rxbuf_free;
146*56b2bdd1SGireesh Nagabhushana 	rxb->ba = cookie.dmac_laddress;
147*56b2bdd1SGireesh Nagabhushana 
148*56b2bdd1SGireesh Nagabhushana 	return (0);
149*56b2bdd1SGireesh Nagabhushana 
150*56b2bdd1SGireesh Nagabhushana fail3:	(void) ddi_dma_unbind_handle(rxb->dhdl);
151*56b2bdd1SGireesh Nagabhushana fail2:	ddi_dma_mem_free(&rxb->ahdl);
152*56b2bdd1SGireesh Nagabhushana fail1:	ddi_dma_free_handle(&rxb->dhdl);
153*56b2bdd1SGireesh Nagabhushana 	return (rc);
154*56b2bdd1SGireesh Nagabhushana }
155*56b2bdd1SGireesh Nagabhushana 
156*56b2bdd1SGireesh Nagabhushana /* ARGSUSED */
157*56b2bdd1SGireesh Nagabhushana static void
rxbuf_dtor(void * arg1,void * arg2)158*56b2bdd1SGireesh Nagabhushana rxbuf_dtor(void *arg1, void *arg2)
159*56b2bdd1SGireesh Nagabhushana {
160*56b2bdd1SGireesh Nagabhushana 	struct rxbuf *rxb = arg1;
161*56b2bdd1SGireesh Nagabhushana 
162*56b2bdd1SGireesh Nagabhushana 	(void) ddi_dma_unbind_handle(rxb->dhdl);
163*56b2bdd1SGireesh Nagabhushana 	ddi_dma_mem_free(&rxb->ahdl);
164*56b2bdd1SGireesh Nagabhushana 	ddi_dma_free_handle(&rxb->dhdl);
165*56b2bdd1SGireesh Nagabhushana }
166