Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 * Intel MIC Platform Software Stack (MPSS)
  3 *
  4 * Copyright(c) 2014 Intel Corporation.
  5 *
  6 * This program is free software; you can redistribute it and/or modify
  7 * it under the terms of the GNU General Public License, version 2, as
  8 * published by the Free Software Foundation.
  9 *
 10 * This program is distributed in the hope that it will be useful, but
 11 * WITHOUT ANY WARRANTY; without even the implied warranty of
 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 13 * General Public License for more details.
 14 *
 15 * Intel SCIF driver.
 16 *
 17 */
 18#ifndef SCIF_MAP_H
 19#define SCIF_MAP_H
 20
 21#include "../bus/scif_bus.h"
 22
 23static __always_inline void *
 24scif_alloc_coherent(dma_addr_t *dma_handle,
 25		    struct scif_dev *scifdev, size_t size,
 26		    gfp_t gfp)
 27{
 28	void *va;
 29
 30	if (scifdev_self(scifdev)) {
 31		va = kmalloc(size, gfp);
 32		if (va)
 33			*dma_handle = virt_to_phys(va);
 34	} else {
 35		va = dma_alloc_coherent(&scifdev->sdev->dev,
 36					size, dma_handle, gfp);
 37		if (va && scifdev_is_p2p(scifdev))
 38			*dma_handle = *dma_handle + scifdev->base_addr;
 39	}
 40	return va;
 41}
 42
 43static __always_inline void
 44scif_free_coherent(void *va, dma_addr_t local,
 45		   struct scif_dev *scifdev, size_t size)
 46{
 47	if (scifdev_self(scifdev)) {
 48		kfree(va);
 49	} else {
 50		if (scifdev_is_p2p(scifdev) && local > scifdev->base_addr)
 51			local = local - scifdev->base_addr;
 52		dma_free_coherent(&scifdev->sdev->dev,
 53				  size, va, local);
 54	}
 55}
 56
 57static __always_inline int
 58scif_map_single(dma_addr_t *dma_handle,
 59		void *local, struct scif_dev *scifdev, size_t size)
 60{
 61	int err = 0;
 62
 63	if (scifdev_self(scifdev)) {
 64		*dma_handle = virt_to_phys((local));
 65	} else {
 66		*dma_handle = dma_map_single(&scifdev->sdev->dev,
 67					     local, size, DMA_BIDIRECTIONAL);
 68		if (dma_mapping_error(&scifdev->sdev->dev, *dma_handle))
 69			err = -ENOMEM;
 70		else if (scifdev_is_p2p(scifdev))
 71			*dma_handle = *dma_handle + scifdev->base_addr;
 72	}
 73	if (err)
 74		*dma_handle = 0;
 75	return err;
 76}
 77
 78static __always_inline void
 79scif_unmap_single(dma_addr_t local, struct scif_dev *scifdev,
 80		  size_t size)
 81{
 82	if (!scifdev_self(scifdev)) {
 83		if (scifdev_is_p2p(scifdev))
 84			local = local - scifdev->base_addr;
 85		dma_unmap_single(&scifdev->sdev->dev, local,
 86				 size, DMA_BIDIRECTIONAL);
 87	}
 88}
 89
 90static __always_inline void *
 91scif_ioremap(dma_addr_t phys, size_t size, struct scif_dev *scifdev)
 92{
 93	void *out_virt;
 94	struct scif_hw_dev *sdev = scifdev->sdev;
 95
 96	if (scifdev_self(scifdev))
 97		out_virt = phys_to_virt(phys);
 98	else
 99		out_virt = (void __force *)
100			   sdev->hw_ops->ioremap(sdev, phys, size);
101	return out_virt;
102}
103
104static __always_inline void
105scif_iounmap(void *virt, size_t len, struct scif_dev *scifdev)
106{
107	if (!scifdev_self(scifdev)) {
108		struct scif_hw_dev *sdev = scifdev->sdev;
109
110		sdev->hw_ops->iounmap(sdev, (void __force __iomem *)virt);
111	}
112}
113
114static __always_inline int
115scif_map_page(dma_addr_t *dma_handle, struct page *page,
116	      struct scif_dev *scifdev)
117{
118	int err = 0;
119
120	if (scifdev_self(scifdev)) {
121		*dma_handle = page_to_phys(page);
122	} else {
123		struct scif_hw_dev *sdev = scifdev->sdev;
124		*dma_handle = dma_map_page(&sdev->dev,
125					   page, 0x0, PAGE_SIZE,
126					   DMA_BIDIRECTIONAL);
127		if (dma_mapping_error(&sdev->dev, *dma_handle))
128			err = -ENOMEM;
129		else if (scifdev_is_p2p(scifdev))
130			*dma_handle = *dma_handle + scifdev->base_addr;
131	}
132	if (err)
133		*dma_handle = 0;
134	return err;
135}
136#endif  /* SCIF_MAP_H */