diff options
author | Heiko Carstens <hca@linux.ibm.com> | 2023-09-11 21:40:08 +0200 |
---|---|---|
committer | Vasily Gorbik <gor@linux.ibm.com> | 2023-09-19 13:26:57 +0200 |
commit | 305a5551af34e1848d80e095c23e94c985cc4ebc (patch) | |
tree | 6122644dca11c6c8c353274050f658801bbcbebb /arch/s390/kernel | |
parent | 103dde702d698c2e17529550650407a386711cdf (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.c | 57 |
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); |