2013-11-16 12:56:06 -05:00
/*
* Copyright ( C ) 2013 Red Hat
* Author : Rob Clark < robdclark @ gmail . com >
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
* this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "msm_drv.h"
# include "msm_mmu.h"
struct msm_iommu {
struct msm_mmu base ;
struct iommu_domain * domain ;
} ;
# define to_msm_iommu(x) container_of(x, struct msm_iommu, base)
2016-12-07 11:13:53 -05:00
static int msm_fault_handler ( struct iommu_domain * domain , struct device * dev ,
2013-11-16 12:56:06 -05:00
unsigned long iova , int flags , void * arg )
{
2016-12-07 11:13:53 -05:00
struct msm_iommu * iommu = arg ;
if ( iommu - > base . handler )
return iommu - > base . handler ( iommu - > base . arg , iova , flags ) ;
2014-08-09 09:07:25 -04:00
pr_warn_ratelimited ( " *** fault: iova=%08lx, flags=%d \n " , iova , flags ) ;
return 0 ;
2013-11-16 12:56:06 -05:00
}
2016-02-25 11:19:43 +05:30
static int msm_iommu_attach ( struct msm_mmu * mmu , const char * const * names ,
int cnt )
2013-11-16 12:56:06 -05:00
{
struct msm_iommu * iommu = to_msm_iommu ( mmu ) ;
2017-02-15 16:00:25 -05:00
int ret ;
pm_runtime_get_sync ( mmu - > dev ) ;
ret = iommu_attach_device ( iommu - > domain , mmu - > dev ) ;
pm_runtime_put_sync ( mmu - > dev ) ;
return ret ;
2013-11-16 12:56:06 -05:00
}
2016-02-25 11:19:43 +05:30
static void msm_iommu_detach ( struct msm_mmu * mmu , const char * const * names ,
int cnt )
2014-06-17 10:32:37 -04:00
{
struct msm_iommu * iommu = to_msm_iommu ( mmu ) ;
2017-02-15 16:00:25 -05:00
pm_runtime_get_sync ( mmu - > dev ) ;
2014-07-09 22:08:15 -04:00
iommu_detach_device ( iommu - > domain , mmu - > dev ) ;
2017-02-15 16:00:25 -05:00
pm_runtime_put_sync ( mmu - > dev ) ;
2014-06-17 10:32:37 -04:00
}
2016-11-11 12:06:46 -05:00
static int msm_iommu_map ( struct msm_mmu * mmu , uint64_t iova ,
2013-11-16 12:56:06 -05:00
struct sg_table * sgt , unsigned len , int prot )
{
struct msm_iommu * iommu = to_msm_iommu ( mmu ) ;
2017-02-15 15:44:04 -05:00
size_t ret ;
2013-11-16 12:56:06 -05:00
2017-02-15 16:00:25 -05:00
// pm_runtime_get_sync(mmu->dev);
2017-02-15 15:44:04 -05:00
ret = iommu_map_sg ( iommu - > domain , iova , sgt - > sgl , sgt - > nents , prot ) ;
2017-02-15 16:00:25 -05:00
// pm_runtime_put_sync(mmu->dev);
2017-02-15 15:44:04 -05:00
WARN_ON ( ret < 0 ) ;
2013-11-16 12:56:06 -05:00
2017-02-15 15:44:04 -05:00
return ( ret = = len ) ? 0 : - EINVAL ;
2013-11-16 12:56:06 -05:00
}
2016-11-11 12:06:46 -05:00
static int msm_iommu_unmap ( struct msm_mmu * mmu , uint64_t iova ,
2013-11-16 12:56:06 -05:00
struct sg_table * sgt , unsigned len )
{
struct msm_iommu * iommu = to_msm_iommu ( mmu ) ;
2017-02-15 16:00:25 -05:00
pm_runtime_get_sync ( mmu - > dev ) ;
2017-02-15 15:44:04 -05:00
iommu_unmap ( iommu - > domain , iova , len ) ;
2017-02-15 16:00:25 -05:00
pm_runtime_put_sync ( mmu - > dev ) ;
2013-11-16 12:56:06 -05:00
return 0 ;
}
static void msm_iommu_destroy ( struct msm_mmu * mmu )
{
struct msm_iommu * iommu = to_msm_iommu ( mmu ) ;
iommu_domain_free ( iommu - > domain ) ;
kfree ( iommu ) ;
}
static const struct msm_mmu_funcs funcs = {
. attach = msm_iommu_attach ,
2014-06-17 10:32:37 -04:00
. detach = msm_iommu_detach ,
2013-11-16 12:56:06 -05:00
. map = msm_iommu_map ,
. unmap = msm_iommu_unmap ,
. destroy = msm_iommu_destroy ,
} ;
2014-07-09 22:08:15 -04:00
struct msm_mmu * msm_iommu_new ( struct device * dev , struct iommu_domain * domain )
2013-11-16 12:56:06 -05:00
{
struct msm_iommu * iommu ;
iommu = kzalloc ( sizeof ( * iommu ) , GFP_KERNEL ) ;
if ( ! iommu )
return ERR_PTR ( - ENOMEM ) ;
iommu - > domain = domain ;
msm_mmu_init ( & iommu - > base , dev , & funcs ) ;
2016-12-07 11:13:53 -05:00
iommu_set_fault_handler ( domain , msm_fault_handler , iommu ) ;
2013-11-16 12:56:06 -05:00
return & iommu - > base ;
}