Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/smartpqi/smartpqi_mem.c
/*- | /*- | ||||
* Copyright (c) 2018 Microsemi Corporation. | * Copyright (c) 2016-2019 Microsemi Corporation. | ||||
* Copyright (c) 2021 Microchip Technology Inc. and it's subsidiaries. | |||||
* | |||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
* notice, this list of conditions and the following disclaimer. | * notice, this list of conditions and the following disclaimer. | ||||
* 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright | ||||
Show All 12 Lines | |||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
/* $FreeBSD$ */ | /* $FreeBSD$ */ | ||||
#include "smartpqi_includes.h" | #include "smartpqi_includes.h" | ||||
MALLOC_DEFINE(M_SMARTPQI, "smartpqi", "Buffers for the smartpqi(4) driver"); | MALLOC_DEFINE(M_SMARTPQI, "smartpqi", "Buffers for the smartpqi driver"); | ||||
/* | /* | ||||
* DMA map load callback function | * DMA map load callback function | ||||
*/ | */ | ||||
static void | static void | ||||
os_dma_map(void *arg, bus_dma_segment_t *segs, int nseg, int error) | os_dma_map(void *arg, bus_dma_segment_t *segs, int nseg, int error) | ||||
{ | { | ||||
bus_addr_t *paddr = (bus_addr_t *)arg; | bus_addr_t *paddr = (bus_addr_t *)arg; | ||||
*paddr = segs[0].ds_addr; | *paddr = segs[0].ds_addr; | ||||
} | } | ||||
int | |||||
os_dma_setup(pqisrc_softstate_t *softs) | |||||
{ | |||||
DBG_FUNC("IN\n"); | |||||
DBG_FUNC("OUT\n"); | |||||
return PQI_STATUS_SUCCESS; | |||||
} | |||||
int | |||||
os_dma_destroy(pqisrc_softstate_t *softs) | |||||
{ | |||||
DBG_FUNC("IN\n"); | |||||
DBG_FUNC("OUT\n"); | |||||
return PQI_STATUS_SUCCESS; | |||||
} | |||||
void | |||||
os_update_dma_attributes(pqisrc_softstate_t *softs) | |||||
{ | |||||
DBG_FUNC("IN\n"); | |||||
DBG_FUNC("OUT\n"); | |||||
} | |||||
/* | /* | ||||
* DMA mem resource allocation wrapper function | * DMA mem resource allocation wrapper function | ||||
*/ | */ | ||||
int os_dma_mem_alloc(pqisrc_softstate_t *softs, struct dma_mem *dma_mem) | int | ||||
os_dma_mem_alloc(pqisrc_softstate_t *softs, struct dma_mem *dma_mem) | |||||
{ | { | ||||
int ret = 0; | int ret = BSD_SUCCESS; | ||||
/* DBG_FUNC("IN\n"); */ | /* DBG_FUNC("IN\n"); */ | ||||
/* Make sure the alignment is at least 4 bytes */ | |||||
ASSERT(dma_mem->align >= 4); | |||||
/* DMA memory needed - allocate it */ | /* DMA memory needed - allocate it */ | ||||
if ((ret = bus_dma_tag_create( | if ((ret = bus_dma_tag_create( | ||||
softs->os_specific.pqi_parent_dmat, /* parent */ | softs->os_specific.pqi_parent_dmat, /* parent */ | ||||
dma_mem->align, 0, /* algnmnt, boundary */ | dma_mem->align, 0, /* algnmnt, boundary */ | ||||
BUS_SPACE_MAXADDR, /* lowaddr */ | BUS_SPACE_MAXADDR, /* lowaddr */ | ||||
BUS_SPACE_MAXADDR, /* highaddr */ | BUS_SPACE_MAXADDR, /* highaddr */ | ||||
NULL, NULL, /* filter, filterarg */ | NULL, NULL, /* filter, filterarg */ | ||||
dma_mem->size, /* maxsize */ | dma_mem->size, /* maxsize */ | ||||
1, /* nsegments */ | 1, /* nsegments */ | ||||
dma_mem->size, /* maxsegsize */ | dma_mem->size, /* maxsegsize */ | ||||
0, /* flags */ | 0, /* flags */ | ||||
NULL, NULL, /* No locking needed */ | NULL, NULL, /* No locking needed */ | ||||
&dma_mem->dma_tag)) != 0 ) { | &dma_mem->dma_tag)) != 0 ) { | ||||
DBG_ERR("can't allocate DMA tag with error = 0x%x\n", ret); | DBG_ERR("can't allocate DMA tag with error = 0x%x\n", ret); | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
if (!dma_mem->dma_tag) { | |||||
DBG_ERR("dma tag is NULL\n"); | |||||
ret = ENOMEM; | |||||
goto err_out; | |||||
} | |||||
if ((ret = bus_dmamem_alloc(dma_mem->dma_tag, (void **)&dma_mem->virt_addr, | if ((ret = bus_dmamem_alloc(dma_mem->dma_tag, (void **)&dma_mem->virt_addr, | ||||
BUS_DMA_NOWAIT, &dma_mem->dma_map)) != 0) { | BUS_DMA_WAITOK, &dma_mem->dma_map)) != 0) { | ||||
DBG_ERR("can't allocate DMA memory for required object \ | DBG_ERR("can't allocate DMA memory for required object \ | ||||
with error = 0x%x\n", ret); | with error = 0x%x\n", ret); | ||||
goto err_mem; | goto err_mem; | ||||
} | } | ||||
if((ret = bus_dmamap_load(dma_mem->dma_tag, dma_mem->dma_map, | if((ret = bus_dmamap_load(dma_mem->dma_tag, dma_mem->dma_map, | ||||
dma_mem->virt_addr, dma_mem->size, | dma_mem->virt_addr, dma_mem->size, | ||||
os_dma_map, &dma_mem->dma_addr, 0)) != 0) { | os_dma_map, &dma_mem->dma_addr, 0)) != 0) { | ||||
DBG_ERR("can't load DMA memory for required \ | DBG_ERR("can't load DMA memory for required \ | ||||
object with error = 0x%x\n", ret); | object with error = 0x%x\n", ret); | ||||
goto err_load; | goto err_load; | ||||
} | } | ||||
memset(dma_mem->virt_addr, 0, dma_mem->size); | memset(dma_mem->virt_addr, 0, dma_mem->size); | ||||
ret = bsd_status_to_pqi_status(ret); | |||||
/* DBG_FUNC("OUT\n"); */ | /* DBG_FUNC("OUT\n"); */ | ||||
return ret; | return ret; | ||||
err_load: | err_load: | ||||
if(dma_mem->virt_addr) | if(dma_mem->virt_addr) | ||||
bus_dmamem_free(dma_mem->dma_tag, dma_mem->virt_addr, | bus_dmamem_free(dma_mem->dma_tag, dma_mem->virt_addr, | ||||
dma_mem->dma_map); | dma_mem->dma_map); | ||||
err_mem: | err_mem: | ||||
if(dma_mem->dma_tag) | if(dma_mem->dma_tag) | ||||
bus_dma_tag_destroy(dma_mem->dma_tag); | bus_dma_tag_destroy(dma_mem->dma_tag); | ||||
err_out: | err_out: | ||||
DBG_FUNC("failed OUT\n"); | DBG_FUNC("failed OUT\n"); | ||||
ret = bsd_status_to_pqi_status(ret); | |||||
return ret; | return ret; | ||||
} | } | ||||
/* | /* | ||||
* DMA mem resource deallocation wrapper function | * DMA mem resource deallocation wrapper function | ||||
*/ | */ | ||||
void os_dma_mem_free(pqisrc_softstate_t *softs, struct dma_mem *dma_mem) | void | ||||
os_dma_mem_free(pqisrc_softstate_t *softs, struct dma_mem *dma_mem) | |||||
{ | { | ||||
/* DBG_FUNC("IN\n"); */ | /* DBG_FUNC("IN\n"); */ | ||||
if(dma_mem->dma_addr) { | if(dma_mem->dma_addr) { | ||||
bus_dmamap_unload(dma_mem->dma_tag, dma_mem->dma_map); | bus_dmamap_unload(dma_mem->dma_tag, dma_mem->dma_map); | ||||
dma_mem->dma_addr = 0; | dma_mem->dma_addr = 0; | ||||
} | } | ||||
Show All 10 Lines | os_dma_mem_free(pqisrc_softstate_t *softs, struct dma_mem *dma_mem) | ||||
/* DBG_FUNC("OUT\n"); */ | /* DBG_FUNC("OUT\n"); */ | ||||
} | } | ||||
/* | /* | ||||
* Mem resource allocation wrapper function | * Mem resource allocation wrapper function | ||||
*/ | */ | ||||
void *os_mem_alloc(pqisrc_softstate_t *softs, size_t size) | void | ||||
*os_mem_alloc(pqisrc_softstate_t *softs, size_t size) | |||||
{ | { | ||||
void *addr = NULL; | void *addr = NULL; | ||||
/* DBG_FUNC("IN\n"); */ | /* DBG_FUNC("IN\n"); */ | ||||
addr = malloc((unsigned long)size, M_SMARTPQI, | addr = malloc((unsigned long)size, M_SMARTPQI, | ||||
M_NOWAIT | M_ZERO); | M_NOWAIT | M_ZERO); | ||||
/* DBG_FUNC("OUT\n"); */ | /* DBG_FUNC("OUT\n"); */ | ||||
return addr; | return addr; | ||||
} | } | ||||
/* | /* | ||||
* Mem resource deallocation wrapper function | * Mem resource deallocation wrapper function | ||||
*/ | */ | ||||
void os_mem_free(pqisrc_softstate_t *softs, | void | ||||
char *addr, size_t size) | os_mem_free(pqisrc_softstate_t *softs, char *addr, size_t size) | ||||
{ | { | ||||
/* DBG_FUNC("IN\n"); */ | /* DBG_FUNC("IN\n"); */ | ||||
free((void*)addr, M_SMARTPQI); | free((void*)addr, M_SMARTPQI); | ||||
/* DBG_FUNC("OUT\n"); */ | /* DBG_FUNC("OUT\n"); */ | ||||
} | } | ||||
/* | /* | ||||
* dma/bus resource deallocation wrapper function | * dma/bus resource deallocation wrapper function | ||||
*/ | */ | ||||
void os_resource_free(pqisrc_softstate_t *softs) | void | ||||
os_resource_free(pqisrc_softstate_t *softs) | |||||
{ | { | ||||
if(softs->os_specific.pqi_parent_dmat) | if(softs->os_specific.pqi_parent_dmat) | ||||
bus_dma_tag_destroy(softs->os_specific.pqi_parent_dmat); | bus_dma_tag_destroy(softs->os_specific.pqi_parent_dmat); | ||||
if (softs->os_specific.pqi_regs_res0 != NULL) | if (softs->os_specific.pqi_regs_res0 != NULL) | ||||
bus_release_resource(softs->os_specific.pqi_dev, | bus_release_resource(softs->os_specific.pqi_dev, | ||||
SYS_RES_MEMORY, | SYS_RES_MEMORY, | ||||
softs->os_specific.pqi_regs_rid0, | softs->os_specific.pqi_regs_rid0, | ||||
softs->os_specific.pqi_regs_res0); | softs->os_specific.pqi_regs_res0); | ||||
} | } |