summaryrefslogtreecommitdiff
path: root/arch/s390/kernel
diff options
context:
space:
mode:
authorHeiko Carstens <hca@linux.ibm.com>2023-09-11 21:40:08 +0200
committerVasily Gorbik <gor@linux.ibm.com>2023-09-19 13:26:57 +0200
commit305a5551af34e1848d80e095c23e94c985cc4ebc (patch)
tree6122644dca11c6c8c353274050f658801bbcbebb /arch/s390/kernel
parent103dde702d698c2e17529550650407a386711cdf (diff)
s390/ctlreg: add system_ctl_load()
Add system_ctl_load() which can be used to load a value to a control register system wide. Refactor system_ctl_set_clear_bit() so it can handle all different request types, and also rename it to system_ctlreg_modify() Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/ctlreg.c57
1 files changed, 39 insertions, 18 deletions
diff --git a/arch/s390/kernel/ctlreg.c b/arch/s390/kernel/ctlreg.c
index 27ba8db1d038..8cc26cf2c64a 100644
--- a/arch/s390/kernel/ctlreg.c
+++ b/arch/s390/kernel/ctlreg.c
@@ -44,24 +44,30 @@ void __init system_ctlreg_init_save_area(struct lowcore *lc)
system_ctlreg_area_init = true;
}
-struct ctl_bit_parms {
- unsigned long orval;
+struct ctlreg_parms {
unsigned long andval;
+ unsigned long orval;
+ unsigned long val;
+ int request;
int cr;
};
-static void ctl_bit_callback(void *info)
+static void ctlreg_callback(void *info)
{
- struct ctl_bit_parms *pp = info;
+ struct ctlreg_parms *pp = info;
struct ctlreg regs[16];
__local_ctl_store(0, 15, regs);
- regs[pp->cr].val &= pp->andval;
- regs[pp->cr].val |= pp->orval;
+ if (pp->request == CTLREG_LOAD) {
+ regs[pp->cr].val = pp->val;
+ } else {
+ regs[pp->cr].val &= pp->andval;
+ regs[pp->cr].val |= pp->orval;
+ }
__local_ctl_load(0, 15, regs);
}
-static void system_ctl_bit_update(void *info)
+static void system_ctlreg_update(void *info)
{
unsigned long flags;
@@ -71,30 +77,45 @@ static void system_ctl_bit_update(void *info)
* since not everything might be setup.
*/
local_irq_save(flags);
- ctl_bit_callback(info);
+ ctlreg_callback(info);
local_irq_restore(flags);
} else {
- on_each_cpu(ctl_bit_callback, info, 1);
+ on_each_cpu(ctlreg_callback, info, 1);
}
}
-void system_ctl_set_clear_bit(unsigned int cr, unsigned int bit, bool set)
+void system_ctlreg_modify(unsigned int cr, unsigned long data, int request)
{
- struct ctl_bit_parms pp = { .cr = cr, };
+ struct ctlreg_parms pp = { .cr = cr, .request = request, };
struct lowcore *abs_lc;
- pp.orval = set ? 1UL << bit : 0;
- pp.andval = set ? -1UL : ~(1UL << bit);
+ switch (request) {
+ case CTLREG_SET_BIT:
+ pp.orval = 1UL << data;
+ pp.andval = -1UL;
+ break;
+ case CTLREG_CLEAR_BIT:
+ pp.orval = 0;
+ pp.andval = ~(1UL << data);
+ break;
+ case CTLREG_LOAD:
+ pp.val = data;
+ break;
+ }
if (system_ctlreg_area_init) {
system_ctlreg_lock();
abs_lc = get_abs_lowcore();
- abs_lc->cregs_save_area[cr].val &= pp.andval;
- abs_lc->cregs_save_area[cr].val |= pp.orval;
+ if (request == CTLREG_LOAD) {
+ abs_lc->cregs_save_area[cr].val = pp.val;
+ } else {
+ abs_lc->cregs_save_area[cr].val &= pp.andval;
+ abs_lc->cregs_save_area[cr].val |= pp.orval;
+ }
put_abs_lowcore(abs_lc);
- system_ctl_bit_update(&pp);
+ system_ctlreg_update(&pp);
system_ctlreg_unlock();
} else {
- system_ctl_bit_update(&pp);
+ system_ctlreg_update(&pp);
}
}
-EXPORT_SYMBOL(system_ctl_set_clear_bit);
+EXPORT_SYMBOL(system_ctlreg_modify);