59
59
#define PLIC_DISABLE_THRESHOLD 0xf
60
60
#define PLIC_ENABLE_THRESHOLD 0
61
61
62
- static void __iomem * plic_regs ;
62
+ struct plic_priv {
63
+ struct cpumask lmask ;
64
+ struct irq_domain * irqdomain ;
65
+ void __iomem * regs ;
66
+ };
63
67
64
68
struct plic_handler {
65
69
bool present ;
@@ -70,6 +74,7 @@ struct plic_handler {
70
74
*/
71
75
raw_spinlock_t enable_lock ;
72
76
void __iomem * enable_base ;
77
+ struct plic_priv * priv ;
73
78
};
74
79
static DEFINE_PER_CPU (struct plic_handler , plic_handlers ) ;
75
80
@@ -88,49 +93,62 @@ static inline void plic_toggle(struct plic_handler *handler,
88
93
}
89
94
90
95
static inline void plic_irq_toggle (const struct cpumask * mask ,
91
- int hwirq , int enable )
96
+ struct irq_data * d , int enable )
92
97
{
93
98
int cpu ;
99
+ struct plic_priv * priv = irq_get_chip_data (d -> irq );
94
100
95
- writel (enable , plic_regs + PRIORITY_BASE + hwirq * PRIORITY_PER_ID );
101
+ writel (enable , priv -> regs + PRIORITY_BASE + d -> hwirq * PRIORITY_PER_ID );
96
102
for_each_cpu (cpu , mask ) {
97
103
struct plic_handler * handler = per_cpu_ptr (& plic_handlers , cpu );
98
104
99
- if (handler -> present )
100
- plic_toggle (handler , hwirq , enable );
105
+ if (handler -> present &&
106
+ cpumask_test_cpu (cpu , & handler -> priv -> lmask ))
107
+ plic_toggle (handler , d -> hwirq , enable );
101
108
}
102
109
}
103
110
104
111
static void plic_irq_unmask (struct irq_data * d )
105
112
{
106
- unsigned int cpu = cpumask_any_and (irq_data_get_affinity_mask (d ),
107
- cpu_online_mask );
113
+ struct cpumask amask ;
114
+ unsigned int cpu ;
115
+ struct plic_priv * priv = irq_get_chip_data (d -> irq );
116
+
117
+ cpumask_and (& amask , & priv -> lmask , cpu_online_mask );
118
+ cpu = cpumask_any_and (irq_data_get_affinity_mask (d ),
119
+ & amask );
108
120
if (WARN_ON_ONCE (cpu >= nr_cpu_ids ))
109
121
return ;
110
- plic_irq_toggle (cpumask_of (cpu ), d -> hwirq , 1 );
122
+ plic_irq_toggle (cpumask_of (cpu ), d , 1 );
111
123
}
112
124
113
125
static void plic_irq_mask (struct irq_data * d )
114
126
{
115
- plic_irq_toggle (cpu_possible_mask , d -> hwirq , 0 );
127
+ struct plic_priv * priv = irq_get_chip_data (d -> irq );
128
+
129
+ plic_irq_toggle (& priv -> lmask , d , 0 );
116
130
}
117
131
118
132
#ifdef CONFIG_SMP
119
133
static int plic_set_affinity (struct irq_data * d ,
120
134
const struct cpumask * mask_val , bool force )
121
135
{
122
136
unsigned int cpu ;
137
+ struct cpumask amask ;
138
+ struct plic_priv * priv = irq_get_chip_data (d -> irq );
139
+
140
+ cpumask_and (& amask , & priv -> lmask , mask_val );
123
141
124
142
if (force )
125
- cpu = cpumask_first (mask_val );
143
+ cpu = cpumask_first (& amask );
126
144
else
127
- cpu = cpumask_any_and (mask_val , cpu_online_mask );
145
+ cpu = cpumask_any_and (& amask , cpu_online_mask );
128
146
129
147
if (cpu >= nr_cpu_ids )
130
148
return - EINVAL ;
131
149
132
- plic_irq_toggle (cpu_possible_mask , d -> hwirq , 0 );
133
- plic_irq_toggle (cpumask_of (cpu ), d -> hwirq , 1 );
150
+ plic_irq_toggle (& priv -> lmask , d , 0 );
151
+ plic_irq_toggle (cpumask_of (cpu ), d , 1 );
134
152
135
153
irq_data_update_effective_affinity (d , cpumask_of (cpu ));
136
154
@@ -191,8 +209,6 @@ static const struct irq_domain_ops plic_irqdomain_ops = {
191
209
.free = irq_domain_free_irqs_top ,
192
210
};
193
211
194
- static struct irq_domain * plic_irqdomain ;
195
-
196
212
/*
197
213
* Handling an interrupt is a two-step process: first you claim the interrupt
198
214
* by reading the claim register, then you complete the interrupt by writing
@@ -209,7 +225,7 @@ static void plic_handle_irq(struct pt_regs *regs)
209
225
210
226
csr_clear (CSR_IE , IE_EIE );
211
227
while ((hwirq = readl (claim ))) {
212
- int irq = irq_find_mapping (plic_irqdomain , hwirq );
228
+ int irq = irq_find_mapping (handler -> priv -> irqdomain , hwirq );
213
229
214
230
if (unlikely (irq <= 0 ))
215
231
pr_warn_ratelimited ("can't find mapping for hwirq %lu\n" ,
@@ -265,15 +281,17 @@ static int __init plic_init(struct device_node *node,
265
281
{
266
282
int error = 0 , nr_contexts , nr_handlers = 0 , i ;
267
283
u32 nr_irqs ;
284
+ struct plic_priv * priv ;
268
285
269
- if (plic_regs ) {
270
- pr_warn ("PLIC already present.\n" );
271
- return - ENXIO ;
272
- }
286
+ priv = kzalloc (sizeof (* priv ), GFP_KERNEL );
287
+ if (!priv )
288
+ return - ENOMEM ;
273
289
274
- plic_regs = of_iomap (node , 0 );
275
- if (WARN_ON (!plic_regs ))
276
- return - EIO ;
290
+ priv -> regs = of_iomap (node , 0 );
291
+ if (WARN_ON (!priv -> regs )) {
292
+ error = - EIO ;
293
+ goto out_free_priv ;
294
+ }
277
295
278
296
error = - EINVAL ;
279
297
of_property_read_u32 (node , "riscv,ndev" , & nr_irqs );
@@ -287,9 +305,9 @@ static int __init plic_init(struct device_node *node,
287
305
goto out_iounmap ;
288
306
289
307
error = - ENOMEM ;
290
- plic_irqdomain = irq_domain_add_linear (node , nr_irqs + 1 ,
291
- & plic_irqdomain_ops , NULL );
292
- if (WARN_ON (!plic_irqdomain ))
308
+ priv -> irqdomain = irq_domain_add_linear (node , nr_irqs + 1 ,
309
+ & plic_irqdomain_ops , priv );
310
+ if (WARN_ON (!priv -> irqdomain ))
293
311
goto out_iounmap ;
294
312
295
313
for (i = 0 ; i < nr_contexts ; i ++ ) {
@@ -334,13 +352,14 @@ static int __init plic_init(struct device_node *node,
334
352
goto done ;
335
353
}
336
354
355
+ cpumask_set_cpu (cpu , & priv -> lmask );
337
356
handler -> present = true;
338
357
handler -> hart_base =
339
- plic_regs + CONTEXT_BASE + i * CONTEXT_PER_HART ;
358
+ priv -> regs + CONTEXT_BASE + i * CONTEXT_PER_HART ;
340
359
raw_spin_lock_init (& handler -> enable_lock );
341
360
handler -> enable_base =
342
- plic_regs + ENABLE_BASE + i * ENABLE_PER_HART ;
343
-
361
+ priv -> regs + ENABLE_BASE + i * ENABLE_PER_HART ;
362
+ handler -> priv = priv ;
344
363
done :
345
364
for (hwirq = 1 ; hwirq <= nr_irqs ; hwirq ++ )
346
365
plic_toggle (handler , hwirq , 0 );
@@ -356,7 +375,9 @@ static int __init plic_init(struct device_node *node,
356
375
return 0 ;
357
376
358
377
out_iounmap :
359
- iounmap (plic_regs );
378
+ iounmap (priv -> regs );
379
+ out_free_priv :
380
+ kfree (priv );
360
381
return error ;
361
382
}
362
383
0 commit comments