Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
894901b5
Commit
894901b5
authored
Aug 22, 2017
by
Joerg Roedel
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'iommu/fixes' into arm/mediatek
parents
46cc815d
2926a2aa
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
79 additions
and
28 deletions
+79
-28
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu.c
+1
-0
drivers/iommu/amd_iommu_init.c
drivers/iommu/amd_iommu_init.c
+1
-1
drivers/iommu/amd_iommu_types.h
drivers/iommu/amd_iommu_types.h
+3
-1
drivers/iommu/arm-smmu.c
drivers/iommu/arm-smmu.c
+19
-4
drivers/iommu/intel-iommu.c
drivers/iommu/intel-iommu.c
+3
-1
drivers/iommu/io-pgtable-arm-v7s.c
drivers/iommu/io-pgtable-arm-v7s.c
+6
-0
drivers/iommu/io-pgtable-arm.c
drivers/iommu/io-pgtable-arm.c
+7
-0
drivers/iommu/io-pgtable.h
drivers/iommu/io-pgtable.h
+1
-8
drivers/iommu/iommu-sysfs.c
drivers/iommu/iommu-sysfs.c
+20
-12
drivers/iommu/mtk_iommu.c
drivers/iommu/mtk_iommu.c
+6
-0
drivers/iommu/mtk_iommu.h
drivers/iommu/mtk_iommu.h
+1
-0
include/linux/iommu.h
include/linux/iommu.h
+11
-1
No files found.
drivers/iommu/amd_iommu.c
View file @
894901b5
...
...
@@ -4452,6 +4452,7 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info)
/* Setting */
irte
->
hi
.
fields
.
ga_root_ptr
=
(
pi_data
->
base
>>
12
);
irte
->
hi
.
fields
.
vector
=
vcpu_pi_info
->
vector
;
irte
->
lo
.
fields_vapic
.
ga_log_intr
=
1
;
irte
->
lo
.
fields_vapic
.
guest_mode
=
1
;
irte
->
lo
.
fields_vapic
.
ga_tag
=
pi_data
->
ga_tag
;
...
...
drivers/iommu/amd_iommu_init.c
View file @
894901b5
...
...
@@ -2440,11 +2440,11 @@ static int __init state_next(void)
break
;
case
IOMMU_ACPI_FINISHED
:
early_enable_iommus
();
register_syscore_ops
(
&
amd_iommu_syscore_ops
);
x86_platform
.
iommu_shutdown
=
disable_iommus
;
init_state
=
IOMMU_ENABLED
;
break
;
case
IOMMU_ENABLED
:
register_syscore_ops
(
&
amd_iommu_syscore_ops
);
ret
=
amd_iommu_init_pci
();
init_state
=
ret
?
IOMMU_INIT_ERROR
:
IOMMU_PCI_INIT
;
enable_iommus_v2
();
...
...
drivers/iommu/amd_iommu_types.h
View file @
894901b5
...
...
@@ -574,7 +574,9 @@ struct amd_iommu {
static
inline
struct
amd_iommu
*
dev_to_amd_iommu
(
struct
device
*
dev
)
{
return
container_of
(
dev
,
struct
amd_iommu
,
iommu
.
dev
);
struct
iommu_device
*
iommu
=
dev_to_iommu_device
(
dev
);
return
container_of
(
iommu
,
struct
amd_iommu
,
iommu
);
}
#define ACPIHID_UID_LEN 256
...
...
drivers/iommu/arm-smmu.c
View file @
894901b5
...
...
@@ -400,6 +400,8 @@ struct arm_smmu_device {
u32
cavium_id_base
;
/* Specific to Cavium */
spinlock_t
global_sync_lock
;
/* IOMMU core code handle */
struct
iommu_device
iommu
;
};
...
...
@@ -436,7 +438,7 @@ struct arm_smmu_domain {
struct
arm_smmu_cfg
cfg
;
enum
arm_smmu_domain_stage
stage
;
struct
mutex
init_mutex
;
/* Protects smmu pointer */
spinlock_t
cb_lock
;
/* Serialises ATS1* ops */
spinlock_t
cb_lock
;
/* Serialises ATS1* ops
and TLB syncs
*/
struct
iommu_domain
domain
;
};
...
...
@@ -602,9 +604,12 @@ static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu,
static
void
arm_smmu_tlb_sync_global
(
struct
arm_smmu_device
*
smmu
)
{
void
__iomem
*
base
=
ARM_SMMU_GR0
(
smmu
);
unsigned
long
flags
;
spin_lock_irqsave
(
&
smmu
->
global_sync_lock
,
flags
);
__arm_smmu_tlb_sync
(
smmu
,
base
+
ARM_SMMU_GR0_sTLBGSYNC
,
base
+
ARM_SMMU_GR0_sTLBGSTATUS
);
spin_unlock_irqrestore
(
&
smmu
->
global_sync_lock
,
flags
);
}
static
void
arm_smmu_tlb_sync_context
(
void
*
cookie
)
...
...
@@ -612,9 +617,12 @@ static void arm_smmu_tlb_sync_context(void *cookie)
struct
arm_smmu_domain
*
smmu_domain
=
cookie
;
struct
arm_smmu_device
*
smmu
=
smmu_domain
->
smmu
;
void
__iomem
*
base
=
ARM_SMMU_CB
(
smmu
,
smmu_domain
->
cfg
.
cbndx
);
unsigned
long
flags
;
spin_lock_irqsave
(
&
smmu_domain
->
cb_lock
,
flags
);
__arm_smmu_tlb_sync
(
smmu
,
base
+
ARM_SMMU_CB_TLBSYNC
,
base
+
ARM_SMMU_CB_TLBSTATUS
);
spin_unlock_irqrestore
(
&
smmu_domain
->
cb_lock
,
flags
);
}
static
void
arm_smmu_tlb_sync_vmid
(
void
*
cookie
)
...
...
@@ -1511,6 +1519,12 @@ static int arm_smmu_add_device(struct device *dev)
if
(
using_legacy_binding
)
{
ret
=
arm_smmu_register_legacy_master
(
dev
,
&
smmu
);
/*
* If dev->iommu_fwspec is initally NULL, arm_smmu_register_legacy_master()
* will allocate/initialise a new one. Thus we need to update fwspec for
* later use.
*/
fwspec
=
dev
->
iommu_fwspec
;
if
(
ret
)
goto
out_free
;
...
...
@@ -1550,15 +1564,15 @@ static int arm_smmu_add_device(struct device *dev)
ret
=
arm_smmu_master_alloc_smes
(
dev
);
if
(
ret
)
goto
out_free
;
goto
out_
cfg_
free
;
iommu_device_link
(
&
smmu
->
iommu
,
dev
);
return
0
;
out_cfg_free:
kfree
(
cfg
);
out_free:
if
(
fwspec
)
kfree
(
fwspec
->
iommu_priv
);
iommu_fwspec_free
(
dev
);
return
ret
;
}
...
...
@@ -1925,6 +1939,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
smmu
->
num_mapping_groups
=
size
;
mutex_init
(
&
smmu
->
stream_map_mutex
);
spin_lock_init
(
&
smmu
->
global_sync_lock
);
if
(
smmu
->
version
<
ARM_SMMU_V2
||
!
(
id
&
ID0_PTFS_NO_AARCH32
))
{
smmu
->
features
|=
ARM_SMMU_FEAT_FMT_AARCH32_L
;
...
...
drivers/iommu/intel-iommu.c
View file @
894901b5
...
...
@@ -4736,7 +4736,9 @@ static void intel_disable_iommus(void)
static
inline
struct
intel_iommu
*
dev_to_intel_iommu
(
struct
device
*
dev
)
{
return
container_of
(
dev
,
struct
intel_iommu
,
iommu
.
dev
);
struct
iommu_device
*
iommu_dev
=
dev_to_iommu_device
(
dev
);
return
container_of
(
iommu_dev
,
struct
intel_iommu
,
iommu
);
}
static
ssize_t
intel_iommu_show_version
(
struct
device
*
dev
,
...
...
drivers/iommu/io-pgtable-arm-v7s.c
View file @
894901b5
...
...
@@ -479,6 +479,9 @@ static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova,
if
(
!
(
prot
&
(
IOMMU_READ
|
IOMMU_WRITE
)))
return
0
;
if
(
WARN_ON
(
upper_32_bits
(
iova
)
||
upper_32_bits
(
paddr
)))
return
-
ERANGE
;
ret
=
__arm_v7s_map
(
data
,
iova
,
paddr
,
size
,
prot
,
1
,
data
->
pgd
);
/*
* Synchronise all PTE updates for the new mapping before there's
...
...
@@ -659,6 +662,9 @@ static int arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova,
struct
arm_v7s_io_pgtable
*
data
=
io_pgtable_ops_to_data
(
ops
);
size_t
unmapped
;
if
(
WARN_ON
(
upper_32_bits
(
iova
)))
return
0
;
unmapped
=
__arm_v7s_unmap
(
data
,
iova
,
size
,
1
,
data
->
pgd
);
if
(
unmapped
)
io_pgtable_tlb_sync
(
&
data
->
iop
);
...
...
drivers/iommu/io-pgtable-arm.c
View file @
894901b5
...
...
@@ -452,6 +452,10 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,
if
(
!
(
iommu_prot
&
(
IOMMU_READ
|
IOMMU_WRITE
)))
return
0
;
if
(
WARN_ON
(
iova
>=
(
1ULL
<<
data
->
iop
.
cfg
.
ias
)
||
paddr
>=
(
1ULL
<<
data
->
iop
.
cfg
.
oas
)))
return
-
ERANGE
;
prot
=
arm_lpae_prot_to_pte
(
data
,
iommu_prot
);
ret
=
__arm_lpae_map
(
data
,
iova
,
paddr
,
size
,
prot
,
lvl
,
ptep
);
/*
...
...
@@ -610,6 +614,9 @@ static int arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova,
arm_lpae_iopte
*
ptep
=
data
->
pgd
;
int
lvl
=
ARM_LPAE_START_LVL
(
data
);
if
(
WARN_ON
(
iova
>=
(
1ULL
<<
data
->
iop
.
cfg
.
ias
)))
return
0
;
unmapped
=
__arm_lpae_unmap
(
data
,
iova
,
size
,
lvl
,
ptep
);
if
(
unmapped
)
io_pgtable_tlb_sync
(
&
data
->
iop
);
...
...
drivers/iommu/io-pgtable.h
View file @
894901b5
...
...
@@ -158,14 +158,12 @@ void free_io_pgtable_ops(struct io_pgtable_ops *ops);
* @fmt: The page table format.
* @cookie: An opaque token provided by the IOMMU driver and passed back to
* any callback routines.
* @tlb_sync_pending: Private flag for optimising out redundant syncs.
* @cfg: A copy of the page table configuration.
* @ops: The page table operations in use for this set of page tables.
*/
struct
io_pgtable
{
enum
io_pgtable_fmt
fmt
;
void
*
cookie
;
bool
tlb_sync_pending
;
struct
io_pgtable_cfg
cfg
;
struct
io_pgtable_ops
ops
;
};
...
...
@@ -175,22 +173,17 @@ struct io_pgtable {
static
inline
void
io_pgtable_tlb_flush_all
(
struct
io_pgtable
*
iop
)
{
iop
->
cfg
.
tlb
->
tlb_flush_all
(
iop
->
cookie
);
iop
->
tlb_sync_pending
=
true
;
}
static
inline
void
io_pgtable_tlb_add_flush
(
struct
io_pgtable
*
iop
,
unsigned
long
iova
,
size_t
size
,
size_t
granule
,
bool
leaf
)
{
iop
->
cfg
.
tlb
->
tlb_add_flush
(
iova
,
size
,
granule
,
leaf
,
iop
->
cookie
);
iop
->
tlb_sync_pending
=
true
;
}
static
inline
void
io_pgtable_tlb_sync
(
struct
io_pgtable
*
iop
)
{
if
(
iop
->
tlb_sync_pending
)
{
iop
->
cfg
.
tlb
->
tlb_sync
(
iop
->
cookie
);
iop
->
tlb_sync_pending
=
false
;
}
iop
->
cfg
.
tlb
->
tlb_sync
(
iop
->
cookie
);
}
/**
...
...
drivers/iommu/iommu-sysfs.c
View file @
894901b5
...
...
@@ -62,32 +62,40 @@ int iommu_device_sysfs_add(struct iommu_device *iommu,
va_list
vargs
;
int
ret
;
device_initialize
(
&
iommu
->
dev
);
iommu
->
dev
=
kzalloc
(
sizeof
(
*
iommu
->
dev
),
GFP_KERNEL
);
if
(
!
iommu
->
dev
)
return
-
ENOMEM
;
iommu
->
dev
.
class
=
&
iommu_class
;
iommu
->
dev
.
parent
=
parent
;
iommu
->
dev
.
groups
=
groups
;
device_initialize
(
iommu
->
dev
);
iommu
->
dev
->
class
=
&
iommu_class
;
iommu
->
dev
->
parent
=
parent
;
iommu
->
dev
->
groups
=
groups
;
va_start
(
vargs
,
fmt
);
ret
=
kobject_set_name_vargs
(
&
iommu
->
dev
.
kobj
,
fmt
,
vargs
);
ret
=
kobject_set_name_vargs
(
&
iommu
->
dev
->
kobj
,
fmt
,
vargs
);
va_end
(
vargs
);
if
(
ret
)
goto
error
;
ret
=
device_add
(
&
iommu
->
dev
);
ret
=
device_add
(
iommu
->
dev
);
if
(
ret
)
goto
error
;
dev_set_drvdata
(
iommu
->
dev
,
iommu
);
return
0
;
error:
put_device
(
&
iommu
->
dev
);
put_device
(
iommu
->
dev
);
return
ret
;
}
void
iommu_device_sysfs_remove
(
struct
iommu_device
*
iommu
)
{
device_unregister
(
&
iommu
->
dev
);
dev_set_drvdata
(
iommu
->
dev
,
NULL
);
device_unregister
(
iommu
->
dev
);
iommu
->
dev
=
NULL
;
}
/*
* IOMMU drivers can indicate a device is managed by a given IOMMU using
...
...
@@ -102,14 +110,14 @@ int iommu_device_link(struct iommu_device *iommu, struct device *link)
if
(
!
iommu
||
IS_ERR
(
iommu
))
return
-
ENODEV
;
ret
=
sysfs_add_link_to_group
(
&
iommu
->
dev
.
kobj
,
"devices"
,
ret
=
sysfs_add_link_to_group
(
&
iommu
->
dev
->
kobj
,
"devices"
,
&
link
->
kobj
,
dev_name
(
link
));
if
(
ret
)
return
ret
;
ret
=
sysfs_create_link_nowarn
(
&
link
->
kobj
,
&
iommu
->
dev
.
kobj
,
"iommu"
);
ret
=
sysfs_create_link_nowarn
(
&
link
->
kobj
,
&
iommu
->
dev
->
kobj
,
"iommu"
);
if
(
ret
)
sysfs_remove_link_from_group
(
&
iommu
->
dev
.
kobj
,
"devices"
,
sysfs_remove_link_from_group
(
&
iommu
->
dev
->
kobj
,
"devices"
,
dev_name
(
link
));
return
ret
;
...
...
@@ -121,5 +129,5 @@ void iommu_device_unlink(struct iommu_device *iommu, struct device *link)
return
;
sysfs_remove_link
(
&
link
->
kobj
,
"iommu"
);
sysfs_remove_link_from_group
(
&
iommu
->
dev
.
kobj
,
"devices"
,
dev_name
(
link
));
sysfs_remove_link_from_group
(
&
iommu
->
dev
->
kobj
,
"devices"
,
dev_name
(
link
));
}
drivers/iommu/mtk_iommu.c
View file @
894901b5
...
...
@@ -129,6 +129,7 @@ static void mtk_iommu_tlb_add_flush_nosync(unsigned long iova, size_t size,
writel_relaxed
(
iova
,
data
->
base
+
REG_MMU_INVLD_START_A
);
writel_relaxed
(
iova
+
size
-
1
,
data
->
base
+
REG_MMU_INVLD_END_A
);
writel_relaxed
(
F_MMU_INV_RANGE
,
data
->
base
+
REG_MMU_INVALIDATE
);
data
->
tlb_flush_active
=
true
;
}
static
void
mtk_iommu_tlb_sync
(
void
*
cookie
)
...
...
@@ -137,6 +138,10 @@ static void mtk_iommu_tlb_sync(void *cookie)
int
ret
;
u32
tmp
;
/* Avoid timing out if there's nothing to wait for */
if
(
!
data
->
tlb_flush_active
)
return
;
ret
=
readl_poll_timeout_atomic
(
data
->
base
+
REG_MMU_CPE_DONE
,
tmp
,
tmp
!=
0
,
10
,
100000
);
if
(
ret
)
{
...
...
@@ -146,6 +151,7 @@ static void mtk_iommu_tlb_sync(void *cookie)
}
/* Clear the CPE status */
writel_relaxed
(
0
,
data
->
base
+
REG_MMU_CPE_DONE
);
data
->
tlb_flush_active
=
false
;
}
static
const
struct
iommu_gather_ops
mtk_iommu_gather_ops
=
{
...
...
drivers/iommu/mtk_iommu.h
View file @
894901b5
...
...
@@ -47,6 +47,7 @@ struct mtk_iommu_data {
struct
iommu_group
*
m4u_group
;
struct
mtk_smi_iommu
smi_imu
;
/* SMI larb iommu info */
bool
enable_4GB
;
bool
tlb_flush_active
;
struct
iommu_device
iommu
;
};
...
...
include/linux/iommu.h
View file @
894901b5
...
...
@@ -240,7 +240,7 @@ struct iommu_device {
struct
list_head
list
;
const
struct
iommu_ops
*
ops
;
struct
fwnode_handle
*
fwnode
;
struct
device
dev
;
struct
device
*
dev
;
};
int
iommu_device_register
(
struct
iommu_device
*
iommu
);
...
...
@@ -265,6 +265,11 @@ static inline void iommu_device_set_fwnode(struct iommu_device *iommu,
iommu
->
fwnode
=
fwnode
;
}
static
inline
struct
iommu_device
*
dev_to_iommu_device
(
struct
device
*
dev
)
{
return
(
struct
iommu_device
*
)
dev_get_drvdata
(
dev
);
}
#define IOMMU_GROUP_NOTIFY_ADD_DEVICE 1
/* Device added */
#define IOMMU_GROUP_NOTIFY_DEL_DEVICE 2
/* Pre Device removed */
#define IOMMU_GROUP_NOTIFY_BIND_DRIVER 3
/* Pre Driver bind */
...
...
@@ -589,6 +594,11 @@ static inline void iommu_device_set_fwnode(struct iommu_device *iommu,
{
}
static
inline
struct
iommu_device
*
dev_to_iommu_device
(
struct
device
*
dev
)
{
return
NULL
;
}
static
inline
void
iommu_device_unregister
(
struct
iommu_device
*
iommu
)
{
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment