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