mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-08 18:26:48 +00:00
refactor(irq): 拆分inner_setup_irq函数,降低栈内存峰值 (#1187)
* refactor(irq): 将错误处理函数重构为类方法 将原先的闭包错误处理函数重构为IrqManager的类方法,减少栈内存使用量864字节 Signed-off-by: longjin <longjin@DragonOS.org> * refactor(irq): 重构中断设置逻辑并优化日志处理 - 将inner_setup_irq拆分为prepare_irq_setup和finalize_irq_setup,使得没有栈帧的大小超过4k.降低内存占用峰值 Signed-off-by: longjin <longjin@DragonOS.org> * refactor(irq): 拆分finalize_irq_setup为setup_irq_resources和activate_irq_line 将原finalize_irq_setup函数拆分为两个更小、职责更明确的函数,并引入SetupIrqResourcesResp结构体管理中间状态。 Signed-off-by: longjin <longjin@DragonOS.org> * fmt --------- Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
parent
9f9b37c492
commit
41c7f962c9
@ -11,7 +11,7 @@ use crate::{
|
|||||||
irqchip::IrqChipSetMaskResult,
|
irqchip::IrqChipSetMaskResult,
|
||||||
irqdesc::{irq_desc_manager, InnerIrqDesc, IrqAction},
|
irqdesc::{irq_desc_manager, InnerIrqDesc, IrqAction},
|
||||||
},
|
},
|
||||||
libs::{cpumask::CpuMask, spinlock::SpinLockGuard},
|
libs::{cpumask::CpuMask, mutex::MutexGuard, spinlock::SpinLockGuard},
|
||||||
process::{kthread::KernelThreadMechanism, ProcessManager},
|
process::{kthread::KernelThreadMechanism, ProcessManager},
|
||||||
smp::cpu::ProcessorId,
|
smp::cpu::ProcessorId,
|
||||||
};
|
};
|
||||||
@ -156,21 +156,17 @@ impl IrqManager {
|
|||||||
*action_guard.flags_mut() = flags;
|
*action_guard.flags_mut() = flags;
|
||||||
*action_guard.dev_id_mut() = dev_id;
|
*action_guard.dev_id_mut() = dev_id;
|
||||||
drop(action_guard);
|
drop(action_guard);
|
||||||
debug!("to inner_setup_irq: {irq:?}");
|
// debug!("to inner_setup_irq: {irq:?}");
|
||||||
return self.inner_setup_irq(irq, irqaction, desc);
|
return self.inner_setup_irq(irq, irqaction, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/manage.c?r=&mo=59252&fi=2138#1497
|
/// 处理线程错误
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn inner_setup_irq(
|
fn handle_thread_error(
|
||||||
&self,
|
&self,
|
||||||
irq: IrqNumber,
|
e: SystemError,
|
||||||
action: Arc<IrqAction>,
|
mut action_guard: SpinLockGuard<'_, InnerIrqAction>,
|
||||||
desc: Arc<IrqDesc>,
|
) -> SystemError {
|
||||||
) -> Result<(), SystemError> {
|
|
||||||
// ==== 定义错误处理函数 ====
|
|
||||||
let err_out_thread =
|
|
||||||
|e: SystemError, mut action_guard: SpinLockGuard<'_, InnerIrqAction>| -> SystemError {
|
|
||||||
if let Some(thread_pcb) = action_guard.thread() {
|
if let Some(thread_pcb) = action_guard.thread() {
|
||||||
action_guard.set_thread(None);
|
action_guard.set_thread(None);
|
||||||
KernelThreadMechanism::stop(&thread_pcb).ok();
|
KernelThreadMechanism::stop(&thread_pcb).ok();
|
||||||
@ -183,60 +179,75 @@ impl IrqManager {
|
|||||||
KernelThreadMechanism::stop(&thread_pcb).ok();
|
KernelThreadMechanism::stop(&thread_pcb).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return e;
|
e
|
||||||
};
|
}
|
||||||
|
|
||||||
let err_out_bus_unlock = |e: SystemError,
|
/// 处理总线解锁错误
|
||||||
|
#[inline(never)]
|
||||||
|
fn handle_bus_unlock_error(
|
||||||
|
&self,
|
||||||
|
e: SystemError,
|
||||||
desc: Arc<IrqDesc>,
|
desc: Arc<IrqDesc>,
|
||||||
req_mutex_guard: crate::libs::mutex::MutexGuard<'_, ()>,
|
req_mutex_guard: crate::libs::mutex::MutexGuard<'_, ()>,
|
||||||
action_guard: SpinLockGuard<'_, InnerIrqAction>|
|
action_guard: SpinLockGuard<'_, InnerIrqAction>,
|
||||||
-> SystemError {
|
) -> SystemError {
|
||||||
desc.chip_bus_sync_unlock();
|
desc.chip_bus_sync_unlock();
|
||||||
drop(req_mutex_guard);
|
drop(req_mutex_guard);
|
||||||
return err_out_thread(e, action_guard);
|
self.handle_thread_error(e, action_guard)
|
||||||
};
|
}
|
||||||
|
|
||||||
let err_out_unlock = |e: SystemError,
|
/// 处理解锁错误
|
||||||
|
#[inline(never)]
|
||||||
|
fn handle_unlock_error(
|
||||||
|
&self,
|
||||||
|
e: SystemError,
|
||||||
desc_guard: SpinLockGuard<'_, InnerIrqDesc>,
|
desc_guard: SpinLockGuard<'_, InnerIrqDesc>,
|
||||||
desc: Arc<IrqDesc>,
|
desc: Arc<IrqDesc>,
|
||||||
req_mutex_guard: crate::libs::mutex::MutexGuard<'_, ()>,
|
req_mutex_guard: crate::libs::mutex::MutexGuard<'_, ()>,
|
||||||
action_guard: SpinLockGuard<'_, InnerIrqAction>|
|
action_guard: SpinLockGuard<'_, InnerIrqAction>,
|
||||||
-> SystemError {
|
) -> SystemError {
|
||||||
drop(desc_guard);
|
drop(desc_guard);
|
||||||
return err_out_bus_unlock(e, desc, req_mutex_guard, action_guard);
|
self.handle_bus_unlock_error(e, desc, req_mutex_guard, action_guard)
|
||||||
};
|
}
|
||||||
|
|
||||||
let err_out_mismatch = |old_action_guard: SpinLockGuard<'_, InnerIrqAction>,
|
/// 处理标志不匹配错误
|
||||||
|
#[inline(never)]
|
||||||
|
fn __inner_setup_irq_handle_mismatch_error(
|
||||||
|
&self,
|
||||||
|
old_action_guard: SpinLockGuard<'_, InnerIrqAction>,
|
||||||
desc_guard: SpinLockGuard<'_, InnerIrqDesc>,
|
desc_guard: SpinLockGuard<'_, InnerIrqDesc>,
|
||||||
action_guard: SpinLockGuard<'_, InnerIrqAction>,
|
action_guard: SpinLockGuard<'_, InnerIrqAction>,
|
||||||
desc: Arc<IrqDesc>,
|
desc: Arc<IrqDesc>,
|
||||||
req_mutex_guard: crate::libs::mutex::MutexGuard<'_, ()>|
|
req_mutex_guard: crate::libs::mutex::MutexGuard<'_, ()>,
|
||||||
-> SystemError {
|
) -> SystemError {
|
||||||
if !action_guard
|
if !action_guard
|
||||||
.flags()
|
.flags()
|
||||||
.contains(IrqHandleFlags::IRQF_PROBE_SHARED)
|
.contains(IrqHandleFlags::IRQF_PROBE_SHARED)
|
||||||
{
|
{
|
||||||
error!("Flags mismatch for irq {} (name: {}, flags: {:?}). old action name: {}, old flags: {:?}", irq.data(), action_guard.name(), action_guard.flags(), old_action_guard.name(), old_action_guard.flags());
|
error!("Flags mismatch for irq {} (name: {}, flags: {:?}). old action name: {}, old flags: {:?}",
|
||||||
|
desc.irq_data().irq().data(),
|
||||||
|
action_guard.name(),
|
||||||
|
action_guard.flags(),
|
||||||
|
old_action_guard.name(),
|
||||||
|
old_action_guard.flags());
|
||||||
}
|
}
|
||||||
return err_out_unlock(
|
self.handle_unlock_error(
|
||||||
SystemError::EBUSY,
|
SystemError::EBUSY,
|
||||||
desc_guard,
|
desc_guard,
|
||||||
desc,
|
desc,
|
||||||
req_mutex_guard,
|
req_mutex_guard,
|
||||||
action_guard,
|
action_guard,
|
||||||
);
|
)
|
||||||
};
|
|
||||||
|
|
||||||
// ===== 代码开始 =====
|
|
||||||
|
|
||||||
if Arc::ptr_eq(
|
|
||||||
&desc.irq_data().chip_info_read_irqsave().chip(),
|
|
||||||
&no_irq_chip(),
|
|
||||||
) {
|
|
||||||
return Err(SystemError::ENOSYS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut action_guard = action.inner();
|
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/irq/manage.c?r=&mo=59252&fi=2138#1497
|
||||||
|
#[inline(never)]
|
||||||
|
fn prepare_irq_setup<'a>(
|
||||||
|
&self,
|
||||||
|
mut action_guard: SpinLockGuard<'a, InnerIrqAction>,
|
||||||
|
irq: IrqNumber,
|
||||||
|
desc: &Arc<IrqDesc>,
|
||||||
|
) -> Result<SpinLockGuard<'a, InnerIrqAction>, SystemError> {
|
||||||
if !action_guard.flags().trigger_type_specified() {
|
if !action_guard.flags().trigger_type_specified() {
|
||||||
// 如果没有指定触发类型,则使用默认的触发类型
|
// 如果没有指定触发类型,则使用默认的触发类型
|
||||||
action_guard
|
action_guard
|
||||||
@ -263,7 +274,7 @@ impl IrqManager {
|
|||||||
if let Some(secondary) = action_guard.secondary() {
|
if let Some(secondary) = action_guard.secondary() {
|
||||||
let secondary_guard = secondary.inner();
|
let secondary_guard = secondary.inner();
|
||||||
if let Err(e) = self.setup_irq_thread(irq, secondary_guard.deref(), true) {
|
if let Err(e) = self.setup_irq_thread(irq, secondary_guard.deref(), true) {
|
||||||
return Err(err_out_thread(e, action_guard));
|
return Err(self.handle_thread_error(e, action_guard));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -286,6 +297,16 @@ impl IrqManager {
|
|||||||
*action_guard.flags_mut() &= !IrqHandleFlags::IRQF_ONESHOT;
|
*action_guard.flags_mut() &= !IrqHandleFlags::IRQF_ONESHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(action_guard)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn setup_irq_resources<'a>(
|
||||||
|
&self,
|
||||||
|
action_guard: SpinLockGuard<'a, InnerIrqAction>,
|
||||||
|
irq: IrqNumber,
|
||||||
|
desc: &'a Arc<IrqDesc>,
|
||||||
|
) -> Result<SetupIrqResourcesResp<'a>, SystemError> {
|
||||||
// Protects against a concurrent __free_irq() call which might wait
|
// Protects against a concurrent __free_irq() call which might wait
|
||||||
// for synchronize_hardirq() to complete without holding the optional
|
// for synchronize_hardirq() to complete without holding the optional
|
||||||
// chip bus lock and desc->lock. Also protects against handing out
|
// chip bus lock and desc->lock. Also protects against handing out
|
||||||
@ -301,14 +322,20 @@ impl IrqManager {
|
|||||||
// 如果当前中断线上还没有irqaction, 则先为中断线申请资源
|
// 如果当前中断线上还没有irqaction, 则先为中断线申请资源
|
||||||
if desc.actions().is_empty() {
|
if desc.actions().is_empty() {
|
||||||
if let Err(e) = self.irq_request_resources(desc.clone()) {
|
if let Err(e) = self.irq_request_resources(desc.clone()) {
|
||||||
|
#[inline(never)]
|
||||||
|
fn __tmp_log(name: &str, irq: &IrqNumber, desc: &Arc<IrqDesc>, e: &SystemError) {
|
||||||
error!(
|
error!(
|
||||||
"Failed to request resources for {} (irq {}) on irqchip {}, error {:?}",
|
"Failed to request resources for {} (irq {}) on irqchip {}, error {:?}",
|
||||||
action_guard.name(),
|
name,
|
||||||
irq.data(),
|
irq.data(),
|
||||||
desc.irq_data().chip_info_read_irqsave().chip().name(),
|
desc.irq_data().chip_info_read_irqsave().chip().name(),
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
return Err(err_out_bus_unlock(
|
}
|
||||||
|
|
||||||
|
__tmp_log(action_guard.name(), &irq, desc, &e);
|
||||||
|
|
||||||
|
return Err(self.handle_bus_unlock_error(
|
||||||
e,
|
e,
|
||||||
desc.clone(),
|
desc.clone(),
|
||||||
req_mutex_guard,
|
req_mutex_guard,
|
||||||
@ -317,7 +344,7 @@ impl IrqManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut desc_inner_guard: SpinLockGuard<'_, InnerIrqDesc> = desc.inner();
|
let desc_inner_guard: SpinLockGuard<'_, InnerIrqDesc> = desc.inner();
|
||||||
|
|
||||||
// 标记当前irq是否是共享的
|
// 标记当前irq是否是共享的
|
||||||
let mut irq_shared = false;
|
let mut irq_shared = false;
|
||||||
@ -330,9 +357,15 @@ impl IrqManager {
|
|||||||
.internal_state()
|
.internal_state()
|
||||||
.contains(IrqDescState::IRQS_NMI)
|
.contains(IrqDescState::IRQS_NMI)
|
||||||
{
|
{
|
||||||
|
#[inline(never)]
|
||||||
|
fn __tmp_log(
|
||||||
|
name: &str,
|
||||||
|
irq: &IrqNumber,
|
||||||
|
desc_inner_guard: &SpinLockGuard<'_, InnerIrqDesc>,
|
||||||
|
) {
|
||||||
error!(
|
error!(
|
||||||
"Invalid attempt to share NMI for {} (irq {}) on irqchip {}",
|
"Invalid attempt to share NMI for {} (irq {}) on irqchip {}",
|
||||||
action_guard.name(),
|
name,
|
||||||
irq.data(),
|
irq.data(),
|
||||||
desc_inner_guard
|
desc_inner_guard
|
||||||
.irq_data()
|
.irq_data()
|
||||||
@ -340,7 +373,11 @@ impl IrqManager {
|
|||||||
.chip()
|
.chip()
|
||||||
.name()
|
.name()
|
||||||
);
|
);
|
||||||
return Err(err_out_unlock(
|
}
|
||||||
|
|
||||||
|
__tmp_log(action_guard.name(), &irq, &desc_inner_guard);
|
||||||
|
|
||||||
|
return Err(self.handle_unlock_error(
|
||||||
SystemError::EINVAL,
|
SystemError::EINVAL,
|
||||||
desc_inner_guard,
|
desc_inner_guard,
|
||||||
desc.clone(),
|
desc.clone(),
|
||||||
@ -371,16 +408,16 @@ impl IrqManager {
|
|||||||
|| ((old_guard.flags().bitxor(*action_guard.flags()))
|
|| ((old_guard.flags().bitxor(*action_guard.flags()))
|
||||||
.contains(IrqHandleFlags::IRQF_ONESHOT))
|
.contains(IrqHandleFlags::IRQF_ONESHOT))
|
||||||
{
|
{
|
||||||
debug!(
|
// debug!(
|
||||||
"Flags mismatch for irq {} (name: {}, flags: {:?}). old action name: {}, old flags: {:?}",
|
// "Flags mismatch for irq {} (name: {}, flags: {:?}). old action name: {}, old flags: {:?}",
|
||||||
irq.data(),
|
// irq.data(),
|
||||||
action_guard.name(),
|
// action_guard.name(),
|
||||||
action_guard.flags(),
|
// action_guard.flags(),
|
||||||
old_guard.name(),
|
// old_guard.name(),
|
||||||
old_guard.flags()
|
// old_guard.flags()
|
||||||
);
|
// );
|
||||||
|
|
||||||
return Err(err_out_mismatch(
|
return Err(self.__inner_setup_irq_handle_mismatch_error(
|
||||||
old_guard,
|
old_guard,
|
||||||
desc_inner_guard,
|
desc_inner_guard,
|
||||||
action_guard,
|
action_guard,
|
||||||
@ -393,13 +430,13 @@ impl IrqManager {
|
|||||||
if *old_guard.flags() & IrqHandleFlags::IRQF_PERCPU
|
if *old_guard.flags() & IrqHandleFlags::IRQF_PERCPU
|
||||||
!= *action_guard.flags() & IrqHandleFlags::IRQF_PERCPU
|
!= *action_guard.flags() & IrqHandleFlags::IRQF_PERCPU
|
||||||
{
|
{
|
||||||
debug!(
|
// debug!(
|
||||||
"Per-cpu mismatch for irq {} (name: {}, flags: {:?})",
|
// "Per-cpu mismatch for irq {} (name: {}, flags: {:?})",
|
||||||
irq.data(),
|
// irq.data(),
|
||||||
action_guard.name(),
|
// action_guard.name(),
|
||||||
action_guard.flags()
|
// action_guard.flags()
|
||||||
);
|
// );
|
||||||
return Err(err_out_mismatch(
|
return Err(self.__inner_setup_irq_handle_mismatch_error(
|
||||||
old_guard,
|
old_guard,
|
||||||
desc_inner_guard,
|
desc_inner_guard,
|
||||||
action_guard,
|
action_guard,
|
||||||
@ -430,12 +467,17 @@ impl IrqManager {
|
|||||||
// 因为我们不能确定这个中断实际上具有什么类型。
|
// 因为我们不能确定这个中断实际上具有什么类型。
|
||||||
// 由于底层芯片实现可能会覆盖它们,所以类型标志并不可靠.
|
// 由于底层芯片实现可能会覆盖它们,所以类型标志并不可靠.
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn __tmp_log(irq: &IrqNumber, name: &str) {
|
||||||
error!(
|
error!(
|
||||||
"Requesting irq {} without a handler, and ONESHOT flags not set for irqaction: {}",
|
"Requesting irq {} without a handler, and ONESHOT flags not set for irqaction: {}",
|
||||||
irq.data(),
|
irq.data(),
|
||||||
action_guard.name()
|
name,
|
||||||
);
|
);
|
||||||
return Err(err_out_unlock(
|
}
|
||||||
|
|
||||||
|
__tmp_log(&irq, action_guard.name());
|
||||||
|
return Err(self.handle_unlock_error(
|
||||||
SystemError::EINVAL,
|
SystemError::EINVAL,
|
||||||
desc_inner_guard,
|
desc_inner_guard,
|
||||||
desc.clone(),
|
desc.clone(),
|
||||||
@ -444,89 +486,119 @@ impl IrqManager {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 第一次在当前irqdesc上注册中断处理函数
|
return Ok(SetupIrqResourcesResp {
|
||||||
if !irq_shared {
|
|
||||||
// 设置中断触发方式
|
|
||||||
if action_guard.flags().trigger_type_specified() {
|
|
||||||
let trigger_type = action_guard.flags().trigger_type();
|
|
||||||
if let Err(e) =
|
|
||||||
self.do_set_irq_trigger(desc.clone(), &mut desc_inner_guard, trigger_type)
|
|
||||||
{
|
|
||||||
debug!(
|
|
||||||
"Failed to set trigger type for irq {} (name: {}, flags: {:?}), error {:?}",
|
|
||||||
irq.data(),
|
|
||||||
action_guard.name(),
|
|
||||||
action_guard.flags(),
|
|
||||||
e
|
|
||||||
);
|
|
||||||
return Err(err_out_unlock(
|
|
||||||
e,
|
|
||||||
desc_inner_guard,
|
|
||||||
desc.clone(),
|
|
||||||
req_mutex_guard,
|
|
||||||
action_guard,
|
action_guard,
|
||||||
|
irq_shared,
|
||||||
|
desc_inner_guard,
|
||||||
|
req_mutex_guard,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn activate_irq_line<'a>(
|
||||||
|
&self,
|
||||||
|
irq: IrqNumber,
|
||||||
|
desc: &'a Arc<IrqDesc>,
|
||||||
|
action: Arc<IrqAction>,
|
||||||
|
mut resp: SetupIrqResourcesResp<'a>,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
// 第一次在当前irqdesc上注册中断处理函数
|
||||||
|
if !resp.irq_shared {
|
||||||
|
// 设置中断触发方式
|
||||||
|
if resp.action_guard.flags().trigger_type_specified() {
|
||||||
|
let trigger_type = resp.action_guard.flags().trigger_type();
|
||||||
|
if let Err(e) =
|
||||||
|
self.do_set_irq_trigger(desc.clone(), &mut resp.desc_inner_guard, trigger_type)
|
||||||
|
{
|
||||||
|
// debug!(
|
||||||
|
// "Failed to set trigger type for irq {} (name: {}, flags: {:?}), error {:?}",
|
||||||
|
// irq.data(),
|
||||||
|
// action_guard.name(),
|
||||||
|
// action_guard.flags(),
|
||||||
|
// e
|
||||||
|
// );
|
||||||
|
return Err(self.handle_unlock_error(
|
||||||
|
e,
|
||||||
|
resp.desc_inner_guard,
|
||||||
|
desc.clone(),
|
||||||
|
resp.req_mutex_guard,
|
||||||
|
resp.action_guard,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug!("to irq_activate");
|
// debug!("to irq_activate");
|
||||||
// 激活中断。这种激活必须独立于IRQ_NOAUTOEN进行*desc_inner_guard.internal_state_mut() |= IrqDescState::IRQS_NOREQUEST;uest.
|
// 激活中断。这种激活必须独立于IRQ_NOAUTOEN进行*desc_inner_guard.internal_state_mut() |= IrqDescState::IRQS_NOREQUEST;uest.
|
||||||
if let Err(e) = self.irq_activate(&desc, &mut desc_inner_guard) {
|
if let Err(e) = self.irq_activate(desc, &mut resp.desc_inner_guard) {
|
||||||
debug!(
|
// debug!(
|
||||||
"Failed to activate irq {} (name: {}, flags: {:?}), error {:?}",
|
// "Failed to activate irq {} (name: {}, flags: {:?}), error {:?}",
|
||||||
irq.data(),
|
// irq.data(),
|
||||||
action_guard.name(),
|
// action_guard.name(),
|
||||||
action_guard.flags(),
|
// action_guard.flags(),
|
||||||
e
|
// e
|
||||||
);
|
// );
|
||||||
return Err(err_out_unlock(
|
return Err(self.handle_unlock_error(
|
||||||
e,
|
e,
|
||||||
desc_inner_guard,
|
resp.desc_inner_guard,
|
||||||
desc.clone(),
|
desc.clone(),
|
||||||
req_mutex_guard,
|
resp.req_mutex_guard,
|
||||||
action_guard,
|
resp.action_guard,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
*desc_inner_guard.internal_state_mut() &= !(IrqDescState::IRQS_AUTODETECT
|
*resp.desc_inner_guard.internal_state_mut() &= !(IrqDescState::IRQS_AUTODETECT
|
||||||
| IrqDescState::IRQS_SPURIOUS_DISABLED
|
| IrqDescState::IRQS_SPURIOUS_DISABLED
|
||||||
| IrqDescState::IRQS_ONESHOT
|
| IrqDescState::IRQS_ONESHOT
|
||||||
| IrqDescState::IRQS_WAITING);
|
| IrqDescState::IRQS_WAITING);
|
||||||
desc_inner_guard
|
resp.desc_inner_guard
|
||||||
.common_data()
|
.common_data()
|
||||||
.clear_status(IrqStatus::IRQD_IRQ_INPROGRESS);
|
.clear_status(IrqStatus::IRQD_IRQ_INPROGRESS);
|
||||||
|
|
||||||
if action_guard.flags().contains(IrqHandleFlags::IRQF_PERCPU) {
|
if resp
|
||||||
desc_inner_guard
|
.action_guard
|
||||||
|
.flags()
|
||||||
|
.contains(IrqHandleFlags::IRQF_PERCPU)
|
||||||
|
{
|
||||||
|
resp.desc_inner_guard
|
||||||
.common_data()
|
.common_data()
|
||||||
.insert_status(IrqStatus::IRQD_PER_CPU);
|
.insert_status(IrqStatus::IRQD_PER_CPU);
|
||||||
desc_inner_guard.line_status_set_per_cpu();
|
resp.desc_inner_guard.line_status_set_per_cpu();
|
||||||
|
|
||||||
if action_guard.flags().contains(IrqHandleFlags::IRQF_NO_DEBUG) {
|
if resp
|
||||||
desc_inner_guard.line_status_set_no_debug();
|
.action_guard
|
||||||
|
.flags()
|
||||||
|
.contains(IrqHandleFlags::IRQF_NO_DEBUG)
|
||||||
|
{
|
||||||
|
resp.desc_inner_guard.line_status_set_no_debug();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if action_guard.flags().contains(IrqHandleFlags::IRQF_ONESHOT) {
|
if resp
|
||||||
*desc_inner_guard.internal_state_mut() |= IrqDescState::IRQS_ONESHOT;
|
.action_guard
|
||||||
|
.flags()
|
||||||
|
.contains(IrqHandleFlags::IRQF_ONESHOT)
|
||||||
|
{
|
||||||
|
*resp.desc_inner_guard.internal_state_mut() |= IrqDescState::IRQS_ONESHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果有要求的话,则忽略IRQ的均衡。
|
// 如果有要求的话,则忽略IRQ的均衡。
|
||||||
if action_guard
|
if resp
|
||||||
|
.action_guard
|
||||||
.flags()
|
.flags()
|
||||||
.contains(IrqHandleFlags::IRQF_NOBALANCING)
|
.contains(IrqHandleFlags::IRQF_NOBALANCING)
|
||||||
{
|
{
|
||||||
todo!("IRQF_NO_BALANCING");
|
todo!("IRQF_NO_BALANCING");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !action_guard
|
if !resp
|
||||||
|
.action_guard
|
||||||
.flags()
|
.flags()
|
||||||
.contains(IrqHandleFlags::IRQF_NO_AUTOEN)
|
.contains(IrqHandleFlags::IRQF_NO_AUTOEN)
|
||||||
&& desc_inner_guard.can_autoenable()
|
&& resp.desc_inner_guard.can_autoenable()
|
||||||
{
|
{
|
||||||
// 如果没有设置IRQF_NOAUTOEN,则自动使能中断
|
// 如果没有设置IRQF_NOAUTOEN,则自动使能中断
|
||||||
self.irq_startup(
|
self.irq_startup(
|
||||||
&desc,
|
desc,
|
||||||
&mut desc_inner_guard,
|
&mut resp.desc_inner_guard,
|
||||||
Self::IRQ_RESEND,
|
Self::IRQ_RESEND,
|
||||||
Self::IRQ_START_COND,
|
Self::IRQ_START_COND,
|
||||||
)
|
)
|
||||||
@ -536,49 +608,89 @@ impl IrqManager {
|
|||||||
// 共享中断可能在它仍然被禁用时请求它,然后永远等待中断。
|
// 共享中断可能在它仍然被禁用时请求它,然后永远等待中断。
|
||||||
|
|
||||||
static mut WARNED: bool = false;
|
static mut WARNED: bool = false;
|
||||||
if action_guard.flags().contains(IrqHandleFlags::IRQF_SHARED) && unsafe { !WARNED }
|
if resp
|
||||||
|
.action_guard
|
||||||
|
.flags()
|
||||||
|
.contains(IrqHandleFlags::IRQF_SHARED)
|
||||||
|
&& unsafe { !WARNED }
|
||||||
{
|
{
|
||||||
|
#[inline(never)]
|
||||||
|
fn __tmp_warn_shared_interrupt(irq: &IrqNumber, name: &str) {
|
||||||
warn!(
|
warn!(
|
||||||
"Shared interrupt {} for {} requested but not auto enabled",
|
"Shared interrupt {} for {} requested but not auto enabled",
|
||||||
irq.data(),
|
irq.data(),
|
||||||
action_guard.name()
|
name
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
__tmp_warn_shared_interrupt(&irq, resp.action_guard.name());
|
||||||
unsafe { WARNED = true };
|
unsafe { WARNED = true };
|
||||||
}
|
}
|
||||||
|
|
||||||
desc_inner_guard.set_depth(1);
|
resp.desc_inner_guard.set_depth(1);
|
||||||
}
|
}
|
||||||
} else if action_guard.flags().trigger_type_specified() {
|
} else if resp.action_guard.flags().trigger_type_specified() {
|
||||||
let new_trigger_type = action_guard.flags().trigger_type();
|
let new_trigger_type = resp.action_guard.flags().trigger_type();
|
||||||
let old_trigger_type = desc_inner_guard.common_data().trigger_type();
|
let old_trigger_type = resp.desc_inner_guard.common_data().trigger_type();
|
||||||
if new_trigger_type != old_trigger_type {
|
if new_trigger_type != old_trigger_type {
|
||||||
|
#[inline(never)]
|
||||||
|
fn ___tmp_log_irq_line_status_change(
|
||||||
|
old_trigger_type: IrqLineStatus,
|
||||||
|
new_trigger_type: IrqLineStatus,
|
||||||
|
irq: &IrqNumber,
|
||||||
|
) {
|
||||||
warn!("Irq {} uses trigger type: {old_trigger_type:?}, but requested trigger type: {new_trigger_type:?}.", irq.data());
|
warn!("Irq {} uses trigger type: {old_trigger_type:?}, but requested trigger type: {new_trigger_type:?}.", irq.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
___tmp_log_irq_line_status_change(old_trigger_type, new_trigger_type, &irq);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在队列末尾添加新的irqaction
|
// 在队列末尾添加新的irqaction
|
||||||
desc_inner_guard.add_action(action.clone());
|
resp.desc_inner_guard.add_action(action.clone());
|
||||||
|
|
||||||
// 检查我们是否曾经通过虚构的中断处理程序禁用过irq。重新启用它并再给它一次机会。
|
// 检查我们是否曾经通过虚构的中断处理程序禁用过irq。重新启用它并再给它一次机会。
|
||||||
if irq_shared
|
if resp.irq_shared
|
||||||
&& desc_inner_guard
|
&& resp
|
||||||
|
.desc_inner_guard
|
||||||
.internal_state()
|
.internal_state()
|
||||||
.contains(IrqDescState::IRQS_SPURIOUS_DISABLED)
|
.contains(IrqDescState::IRQS_SPURIOUS_DISABLED)
|
||||||
{
|
{
|
||||||
desc_inner_guard
|
resp.desc_inner_guard
|
||||||
.internal_state_mut()
|
.internal_state_mut()
|
||||||
.remove(IrqDescState::IRQS_SPURIOUS_DISABLED);
|
.remove(IrqDescState::IRQS_SPURIOUS_DISABLED);
|
||||||
self.do_enable_irq(desc.clone(), &mut desc_inner_guard).ok();
|
self.do_enable_irq(desc.clone(), &mut resp.desc_inner_guard)
|
||||||
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(desc_inner_guard);
|
drop(resp.desc_inner_guard);
|
||||||
desc.chip_bus_sync_unlock();
|
desc.chip_bus_sync_unlock();
|
||||||
drop(req_mutex_guard);
|
drop(resp.req_mutex_guard);
|
||||||
|
|
||||||
drop(action_guard);
|
drop(resp.action_guard);
|
||||||
self.wake_up_and_wait_for_irq_thread_ready(&desc, Some(action.clone()));
|
self.wake_up_and_wait_for_irq_thread_ready(desc, Some(action.clone()));
|
||||||
self.wake_up_and_wait_for_irq_thread_ready(&desc, action.inner().secondary());
|
self.wake_up_and_wait_for_irq_thread_ready(desc, action.inner().secondary());
|
||||||
return Ok(());
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
|
fn inner_setup_irq(
|
||||||
|
&self,
|
||||||
|
irq: IrqNumber,
|
||||||
|
action: Arc<IrqAction>,
|
||||||
|
desc: Arc<IrqDesc>,
|
||||||
|
) -> Result<(), SystemError> {
|
||||||
|
if Arc::ptr_eq(
|
||||||
|
&desc.irq_data().chip_info_read_irqsave().chip(),
|
||||||
|
&no_irq_chip(),
|
||||||
|
) {
|
||||||
|
return Err(SystemError::ENOSYS);
|
||||||
|
}
|
||||||
|
let action_guard = action.inner();
|
||||||
|
|
||||||
|
let action_guard = self.prepare_irq_setup(action_guard, irq, &desc)?;
|
||||||
|
let resp: SetupIrqResourcesResp<'_> = self.setup_irq_resources(action_guard, irq, &desc)?;
|
||||||
|
|
||||||
|
self.activate_irq_line(irq, &desc, action.clone(), resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 唤醒中断线程并等待中断线程准备好
|
/// 唤醒中断线程并等待中断线程准备好
|
||||||
@ -638,6 +750,7 @@ impl IrqManager {
|
|||||||
self.irq_startup(desc, desc_inner_guard, resend, Self::IRQ_START_FORCE)
|
self.irq_startup(desc, desc_inner_guard, resend, Self::IRQ_START_FORCE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(never)]
|
||||||
pub(super) fn irq_activate(
|
pub(super) fn irq_activate(
|
||||||
&self,
|
&self,
|
||||||
_desc: &Arc<IrqDesc>,
|
_desc: &Arc<IrqDesc>,
|
||||||
@ -1144,3 +1257,10 @@ impl IrqHandler for IrqNestedPrimaryHandler {
|
|||||||
return Ok(IrqReturn::NotHandled);
|
return Ok(IrqReturn::NotHandled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SetupIrqResourcesResp<'a> {
|
||||||
|
action_guard: SpinLockGuard<'a, InnerIrqAction>,
|
||||||
|
irq_shared: bool,
|
||||||
|
desc_inner_guard: SpinLockGuard<'a, InnerIrqDesc>,
|
||||||
|
req_mutex_guard: MutexGuard<'a, ()>,
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user