oce_util.c revision 330897
11556Srgrimes/*-
21556Srgrimes * SPDX-License-Identifier: BSD-3-Clause
31556Srgrimes *
41556Srgrimes * Copyright (C) 2013 Emulex
51556Srgrimes * All rights reserved.
61556Srgrimes *
71556Srgrimes * Redistribution and use in source and binary forms, with or without
81556Srgrimes * modification, are permitted provided that the following conditions are met:
91556Srgrimes *
101556Srgrimes * 1. Redistributions of source code must retain the above copyright notice,
111556Srgrimes *    this list of conditions and the following disclaimer.
121556Srgrimes *
131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141556Srgrimes *    notice, this list of conditions and the following disclaimer in the
151556Srgrimes *    documentation and/or other materials provided with the distribution.
161556Srgrimes *
171556Srgrimes * 3. Neither the name of the Emulex Corporation nor the names of its
181556Srgrimes *    contributors may be used to endorse or promote products derived from
191556Srgrimes *    this software without specific prior written permission.
201556Srgrimes *
211556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
221556Srgrimes * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
251556Srgrimes * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
261556Srgrimes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
271556Srgrimes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
281556Srgrimes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
291556Srgrimes * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
301556Srgrimes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
311556Srgrimes * POSSIBILITY OF SUCH DAMAGE.
321556Srgrimes *
331556Srgrimes * Contact Information:
3436150Scharnier * freebsd-drivers@emulex.com
3536150Scharnier *
3636150Scharnier * Emulex
371556Srgrimes * 3333 Susan Street
3899110Sobrien * Costa Mesa, CA 92626
3999110Sobrien */
401556Srgrimes
4117987Speter/* $FreeBSD: stable/11/sys/dev/oce/oce_util.c 330897 2018-03-14 03:19:51Z eadler $ */
4217987Speter
43114763Sobrien#include "oce_if.h"
4417987Speter
451556Srgrimesstatic void oce_dma_map_ring(void *arg,
461556Srgrimes			     bus_dma_segment_t *segs,
471556Srgrimes			     int nseg,
481556Srgrimes			     int error);
4917525Sache
5017525Sache/**
511556Srgrimes * @brief		Allocate DMA memory
521556Srgrimes * @param sc		software handle to the device
531556Srgrimes * @param size		bus size
541556Srgrimes * @param dma		dma memory area
551556Srgrimes * @param flags		creation flags
561556Srgrimes * @returns		0 on success, error otherwize
571556Srgrimes */
581556Srgrimesint
591556Srgrimesoce_dma_alloc(POCE_SOFTC sc, bus_size_t size, POCE_DMA_MEM dma, int flags)
601556Srgrimes{
611556Srgrimes	int rc;
621556Srgrimes
631556Srgrimes
6420425Ssteve	memset(dma, 0, sizeof(OCE_DMA_MEM));
6517987Speter
6617987Speter	rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev),
6717987Speter				8, 0,
681556Srgrimes				BUS_SPACE_MAXADDR,
691556Srgrimes				BUS_SPACE_MAXADDR,
701556Srgrimes				NULL, NULL,
711556Srgrimes				size, 1, size, 0, NULL, NULL, &dma->tag);
721556Srgrimes
731556Srgrimes	if (rc == 0) {
741556Srgrimes		rc = bus_dmamem_alloc(dma->tag,
751556Srgrimes				      &dma->ptr,
76201056Sjilles				      BUS_DMA_NOWAIT | BUS_DMA_COHERENT |
7790111Simp					BUS_DMA_ZERO,
781556Srgrimes				      &dma->map);
791556Srgrimes	}
801556Srgrimes
8117987Speter	dma->paddr = 0;
821556Srgrimes	if (rc == 0) {
83208755Sjilles		rc = bus_dmamap_load(dma->tag,
8417987Speter				     dma->map,
851556Srgrimes				     dma->ptr,
861556Srgrimes				     size,
871556Srgrimes				     oce_dma_map_addr,
881556Srgrimes				     &dma->paddr, flags | BUS_DMA_NOWAIT);
8997689Stjr		if (dma->paddr == 0)
901556Srgrimes			rc = ENXIO;
911556Srgrimes	}
92159632Sstefanf
931556Srgrimes	if (rc != 0)
94213760Sobrien		oce_dma_free(sc, dma);
951556Srgrimes
96213760Sobrien	return rc;
9717987Speter}
98201056Sjilles
9920425Ssteve/**
10017987Speter * @brief		Free DMA memory
101201056Sjilles * @param sc		software handle to the device
10220425Ssteve * @param dma		dma area to free
103201056Sjilles */
10420425Sstevevoid
105201056Sjillesoce_dma_free(POCE_SOFTC sc, POCE_DMA_MEM dma)
10620425Ssteve{
107201056Sjilles	if (dma->tag == NULL)
10820425Ssteve		return;
109201056Sjilles
11097689Stjr	if (dma->paddr != 0) {
1118855Srgrimes		bus_dmamap_sync(dma->tag, dma->map,
1121556Srgrimes				BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1131556Srgrimes		bus_dmamap_unload(dma->tag, dma->map);
114201056Sjilles		dma->paddr = 0;
11520425Ssteve	}
116201056Sjilles
117159632Sstefanf	if (dma->ptr != NULL) {
118208755Sjilles		bus_dmamem_free(dma->tag, dma->ptr, dma->map);
119208755Sjilles		dma->ptr = NULL;
120208755Sjilles	}
121208755Sjilles
122201056Sjilles	bus_dma_tag_destroy(dma->tag);
12320425Ssteve	dma->tag = NULL;
12420425Ssteve
12520425Ssteve	return;
1261556Srgrimes}
1271556Srgrimes
128213760Sobrien
1291556Srgrimes
130213760Sobrien/**
131207678Sjilles * @brief		Map DMA memory segment addresses
132207678Sjilles * @param arg		physical address pointer
133207678Sjilles * @param segs		dma memory segments
134213760Sobrien * @param nseg		number of dma memory segments
135207678Sjilles * @param error		if error, zeroes the physical address
136207678Sjilles */
137207678Sjillesvoid
138213811Sobrienoce_dma_map_addr(void *arg, bus_dma_segment_t * segs, int nseg, int error)
139213811Sobrien{
140213811Sobrien	bus_addr_t *paddr = arg;
1411556Srgrimes
1421556Srgrimes	if (error)
143155302Sschweikh		*paddr = 0;
1441556Srgrimes	else
1451556Srgrimes		*paddr = segs->ds_addr;
1461556Srgrimes}
1471556Srgrimes
148201053Sjilles
1491556Srgrimes
1501556Srgrimes/**
1511556Srgrimes * @brief		Destroy a ring buffer
1521556Srgrimes * @param sc		software handle to the device
1531556Srgrimes * @param ring		ring buffer
1541556Srgrimes */
1551556Srgrimes
1561556Srgrimesvoid
1571556Srgrimesoce_destroy_ring_buffer(POCE_SOFTC sc, oce_ring_buffer_t *ring)
1581556Srgrimes{
1591556Srgrimes	oce_dma_free(sc, &ring->dma);
1601556Srgrimes	free(ring, M_DEVBUF);
1611556Srgrimes}
1621556Srgrimes
1631556Srgrimes
1641556Srgrimes
1651556Srgrimesoce_ring_buffer_t *
1661556Srgrimesoce_create_ring_buffer(POCE_SOFTC sc,
1671556Srgrimes		uint32_t q_len, uint32_t item_size)
16890111Simp{
16990111Simp	uint32_t size = q_len * item_size;
17097689Stjr	int rc;
1711556Srgrimes	oce_ring_buffer_t *ring;
1721556Srgrimes
1731556Srgrimes
1741556Srgrimes	ring = malloc(sizeof(oce_ring_buffer_t), M_DEVBUF, M_NOWAIT | M_ZERO);
1751556Srgrimes	if (ring == NULL)
1761556Srgrimes		return NULL;
1771556Srgrimes
1781556Srgrimes	ring->item_size = item_size;
1791556Srgrimes	ring->num_items = q_len;
180201056Sjilles
181201056Sjilles	rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev),
18220425Ssteve				4096, 0,
1831556Srgrimes				BUS_SPACE_MAXADDR,
1841556Srgrimes				BUS_SPACE_MAXADDR,
1851556Srgrimes				NULL, NULL,
1861556Srgrimes				size, 8, 4096, 0, NULL, NULL, &ring->dma.tag);
1871556Srgrimes	if (rc)
1881556Srgrimes		goto fail;
1891556Srgrimes
1901556Srgrimes
1911556Srgrimes	rc = bus_dmamem_alloc(ring->dma.tag,
192201056Sjilles				&ring->dma.ptr,
1931556Srgrimes				BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
1941556Srgrimes				&ring->dma.map);
19597689Stjr	if (rc)
19697689Stjr		goto fail;
19797689Stjr
19897689Stjr	bzero(ring->dma.ptr, size);
1991556Srgrimes	bus_dmamap_sync(ring->dma.tag, ring->dma.map,
2001556Srgrimes			BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2011556Srgrimes	ring->dma.paddr = 0;
20220425Ssteve
20320425Ssteve	return ring;
20420425Ssteve
20520425Sstevefail:
206200956Sjilles	oce_dma_free(sc, &ring->dma);
20720425Ssteve	free(ring, M_DEVBUF);
20820425Ssteve	ring = NULL;
209194765Sjilles	return NULL;
21020425Ssteve}
211199660Sjilles
21220425Ssteve
213199660Sjilles
21420425Sstevestruct _oce_dmamap_paddr_table {
21520425Ssteve	uint32_t max_entries;
21620425Ssteve	uint32_t num_entries;
21720425Ssteve	struct phys_addr *paddrs;
21820425Ssteve};
21920425Ssteve
22020425Ssteve
221199660Sjilles
22220425Ssteve/**
22320425Ssteve * @brief		Map ring buffer
22420425Ssteve * @param arg		dma map phyical address table pointer
22520425Ssteve * @param segs		dma memory segments
226155302Sschweikh * @param nseg		number of dma memory segments
2271556Srgrimes * @param error		maps only if error is 0
2281556Srgrimes */
2291556Srgrimesstatic void
2301556Srgrimesoce_dma_map_ring(void *arg, bus_dma_segment_t * segs, int nseg, int error)
231200956Sjilles{
23217987Speter	int i;
233200956Sjilles	struct _oce_dmamap_paddr_table *dpt =
2341556Srgrimes	    (struct _oce_dmamap_paddr_table *)arg;
2351556Srgrimes
2361556Srgrimes	if (error == 0) {
2371556Srgrimes		if (nseg <= dpt->max_entries) {
2381556Srgrimes			for (i = 0; i < nseg; i++) {
2391556Srgrimes				dpt->paddrs[i].lo = ADDR_LO(segs[i].ds_addr);
2401556Srgrimes				dpt->paddrs[i].hi = ADDR_HI(segs[i].ds_addr);
24117525Sache			}
2421556Srgrimes			dpt->num_entries = nseg;
24317525Sache		}
2441556Srgrimes	}
2451556Srgrimes}
2461556Srgrimes
2471556Srgrimes
2481556Srgrimes
2491556Srgrimes/**
2501556Srgrimes * @brief		Load bus dma map for a ring buffer
2511556Srgrimes * @param ring		ring buffer pointer
2521556Srgrimes * @param pa_list	physical address list
2531556Srgrimes * @returns		number entries
2541556Srgrimes */
2551556Srgrimesuint32_t
2561556Srgrimesoce_page_list(oce_ring_buffer_t *ring, struct phys_addr *pa_list)
2571556Srgrimes{
2581556Srgrimes	struct _oce_dmamap_paddr_table dpt;
2591556Srgrimes
2601556Srgrimes	dpt.max_entries = 8;
261200956Sjilles	dpt.num_entries = 0;
262200956Sjilles	dpt.paddrs = pa_list;
263200956Sjilles
2641556Srgrimes	bus_dmamap_load(ring->dma.tag,
265200956Sjilles			ring->dma.map,
266200956Sjilles			ring->dma.ptr,
267200956Sjilles			ring->item_size * ring->num_items,
2681556Srgrimes			oce_dma_map_ring, &dpt, BUS_DMA_NOWAIT);
2691556Srgrimes
2701556Srgrimes	return dpt.num_entries;
271213811Sobrien}
272200956Sjilles