mirror of
https://github.com/ipxe/ipxe
synced 2026-01-29 12:29:13 +03:00
[dma] Use virtual addresses for dma_map()
Cache management operations must generally be performed on virtual addresses rather than physical addresses. Change the address parameter in dma_map() to be a virtual address, and make dma() the API-level primitive instead of dma_phys(). Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -47,7 +47,7 @@ PROVIDE_DMAAPI_INLINE ( flat, dma_free );
|
|||||||
PROVIDE_DMAAPI_INLINE ( flat, dma_umalloc );
|
PROVIDE_DMAAPI_INLINE ( flat, dma_umalloc );
|
||||||
PROVIDE_DMAAPI_INLINE ( flat, dma_ufree );
|
PROVIDE_DMAAPI_INLINE ( flat, dma_ufree );
|
||||||
PROVIDE_DMAAPI_INLINE ( flat, dma_set_mask );
|
PROVIDE_DMAAPI_INLINE ( flat, dma_set_mask );
|
||||||
PROVIDE_DMAAPI_INLINE ( flat, dma_phys );
|
PROVIDE_DMAAPI_INLINE ( flat, dma );
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
*
|
*
|
||||||
@@ -67,7 +67,7 @@ PROVIDE_DMAAPI_INLINE ( flat, dma_phys );
|
|||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int dma_op_map ( struct dma_device *dma, struct dma_mapping *map,
|
static int dma_op_map ( struct dma_device *dma, struct dma_mapping *map,
|
||||||
physaddr_t addr, size_t len, int flags ) {
|
void *addr, size_t len, int flags ) {
|
||||||
struct dma_operations *op = dma->op;
|
struct dma_operations *op = dma->op;
|
||||||
|
|
||||||
if ( ! op )
|
if ( ! op )
|
||||||
@@ -175,4 +175,4 @@ PROVIDE_DMAAPI ( op, dma_free, dma_op_free );
|
|||||||
PROVIDE_DMAAPI ( op, dma_umalloc, dma_op_umalloc );
|
PROVIDE_DMAAPI ( op, dma_umalloc, dma_op_umalloc );
|
||||||
PROVIDE_DMAAPI ( op, dma_ufree, dma_op_ufree );
|
PROVIDE_DMAAPI ( op, dma_ufree, dma_op_ufree );
|
||||||
PROVIDE_DMAAPI ( op, dma_set_mask, dma_op_set_mask );
|
PROVIDE_DMAAPI ( op, dma_set_mask, dma_op_set_mask );
|
||||||
PROVIDE_DMAAPI_INLINE ( op, dma_phys );
|
PROVIDE_DMAAPI_INLINE ( op, dma );
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ int intelxl_msix_enable ( struct intelxl_nic *intelxl,
|
|||||||
|
|
||||||
/* Map dummy target location */
|
/* Map dummy target location */
|
||||||
if ( ( rc = dma_map ( intelxl->dma, &intelxl->msix.map,
|
if ( ( rc = dma_map ( intelxl->dma, &intelxl->msix.map,
|
||||||
virt_to_phys ( &intelxl->msix.msg ),
|
&intelxl->msix.msg, sizeof ( intelxl->msix.msg ),
|
||||||
sizeof ( intelxl->msix.msg ), DMA_RX ) ) != 0 ) {
|
DMA_RX ) ) != 0 ) {
|
||||||
DBGC ( intelxl, "INTELXL %p could not map MSI-X target: %s\n",
|
DBGC ( intelxl, "INTELXL %p could not map MSI-X target: %s\n",
|
||||||
intelxl, strerror ( rc ) );
|
intelxl, strerror ( rc ) );
|
||||||
goto err_map;
|
goto err_map;
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ struct dma_operations {
|
|||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
int ( * map ) ( struct dma_device *dma, struct dma_mapping *map,
|
int ( * map ) ( struct dma_device *dma, struct dma_mapping *map,
|
||||||
physaddr_t addr, size_t len, int flags );
|
void *addr, size_t len, int flags );
|
||||||
/**
|
/**
|
||||||
* Unmap buffer
|
* Unmap buffer
|
||||||
*
|
*
|
||||||
@@ -178,8 +178,7 @@ struct dma_operations {
|
|||||||
*/
|
*/
|
||||||
static inline __always_inline int
|
static inline __always_inline int
|
||||||
DMAAPI_INLINE ( flat, dma_map ) ( struct dma_device *dma,
|
DMAAPI_INLINE ( flat, dma_map ) ( struct dma_device *dma,
|
||||||
struct dma_mapping *map,
|
struct dma_mapping *map, void *addr __unused,
|
||||||
physaddr_t addr __unused,
|
|
||||||
size_t len __unused, int flags __unused ) {
|
size_t len __unused, int flags __unused ) {
|
||||||
|
|
||||||
/* Increment mapping count (for debugging) */
|
/* Increment mapping count (for debugging) */
|
||||||
@@ -319,32 +318,31 @@ DMAAPI_INLINE ( flat, dma_set_mask ) ( struct dma_device *dma __unused,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get DMA address from physical address
|
* Get DMA address from virtual address
|
||||||
*
|
*
|
||||||
* @v map DMA mapping
|
* @v map DMA mapping
|
||||||
* @v addr Physical address within the mapped region
|
* @v addr Address within the mapped region
|
||||||
* @ret addr Device-side DMA address
|
* @ret addr Device-side DMA address
|
||||||
*/
|
*/
|
||||||
static inline __always_inline physaddr_t
|
static inline __always_inline physaddr_t
|
||||||
DMAAPI_INLINE ( flat, dma_phys ) ( struct dma_mapping *map __unused,
|
DMAAPI_INLINE ( flat, dma ) ( struct dma_mapping *map __unused, void *addr ) {
|
||||||
physaddr_t addr ) {
|
|
||||||
|
|
||||||
/* Use physical address as device address */
|
/* Use physical address as device address */
|
||||||
return addr;
|
return virt_to_phys ( addr );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get DMA address from physical address
|
* Get DMA address from virtual address
|
||||||
*
|
*
|
||||||
* @v map DMA mapping
|
* @v map DMA mapping
|
||||||
* @v addr Physical address within the mapped region
|
* @v addr Address within the mapped region
|
||||||
* @ret addr Device-side DMA address
|
* @ret addr Device-side DMA address
|
||||||
*/
|
*/
|
||||||
static inline __always_inline physaddr_t
|
static inline __always_inline physaddr_t
|
||||||
DMAAPI_INLINE ( op, dma_phys ) ( struct dma_mapping *map, physaddr_t addr ) {
|
DMAAPI_INLINE ( op, dma ) ( struct dma_mapping *map, void *addr ) {
|
||||||
|
|
||||||
/* Adjust physical address using mapping offset */
|
/* Adjust physical address using mapping offset */
|
||||||
return ( addr + map->offset );
|
return ( virt_to_phys ( addr ) + map->offset );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -358,7 +356,7 @@ DMAAPI_INLINE ( op, dma_phys ) ( struct dma_mapping *map, physaddr_t addr ) {
|
|||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
int dma_map ( struct dma_device *dma, struct dma_mapping *map,
|
int dma_map ( struct dma_device *dma, struct dma_mapping *map,
|
||||||
physaddr_t addr, size_t len, int flags );
|
void *addr, size_t len, int flags );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unmap buffer
|
* Unmap buffer
|
||||||
@@ -417,28 +415,14 @@ void dma_ufree ( struct dma_mapping *map, void *addr, size_t len );
|
|||||||
*/
|
*/
|
||||||
void dma_set_mask ( struct dma_device *dma, physaddr_t mask );
|
void dma_set_mask ( struct dma_device *dma, physaddr_t mask );
|
||||||
|
|
||||||
/**
|
|
||||||
* Get DMA address from physical address
|
|
||||||
*
|
|
||||||
* @v map DMA mapping
|
|
||||||
* @v addr Physical address within the mapped region
|
|
||||||
* @ret addr Device-side DMA address
|
|
||||||
*/
|
|
||||||
physaddr_t dma_phys ( struct dma_mapping *map, physaddr_t addr );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get DMA address from virtual address
|
* Get DMA address from virtual address
|
||||||
*
|
*
|
||||||
* @v map DMA mapping
|
* @v map DMA mapping
|
||||||
* @v addr Virtual address within the mapped region
|
* @v addr Address within the mapped region
|
||||||
* @ret addr Device-side DMA address
|
* @ret addr Device-side DMA address
|
||||||
*/
|
*/
|
||||||
static inline __always_inline physaddr_t dma ( struct dma_mapping *map,
|
physaddr_t dma ( struct dma_mapping *map, void *addr );
|
||||||
void *addr ) {
|
|
||||||
|
|
||||||
/* Get DMA address from corresponding physical address */
|
|
||||||
return dma_phys ( map, virt_to_phys ( addr ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if DMA unmapping is required
|
* Check if DMA unmapping is required
|
||||||
|
|||||||
@@ -230,8 +230,7 @@ static inline void iob_populate ( struct io_buffer *iobuf,
|
|||||||
static inline __always_inline int iob_map ( struct io_buffer *iobuf,
|
static inline __always_inline int iob_map ( struct io_buffer *iobuf,
|
||||||
struct dma_device *dma,
|
struct dma_device *dma,
|
||||||
size_t len, int flags ) {
|
size_t len, int flags ) {
|
||||||
return dma_map ( dma, &iobuf->map, virt_to_phys ( iobuf->data ),
|
return dma_map ( dma, &iobuf->map, iobuf->data, len, flags );
|
||||||
len, flags );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -455,7 +455,7 @@ PROVIDE_PCIAPI ( efi, pci_ioremap, efipci_ioremap );
|
|||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map,
|
static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map,
|
||||||
physaddr_t addr, size_t len, int flags ) {
|
void *addr, size_t len, int flags ) {
|
||||||
struct efi_pci_device *efipci =
|
struct efi_pci_device *efipci =
|
||||||
container_of ( dma, struct efi_pci_device, pci.dma );
|
container_of ( dma, struct efi_pci_device, pci.dma );
|
||||||
struct pci_device *pci = &efipci->pci;
|
struct pci_device *pci = &efipci->pci;
|
||||||
@@ -464,6 +464,7 @@ static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map,
|
|||||||
EFI_PHYSICAL_ADDRESS bus;
|
EFI_PHYSICAL_ADDRESS bus;
|
||||||
UINTN count;
|
UINTN count;
|
||||||
VOID *mapping;
|
VOID *mapping;
|
||||||
|
physaddr_t phys;
|
||||||
EFI_STATUS efirc;
|
EFI_STATUS efirc;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@@ -486,18 +487,19 @@ static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Map buffer (if non-zero length) */
|
/* Map buffer (if non-zero length) */
|
||||||
|
phys = virt_to_phys ( addr );
|
||||||
count = len;
|
count = len;
|
||||||
if ( len ) {
|
if ( len ) {
|
||||||
if ( ( efirc = pci_io->Map ( pci_io, op, phys_to_virt ( addr ),
|
if ( ( efirc = pci_io->Map ( pci_io, op, addr, &count, &bus,
|
||||||
&count, &bus, &mapping ) ) != 0 ) {
|
&mapping ) ) != 0 ) {
|
||||||
rc = -EEFI ( efirc );
|
rc = -EEFI ( efirc );
|
||||||
DBGC ( pci, "EFIPCI " PCI_FMT " cannot map %08lx+%zx: "
|
DBGC ( pci, "EFIPCI " PCI_FMT " cannot map %p+%zx: "
|
||||||
"%s\n", PCI_ARGS ( pci ), addr, len,
|
"%s\n", PCI_ARGS ( pci ), addr, len,
|
||||||
strerror ( rc ) );
|
strerror ( rc ) );
|
||||||
goto err_map;
|
goto err_map;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bus = addr;
|
bus = phys;
|
||||||
mapping = NULL;
|
mapping = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,14 +510,14 @@ static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map,
|
|||||||
*/
|
*/
|
||||||
if ( count != len ) {
|
if ( count != len ) {
|
||||||
DBGC ( pci, "EFIPCI " PCI_FMT " attempted split mapping for "
|
DBGC ( pci, "EFIPCI " PCI_FMT " attempted split mapping for "
|
||||||
"%08lx+%zx\n", PCI_ARGS ( pci ), addr, len );
|
"%p+%zx\n", PCI_ARGS ( pci ), addr, len );
|
||||||
rc = -ENOTSUP;
|
rc = -ENOTSUP;
|
||||||
goto err_len;
|
goto err_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Populate mapping */
|
/* Populate mapping */
|
||||||
map->dma = dma;
|
map->dma = dma;
|
||||||
map->offset = ( bus - addr );
|
map->offset = ( bus - phys );
|
||||||
map->token = mapping;
|
map->token = mapping;
|
||||||
|
|
||||||
/* Increment mapping count (for debugging) */
|
/* Increment mapping count (for debugging) */
|
||||||
@@ -594,8 +596,7 @@ static void * efipci_dma_alloc ( struct dma_device *dma,
|
|||||||
memset ( addr, 0, ( pages * EFI_PAGE_SIZE ) );
|
memset ( addr, 0, ( pages * EFI_PAGE_SIZE ) );
|
||||||
|
|
||||||
/* Map buffer */
|
/* Map buffer */
|
||||||
if ( ( rc = efipci_dma_map ( dma, map, virt_to_phys ( addr ),
|
if ( ( rc = efipci_dma_map ( dma, map, addr, ( pages * EFI_PAGE_SIZE ),
|
||||||
( pages * EFI_PAGE_SIZE ),
|
|
||||||
DMA_BI ) ) != 0 )
|
DMA_BI ) ) != 0 )
|
||||||
goto err_map;
|
goto err_map;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user