xref: /openbmc/linux/drivers/s390/cio/isc.c (revision 724117b7)
1724117b7SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2fcc6ab33SSebastian Ott /*
3fcc6ab33SSebastian Ott  * Functions for registration of I/O interruption subclasses on s390.
4fcc6ab33SSebastian Ott  *
5fcc6ab33SSebastian Ott  * Copyright IBM Corp. 2008
6fcc6ab33SSebastian Ott  * Authors: Sebastian Ott <sebott@linux.vnet.ibm.com>
7fcc6ab33SSebastian Ott  */
8fcc6ab33SSebastian Ott 
9fcc6ab33SSebastian Ott #include <linux/spinlock.h>
10fcc6ab33SSebastian Ott #include <linux/module.h>
11fcc6ab33SSebastian Ott #include <asm/isc.h>
12fcc6ab33SSebastian Ott 
13fcc6ab33SSebastian Ott static unsigned int isc_refs[MAX_ISC + 1];
14fcc6ab33SSebastian Ott static DEFINE_SPINLOCK(isc_ref_lock);
15fcc6ab33SSebastian Ott 
16fcc6ab33SSebastian Ott 
17fcc6ab33SSebastian Ott /**
18fcc6ab33SSebastian Ott  * isc_register - register an I/O interruption subclass.
19fcc6ab33SSebastian Ott  * @isc: I/O interruption subclass to register
20fcc6ab33SSebastian Ott  *
21fcc6ab33SSebastian Ott  * The number of users for @isc is increased. If this is the first user to
22fcc6ab33SSebastian Ott  * register @isc, the corresponding I/O interruption subclass mask is enabled.
23fcc6ab33SSebastian Ott  *
24fcc6ab33SSebastian Ott  * Context:
25fcc6ab33SSebastian Ott  *   This function must not be called in interrupt context.
26fcc6ab33SSebastian Ott  */
isc_register(unsigned int isc)27fcc6ab33SSebastian Ott void isc_register(unsigned int isc)
28fcc6ab33SSebastian Ott {
29fcc6ab33SSebastian Ott 	if (isc > MAX_ISC) {
30fcc6ab33SSebastian Ott 		WARN_ON(1);
31fcc6ab33SSebastian Ott 		return;
32fcc6ab33SSebastian Ott 	}
33fcc6ab33SSebastian Ott 
34fcc6ab33SSebastian Ott 	spin_lock(&isc_ref_lock);
35fcc6ab33SSebastian Ott 	if (isc_refs[isc] == 0)
36fcc6ab33SSebastian Ott 		ctl_set_bit(6, 31 - isc);
37fcc6ab33SSebastian Ott 	isc_refs[isc]++;
38fcc6ab33SSebastian Ott 	spin_unlock(&isc_ref_lock);
39fcc6ab33SSebastian Ott }
40fcc6ab33SSebastian Ott EXPORT_SYMBOL_GPL(isc_register);
41fcc6ab33SSebastian Ott 
42fcc6ab33SSebastian Ott /**
43fcc6ab33SSebastian Ott  * isc_unregister - unregister an I/O interruption subclass.
44fcc6ab33SSebastian Ott  * @isc: I/O interruption subclass to unregister
45fcc6ab33SSebastian Ott  *
46fcc6ab33SSebastian Ott  * The number of users for @isc is decreased. If this is the last user to
47fcc6ab33SSebastian Ott  * unregister @isc, the corresponding I/O interruption subclass mask is
48fcc6ab33SSebastian Ott  * disabled.
49fcc6ab33SSebastian Ott  * Note: This function must not be called if isc_register() hasn't been called
50fcc6ab33SSebastian Ott  * before by the driver for @isc.
51fcc6ab33SSebastian Ott  *
52fcc6ab33SSebastian Ott  * Context:
53fcc6ab33SSebastian Ott  *   This function must not be called in interrupt context.
54fcc6ab33SSebastian Ott  */
isc_unregister(unsigned int isc)55fcc6ab33SSebastian Ott void isc_unregister(unsigned int isc)
56fcc6ab33SSebastian Ott {
57fcc6ab33SSebastian Ott 	spin_lock(&isc_ref_lock);
58fcc6ab33SSebastian Ott 	/* check for misuse */
59fcc6ab33SSebastian Ott 	if (isc > MAX_ISC || isc_refs[isc] == 0) {
60fcc6ab33SSebastian Ott 		WARN_ON(1);
61fcc6ab33SSebastian Ott 		goto out_unlock;
62fcc6ab33SSebastian Ott 	}
63fcc6ab33SSebastian Ott 	if (isc_refs[isc] == 1)
64fcc6ab33SSebastian Ott 		ctl_clear_bit(6, 31 - isc);
65fcc6ab33SSebastian Ott 	isc_refs[isc]--;
66fcc6ab33SSebastian Ott out_unlock:
67fcc6ab33SSebastian Ott 	spin_unlock(&isc_ref_lock);
68fcc6ab33SSebastian Ott }
69fcc6ab33SSebastian Ott EXPORT_SYMBOL_GPL(isc_unregister);
70