162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Functions for registration of I/O interruption subclasses on s390. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright IBM Corp. 2008 662306a36Sopenharmony_ci * Authors: Sebastian Ott <sebott@linux.vnet.ibm.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/spinlock.h> 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <asm/isc.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic unsigned int isc_refs[MAX_ISC + 1]; 1462306a36Sopenharmony_cistatic DEFINE_SPINLOCK(isc_ref_lock); 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/** 1862306a36Sopenharmony_ci * isc_register - register an I/O interruption subclass. 1962306a36Sopenharmony_ci * @isc: I/O interruption subclass to register 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * The number of users for @isc is increased. If this is the first user to 2262306a36Sopenharmony_ci * register @isc, the corresponding I/O interruption subclass mask is enabled. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * Context: 2562306a36Sopenharmony_ci * This function must not be called in interrupt context. 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_civoid isc_register(unsigned int isc) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci if (isc > MAX_ISC) { 3062306a36Sopenharmony_ci WARN_ON(1); 3162306a36Sopenharmony_ci return; 3262306a36Sopenharmony_ci } 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci spin_lock(&isc_ref_lock); 3562306a36Sopenharmony_ci if (isc_refs[isc] == 0) 3662306a36Sopenharmony_ci ctl_set_bit(6, 31 - isc); 3762306a36Sopenharmony_ci isc_refs[isc]++; 3862306a36Sopenharmony_ci spin_unlock(&isc_ref_lock); 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(isc_register); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/** 4362306a36Sopenharmony_ci * isc_unregister - unregister an I/O interruption subclass. 4462306a36Sopenharmony_ci * @isc: I/O interruption subclass to unregister 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * The number of users for @isc is decreased. If this is the last user to 4762306a36Sopenharmony_ci * unregister @isc, the corresponding I/O interruption subclass mask is 4862306a36Sopenharmony_ci * disabled. 4962306a36Sopenharmony_ci * Note: This function must not be called if isc_register() hasn't been called 5062306a36Sopenharmony_ci * before by the driver for @isc. 5162306a36Sopenharmony_ci * 5262306a36Sopenharmony_ci * Context: 5362306a36Sopenharmony_ci * This function must not be called in interrupt context. 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_civoid isc_unregister(unsigned int isc) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci spin_lock(&isc_ref_lock); 5862306a36Sopenharmony_ci /* check for misuse */ 5962306a36Sopenharmony_ci if (isc > MAX_ISC || isc_refs[isc] == 0) { 6062306a36Sopenharmony_ci WARN_ON(1); 6162306a36Sopenharmony_ci goto out_unlock; 6262306a36Sopenharmony_ci } 6362306a36Sopenharmony_ci if (isc_refs[isc] == 1) 6462306a36Sopenharmony_ci ctl_clear_bit(6, 31 - isc); 6562306a36Sopenharmony_ci isc_refs[isc]--; 6662306a36Sopenharmony_ciout_unlock: 6762306a36Sopenharmony_ci spin_unlock(&isc_ref_lock); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(isc_unregister); 70