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
aaa95f74
"storage/ndb/src/mgmsrv/MgmtSrvr.hpp" did not exist on "551ac8d69c7077b6deb4095bcb372c1239cc7254"
Commit
aaa95f74
authored
Mar 15, 2015
by
Jason Cooper
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'irqchip/urgent-gic' into irqchip/urgent
parents
5724be84
4559fbb3
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
146 additions
and
38 deletions
+146
-38
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3-its.c
+128
-29
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-gic-v3.c
+1
-1
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-gic.c
+12
-8
include/linux/irqchip/arm-gic-v3.h
include/linux/irqchip/arm-gic-v3.h
+5
-0
No files found.
drivers/irqchip/irq-gic-v3-its.c
View file @
aaa95f74
...
...
@@ -416,13 +416,14 @@ static void its_send_single_command(struct its_node *its,
{
struct
its_cmd_block
*
cmd
,
*
sync_cmd
,
*
next_cmd
;
struct
its_collection
*
sync_col
;
unsigned
long
flags
;
raw_spin_lock
(
&
its
->
lock
);
raw_spin_lock
_irqsave
(
&
its
->
lock
,
flags
);
cmd
=
its_allocate_entry
(
its
);
if
(
!
cmd
)
{
/* We're soooooo screewed... */
pr_err_ratelimited
(
"ITS can't allocate, dropping command
\n
"
);
raw_spin_unlock
(
&
its
->
lock
);
raw_spin_unlock
_irqrestore
(
&
its
->
lock
,
flags
);
return
;
}
sync_col
=
builder
(
cmd
,
desc
);
...
...
@@ -442,7 +443,7 @@ static void its_send_single_command(struct its_node *its,
post:
next_cmd
=
its_post_commands
(
its
);
raw_spin_unlock
(
&
its
->
lock
);
raw_spin_unlock
_irqrestore
(
&
its
->
lock
,
flags
);
its_wait_for_range_completion
(
its
,
cmd
,
next_cmd
);
}
...
...
@@ -799,21 +800,43 @@ static int its_alloc_tables(struct its_node *its)
{
int
err
;
int
i
;
int
psz
=
PAGE_SIZE
;
int
psz
=
SZ_64K
;
u64
shr
=
GITS_BASER_InnerShareable
;
for
(
i
=
0
;
i
<
GITS_BASER_NR_REGS
;
i
++
)
{
u64
val
=
readq_relaxed
(
its
->
base
+
GITS_BASER
+
i
*
8
);
u64
type
=
GITS_BASER_TYPE
(
val
);
u64
entry_size
=
GITS_BASER_ENTRY_SIZE
(
val
);
int
order
=
get_order
(
psz
);
int
alloc_size
;
u64
tmp
;
void
*
base
;
if
(
type
==
GITS_BASER_TYPE_NONE
)
continue
;
/* We're lazy and only allocate a single page for now */
base
=
(
void
*
)
get_zeroed_page
(
GFP_KERNEL
);
/*
* Allocate as many entries as required to fit the
* range of device IDs that the ITS can grok... The ID
* space being incredibly sparse, this results in a
* massive waste of memory.
*
* For other tables, only allocate a single page.
*/
if
(
type
==
GITS_BASER_TYPE_DEVICE
)
{
u64
typer
=
readq_relaxed
(
its
->
base
+
GITS_TYPER
);
u32
ids
=
GITS_TYPER_DEVBITS
(
typer
);
order
=
get_order
((
1UL
<<
ids
)
*
entry_size
);
if
(
order
>=
MAX_ORDER
)
{
order
=
MAX_ORDER
-
1
;
pr_warn
(
"%s: Device Table too large, reduce its page order to %u
\n
"
,
its
->
msi_chip
.
of_node
->
full_name
,
order
);
}
}
alloc_size
=
(
1
<<
order
)
*
PAGE_SIZE
;
base
=
(
void
*
)
__get_free_pages
(
GFP_KERNEL
|
__GFP_ZERO
,
order
);
if
(
!
base
)
{
err
=
-
ENOMEM
;
goto
out_free
;
...
...
@@ -841,7 +864,7 @@ static int its_alloc_tables(struct its_node *its)
break
;
}
val
|=
(
PAGE_SIZE
/
psz
)
-
1
;
val
|=
(
alloc_size
/
psz
)
-
1
;
writeq_relaxed
(
val
,
its
->
base
+
GITS_BASER
+
i
*
8
);
tmp
=
readq_relaxed
(
its
->
base
+
GITS_BASER
+
i
*
8
);
...
...
@@ -882,7 +905,7 @@ static int its_alloc_tables(struct its_node *its)
}
pr_info
(
"ITS: allocated %d %s @%lx (psz %dK, shr %d)
\n
"
,
(
int
)(
PAGE_SIZE
/
entry_size
),
(
int
)(
alloc_size
/
entry_size
),
its_base_type_string
[
type
],
(
unsigned
long
)
virt_to_phys
(
base
),
psz
/
SZ_1K
,
(
int
)
shr
>>
GITS_BASER_SHAREABILITY_SHIFT
);
...
...
@@ -1020,8 +1043,9 @@ static void its_cpu_init_collection(void)
static
struct
its_device
*
its_find_device
(
struct
its_node
*
its
,
u32
dev_id
)
{
struct
its_device
*
its_dev
=
NULL
,
*
tmp
;
unsigned
long
flags
;
raw_spin_lock
(
&
its
->
lock
);
raw_spin_lock
_irqsave
(
&
its
->
lock
,
flags
);
list_for_each_entry
(
tmp
,
&
its
->
its_device_list
,
entry
)
{
if
(
tmp
->
device_id
==
dev_id
)
{
...
...
@@ -1030,7 +1054,7 @@ static struct its_device *its_find_device(struct its_node *its, u32 dev_id)
}
}
raw_spin_unlock
(
&
its
->
lock
);
raw_spin_unlock
_irqrestore
(
&
its
->
lock
,
flags
);
return
its_dev
;
}
...
...
@@ -1040,6 +1064,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
{
struct
its_device
*
dev
;
unsigned
long
*
lpi_map
;
unsigned
long
flags
;
void
*
itt
;
int
lpi_base
;
int
nr_lpis
;
...
...
@@ -1056,7 +1081,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
nr_ites
=
max
(
2UL
,
roundup_pow_of_two
(
nvecs
));
sz
=
nr_ites
*
its
->
ite_size
;
sz
=
max
(
sz
,
ITS_ITT_ALIGN
)
+
ITS_ITT_ALIGN
-
1
;
itt
=
k
m
alloc
(
sz
,
GFP_KERNEL
);
itt
=
k
z
alloc
(
sz
,
GFP_KERNEL
);
lpi_map
=
its_lpi_alloc_chunks
(
nvecs
,
&
lpi_base
,
&
nr_lpis
);
if
(
!
dev
||
!
itt
||
!
lpi_map
)
{
...
...
@@ -1075,9 +1100,9 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
dev
->
device_id
=
dev_id
;
INIT_LIST_HEAD
(
&
dev
->
entry
);
raw_spin_lock
(
&
its
->
lock
);
raw_spin_lock
_irqsave
(
&
its
->
lock
,
flags
);
list_add
(
&
dev
->
entry
,
&
its
->
its_device_list
);
raw_spin_unlock
(
&
its
->
lock
);
raw_spin_unlock
_irqrestore
(
&
its
->
lock
,
flags
);
/* Bind the device to the first possible CPU */
cpu
=
cpumask_first
(
cpu_online_mask
);
...
...
@@ -1091,9 +1116,11 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
static
void
its_free_device
(
struct
its_device
*
its_dev
)
{
raw_spin_lock
(
&
its_dev
->
its
->
lock
);
unsigned
long
flags
;
raw_spin_lock_irqsave
(
&
its_dev
->
its
->
lock
,
flags
);
list_del
(
&
its_dev
->
entry
);
raw_spin_unlock
(
&
its_dev
->
its
->
lock
);
raw_spin_unlock
_irqrestore
(
&
its_dev
->
its
->
lock
,
flags
);
kfree
(
its_dev
->
itt
);
kfree
(
its_dev
);
}
...
...
@@ -1112,31 +1139,69 @@ static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq)
return
0
;
}
struct
its_pci_alias
{
struct
pci_dev
*
pdev
;
u32
dev_id
;
u32
count
;
};
static
int
its_pci_msi_vec_count
(
struct
pci_dev
*
pdev
)
{
int
msi
,
msix
;
msi
=
max
(
pci_msi_vec_count
(
pdev
),
0
);
msix
=
max
(
pci_msix_vec_count
(
pdev
),
0
);
return
max
(
msi
,
msix
);
}
static
int
its_get_pci_alias
(
struct
pci_dev
*
pdev
,
u16
alias
,
void
*
data
)
{
struct
its_pci_alias
*
dev_alias
=
data
;
dev_alias
->
dev_id
=
alias
;
if
(
pdev
!=
dev_alias
->
pdev
)
dev_alias
->
count
+=
its_pci_msi_vec_count
(
dev_alias
->
pdev
);
return
0
;
}
static
int
its_msi_prepare
(
struct
irq_domain
*
domain
,
struct
device
*
dev
,
int
nvec
,
msi_alloc_info_t
*
info
)
{
struct
pci_dev
*
pdev
;
struct
its_node
*
its
;
u32
dev_id
;
struct
its_device
*
its_dev
;
struct
its_pci_alias
dev_alias
;
if
(
!
dev_is_pci
(
dev
))
return
-
EINVAL
;
pdev
=
to_pci_dev
(
dev
);
dev_id
=
PCI_DEVID
(
pdev
->
bus
->
number
,
pdev
->
devfn
);
dev_alias
.
pdev
=
pdev
;
dev_alias
.
count
=
nvec
;
pci_for_each_dma_alias
(
pdev
,
its_get_pci_alias
,
&
dev_alias
);
its
=
domain
->
parent
->
host_data
;
its_dev
=
its_find_device
(
its
,
dev_id
);
if
(
WARN_ON
(
its_dev
))
return
-
EINVAL
;
its_dev
=
its_find_device
(
its
,
dev_alias
.
dev_id
);
if
(
its_dev
)
{
/*
* We already have seen this ID, probably through
* another alias (PCI bridge of some sort). No need to
* create the device.
*/
dev_dbg
(
dev
,
"Reusing ITT for devID %x
\n
"
,
dev_alias
.
dev_id
);
goto
out
;
}
its_dev
=
its_create_device
(
its
,
dev_
id
,
nvec
);
its_dev
=
its_create_device
(
its
,
dev_
alias
.
dev_id
,
dev_alias
.
count
);
if
(
!
its_dev
)
return
-
ENOMEM
;
dev_dbg
(
&
pdev
->
dev
,
"ITT %d entries, %d bits
\n
"
,
nvec
,
ilog2
(
nvec
));
dev_dbg
(
&
pdev
->
dev
,
"ITT %d entries, %d bits
\n
"
,
dev_alias
.
count
,
ilog2
(
dev_alias
.
count
));
out:
info
->
scratchpad
[
0
].
ptr
=
its_dev
;
info
->
scratchpad
[
1
].
ptr
=
dev
;
return
0
;
...
...
@@ -1255,6 +1320,34 @@ static const struct irq_domain_ops its_domain_ops = {
.
deactivate
=
its_irq_domain_deactivate
,
};
static
int
its_force_quiescent
(
void
__iomem
*
base
)
{
u32
count
=
1000000
;
/* 1s */
u32
val
;
val
=
readl_relaxed
(
base
+
GITS_CTLR
);
if
(
val
&
GITS_CTLR_QUIESCENT
)
return
0
;
/* Disable the generation of all interrupts to this ITS */
val
&=
~
GITS_CTLR_ENABLE
;
writel_relaxed
(
val
,
base
+
GITS_CTLR
);
/* Poll GITS_CTLR and wait until ITS becomes quiescent */
while
(
1
)
{
val
=
readl_relaxed
(
base
+
GITS_CTLR
);
if
(
val
&
GITS_CTLR_QUIESCENT
)
return
0
;
count
--
;
if
(
!
count
)
return
-
EBUSY
;
cpu_relax
();
udelay
(
1
);
}
}
static
int
its_probe
(
struct
device_node
*
node
,
struct
irq_domain
*
parent
)
{
struct
resource
res
;
...
...
@@ -1283,6 +1376,13 @@ static int its_probe(struct device_node *node, struct irq_domain *parent)
goto
out_unmap
;
}
err
=
its_force_quiescent
(
its_base
);
if
(
err
)
{
pr_warn
(
"%s: failed to quiesce, giving up
\n
"
,
node
->
full_name
);
goto
out_unmap
;
}
pr_info
(
"ITS: %s
\n
"
,
node
->
full_name
);
its
=
kzalloc
(
sizeof
(
*
its
),
GFP_KERNEL
);
...
...
@@ -1323,7 +1423,7 @@ static int its_probe(struct device_node *node, struct irq_domain *parent)
writeq_relaxed
(
baser
,
its
->
base
+
GITS_CBASER
);
tmp
=
readq_relaxed
(
its
->
base
+
GITS_CBASER
);
writeq_relaxed
(
0
,
its
->
base
+
GITS_CWRITER
);
writel_relaxed
(
1
,
its
->
base
+
GITS_CTLR
);
writel_relaxed
(
GITS_CTLR_ENABLE
,
its
->
base
+
GITS_CTLR
);
if
((
tmp
^
baser
)
&
GITS_BASER_SHAREABILITY_MASK
)
{
pr_info
(
"ITS: using cache flushing for cmd queue
\n
"
);
...
...
@@ -1382,12 +1482,11 @@ static bool gic_rdists_supports_plpis(void)
int
its_cpu_init
(
void
)
{
if
(
!
list_empty
(
&
its_nodes
))
{
if
(
!
gic_rdists_supports_plpis
())
{
pr_info
(
"CPU%d: LPIs not supported
\n
"
,
smp_processor_id
());
return
-
ENXIO
;
}
if
(
!
list_empty
(
&
its_nodes
))
{
its_cpu_init_lpis
();
its_cpu_init_collection
();
}
...
...
drivers/irqchip/irq-gic-v3.c
View file @
aaa95f74
...
...
@@ -466,7 +466,7 @@ static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
tlist
|=
1
<<
(
mpidr
&
0xf
);
cpu
=
cpumask_next
(
cpu
,
mask
);
if
(
cpu
=
=
nr_cpu_ids
)
if
(
cpu
>
=
nr_cpu_ids
)
goto
out
;
mpidr
=
cpu_logical_map
(
cpu
);
...
...
drivers/irqchip/irq-gic.c
View file @
aaa95f74
...
...
@@ -154,23 +154,25 @@ static inline unsigned int gic_irq(struct irq_data *d)
static
void
gic_mask_irq
(
struct
irq_data
*
d
)
{
u32
mask
=
1
<<
(
gic_irq
(
d
)
%
32
);
unsigned
long
flags
;
raw_spin_lock
(
&
irq_controller_lock
);
raw_spin_lock
_irqsave
(
&
irq_controller_lock
,
flags
);
writel_relaxed
(
mask
,
gic_dist_base
(
d
)
+
GIC_DIST_ENABLE_CLEAR
+
(
gic_irq
(
d
)
/
32
)
*
4
);
if
(
gic_arch_extn
.
irq_mask
)
gic_arch_extn
.
irq_mask
(
d
);
raw_spin_unlock
(
&
irq_controller_lock
);
raw_spin_unlock
_irqrestore
(
&
irq_controller_lock
,
flags
);
}
static
void
gic_unmask_irq
(
struct
irq_data
*
d
)
{
u32
mask
=
1
<<
(
gic_irq
(
d
)
%
32
);
unsigned
long
flags
;
raw_spin_lock
(
&
irq_controller_lock
);
raw_spin_lock
_irqsave
(
&
irq_controller_lock
,
flags
);
if
(
gic_arch_extn
.
irq_unmask
)
gic_arch_extn
.
irq_unmask
(
d
);
writel_relaxed
(
mask
,
gic_dist_base
(
d
)
+
GIC_DIST_ENABLE_SET
+
(
gic_irq
(
d
)
/
32
)
*
4
);
raw_spin_unlock
(
&
irq_controller_lock
);
raw_spin_unlock
_irqrestore
(
&
irq_controller_lock
,
flags
);
}
static
void
gic_eoi_irq
(
struct
irq_data
*
d
)
...
...
@@ -188,6 +190,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
{
void
__iomem
*
base
=
gic_dist_base
(
d
);
unsigned
int
gicirq
=
gic_irq
(
d
);
unsigned
long
flags
;
int
ret
;
/* Interrupt configuration for SGIs can't be changed */
...
...
@@ -199,14 +202,14 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
type
!=
IRQ_TYPE_EDGE_RISING
)
return
-
EINVAL
;
raw_spin_lock
(
&
irq_controller_lock
);
raw_spin_lock
_irqsave
(
&
irq_controller_lock
,
flags
);
if
(
gic_arch_extn
.
irq_set_type
)
gic_arch_extn
.
irq_set_type
(
d
,
type
);
ret
=
gic_configure_irq
(
gicirq
,
type
,
base
,
NULL
);
raw_spin_unlock
(
&
irq_controller_lock
);
raw_spin_unlock
_irqrestore
(
&
irq_controller_lock
,
flags
);
return
ret
;
}
...
...
@@ -227,6 +230,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
void
__iomem
*
reg
=
gic_dist_base
(
d
)
+
GIC_DIST_TARGET
+
(
gic_irq
(
d
)
&
~
3
);
unsigned
int
cpu
,
shift
=
(
gic_irq
(
d
)
%
4
)
*
8
;
u32
val
,
mask
,
bit
;
unsigned
long
flags
;
if
(
!
force
)
cpu
=
cpumask_any_and
(
mask_val
,
cpu_online_mask
);
...
...
@@ -236,12 +240,12 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
if
(
cpu
>=
NR_GIC_CPU_IF
||
cpu
>=
nr_cpu_ids
)
return
-
EINVAL
;
raw_spin_lock
(
&
irq_controller_lock
);
raw_spin_lock
_irqsave
(
&
irq_controller_lock
,
flags
);
mask
=
0xff
<<
shift
;
bit
=
gic_cpu_map
[
cpu
]
<<
shift
;
val
=
readl_relaxed
(
reg
)
&
~
mask
;
writel_relaxed
(
val
|
bit
,
reg
);
raw_spin_unlock
(
&
irq_controller_lock
);
raw_spin_unlock
_irqrestore
(
&
irq_controller_lock
,
flags
);
return
IRQ_SET_MASK_OK
;
}
...
...
include/linux/irqchip/arm-gic-v3.h
View file @
aaa95f74
...
...
@@ -166,6 +166,11 @@
#define GITS_TRANSLATER 0x10040
#define GITS_CTLR_ENABLE (1U << 0)
#define GITS_CTLR_QUIESCENT (1U << 31)
#define GITS_TYPER_DEVBITS_SHIFT 13
#define GITS_TYPER_DEVBITS(r) ((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
#define GITS_TYPER_PTA (1UL << 19)
#define GITS_CBASER_VALID (1UL << 63)
...
...
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