diff options
Diffstat (limited to 'drivers/net/ethernet/microchip/fdma/fdma_api.c')
| -rw-r--r-- | drivers/net/ethernet/microchip/fdma/fdma_api.c | 65 |
1 files changed, 60 insertions, 5 deletions
diff --git a/drivers/net/ethernet/microchip/fdma/fdma_api.c b/drivers/net/ethernet/microchip/fdma/fdma_api.c index e78c3590da9e..f7a42348e932 100644 --- a/drivers/net/ethernet/microchip/fdma/fdma_api.c +++ b/drivers/net/ethernet/microchip/fdma/fdma_api.c @@ -12,10 +12,18 @@ static int __fdma_db_add(struct fdma *fdma, int dcb_idx, int db_idx, u64 status, int db_idx, u64 *dataptr)) { struct fdma_db *db = fdma_db_get(fdma, dcb_idx, db_idx); + u64 dataptr; + int err; - db->status = status; + db->status = cpu_to_le64(status); - return cb(fdma, dcb_idx, db_idx, &db->dataptr); + err = cb(fdma, dcb_idx, db_idx, &dataptr); + if (unlikely(err)) + return err; + + db->dataptr = cpu_to_le64(dataptr); + + return 0; } /* Add a DB to a DCB, using the callback set in the fdma_ops struct. */ @@ -35,6 +43,7 @@ int __fdma_dcb_add(struct fdma *fdma, int dcb_idx, u64 info, u64 status, u64 *dataptr)) { struct fdma_dcb *dcb = fdma_dcb_get(fdma, dcb_idx); + u64 nextptr; int i, err; for (i = 0; i < fdma->n_dbs; i++) { @@ -43,14 +52,16 @@ int __fdma_dcb_add(struct fdma *fdma, int dcb_idx, u64 info, u64 status, return err; } - err = dcb_cb(fdma, dcb_idx, &fdma->last_dcb->nextptr); + err = dcb_cb(fdma, dcb_idx, &nextptr); if (unlikely(err)) return err; + fdma->last_dcb->nextptr = cpu_to_le64(nextptr); + fdma->last_dcb = dcb; - dcb->nextptr = FDMA_DCB_INVALID_DATA; - dcb->info = info; + dcb->nextptr = cpu_to_le64(FDMA_DCB_INVALID_DATA); + dcb->info = cpu_to_le64(info); return 0; } @@ -127,6 +138,50 @@ void fdma_free_phys(struct fdma *fdma) } EXPORT_SYMBOL_GPL(fdma_free_phys); +#if IS_ENABLED(CONFIG_MCHP_LAN966X_PCI) +/* Allocate coherent DMA memory and map it in the ATU. */ +int fdma_alloc_coherent_and_map(struct device *dev, struct fdma *fdma, + struct fdma_pci_atu *atu) +{ + struct fdma_pci_atu_region *region; + int err; + + if (WARN_ON(fdma->atu_region)) + return -EBUSY; + + /* The ATU cannot express a limit finer than the region granularity, so + * the hardware widens the programmed limit to that boundary. Pad the + * allocation to match, or the outbound window would extend past the + * memory we own. + */ + fdma->size = ALIGN(fdma->size, FDMA_PCI_ATU_REGION_ALIGN); + + err = fdma_alloc_coherent(dev, fdma); + if (err) + return err; + + region = fdma_pci_atu_region_map(atu, fdma->dma, fdma->size); + if (IS_ERR(region)) { + fdma_free_coherent(dev, fdma); + return PTR_ERR(region); + } + + fdma->atu_region = region; + + return 0; +} +EXPORT_SYMBOL_GPL(fdma_alloc_coherent_and_map); + +/* Free coherent DMA memory and unmap the memory in the ATU. */ +void fdma_free_coherent_and_unmap(struct device *dev, struct fdma *fdma) +{ + fdma_pci_atu_region_unmap(fdma->atu_region); + fdma->atu_region = NULL; + fdma_free_coherent(dev, fdma); +} +EXPORT_SYMBOL_GPL(fdma_free_coherent_and_unmap); +#endif + /* Get the size of the FDMA memory */ u32 fdma_get_size(struct fdma *fdma) { |
