Linux v2.13.6中ACPI PCI中断路由的实现

版权申诉
0 下载量 200 浏览量 更新于2024-10-08 收藏 5KB RAR 举报
资源摘要信息:"PCI IRQ 是一个关于PCI总线中断路由的技术实现,特别针对Linux操作系统。该技术主要用于操作系统内核级别,负责管理PCI设备与中断请求(IRQ)之间的映射关系。PCI IRQ的技术实现文件名为'pci_irq.c',版本为v2.13.6。该文件是ACPI(高级配置与电源接口)的一部分,它为Linux系统中的PCI设备中断路由提供支持和管理。 在讨论PCI IRQ之前,首先需要了解一些基础概念。PCI(外围组件互连)是一种总线标准,允许各种外围设备(如显卡、声卡和网络卡)连接到计算机主板。中断请求(IRQ)是计算机系统中的一种信号线,用于向中央处理单元(CPU)发送中断信号,以处理紧急或重要的事件。中断路由是指将设备发出的中断信号正确地映射到CPU可用的中断线路上。 PCI IRQ在操作系统中的角色至关重要。它需要实现以下功能: 1. PCI中断路由初始化:在系统启动时,PCI IRQ必须初始化中断路由表,这包括映射哪些中断线用于哪些PCI设备。 2. 中断请求处理:当PCI设备需要CPU处理时,它会发出一个中断信号。PCI IRQ负责处理这些中断请求,确保它们被正确地转发到CPU。 3. 中断共享:现代计算机系统中,多个设备可能共享一个中断线路。PCI IRQ需要管理中断共享,确保当一个设备使用中断线路时,其他设备不会产生冲突。 4. 中断优先级:不同的设备有不同的中断优先级。PCI IRQ负责根据设备的中断优先级来排序,以优化中断处理的效率。 5. 系统电源管理:作为ACPI的一部分,PCI IRQ还参与了系统电源管理,包括在系统进入低功耗状态时保存中断路由信息,在唤醒后恢复中断路由。 在Linux内核的实现中,'pci_irq.c'文件包含了实现上述功能的核心代码。它由多个函数和数据结构组成,用于实现ACPI PCI中断路由协议。例如,它可能包含用于枚举PCI设备、配置中断路由表、处理中断请求的函数。 v2.13.6版本的'pci_irq.c'文件是该技术实现的较新版本,它可能包含了之前的版本中未有的错误修复、性能优化和新特性的增加。这个版本的发布应该能够为Linux系统中的PCI设备提供更加稳定和高效的中断处理。 了解这些知识点,对于Linux内核开发者和系统管理员来说是必要的。他们需要知道如何修改和优化'pci_irq.c'中的代码来适配特定硬件环境,或者确保系统稳定运行。对于硬件制造商而言,了解PCI IRQ的工作原理有助于他们设计出更好的硬件产品,以与Linux系统更好地协同工作。"

static void nvme_calc_irq_sets(struct irq_affinity *affd, unsigned int nrirqs) { struct nvme_dev *dev = affd->priv; unsigned int nr_read_queues, nr_write_queues = dev->nr_write_queues; if (!nrirqs) { nrirqs = 1; nr_read_queues = 0; } else if (nrirqs == 1 || !nr_write_queues) { nr_read_queues = 0; } else if (nr_write_queues >= nrirqs) { nr_read_queues = 1; } else { nr_read_queues = nrirqs - nr_write_queues; } dev->io_queues[HCTX_TYPE_DEFAULT] = nrirqs - nr_read_queues; affd->set_size[HCTX_TYPE_DEFAULT] = nrirqs - nr_read_queues; dev->io_queues[HCTX_TYPE_READ] = nr_read_queues; affd->set_size[HCTX_TYPE_READ] = nr_read_queues; affd->nr_sets = nr_read_queues ? 2 : 1; }static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues) { struct pci_dev *pdev = to_pci_dev(dev->dev); struct irq_affinity affd = { //ָ���ж��׺��Եļ��㷽���Ͳ��� .pre_vectors = 1, .calc_sets = nvme_set_irq_affinity, //nvme_calc_irq_sets, .priv = dev, }; unsigned int irq_queues, poll_queues; poll_queues = min(dev->nr_poll_queues, nr_io_queues - 1); dev->io_queues[HCTX_TYPE_POLL] = poll_queues; dev->io_queues[HCTX_TYPE_DEFAULT] = 1; dev->io_queues[HCTX_TYPE_READ] = 0; irq_queues = 1; if (!(dev->ctrl.quirks & NVME_QUIRK_SINGLE_VECTOR)) irq_queues += (nr_io_queues - poll_queues); return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues, PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd); } 在 Linux 5.17.12 内核版本中,如何修改 pci_alloc_irq_vectors_affinity() 函数的 affinity_hint 参数来绑定 NVMe 驱动的所有 I/O 队列到同一 CPU 核心上。代码展示

2023-06-09 上传
2023-06-06 上传

帮我优化一下这段代码配置2M波特率的CANFD :#include "can.h" #include "gd32c10x.h" #include "gd32c10x_eval.h" void can_gpio_config(void) { rcu_periph_clock_enable(RCU_CAN0); rcu_periph_clock_enable(RCU_CAN1); rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_AF); gpio_init(GPIOB,GPIO_MODE_IPU,GPIO_OSPEED_50MHZ,GPIO_PIN_8); gpio_init(GPIOB,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_9); gpio_init(GPIOB, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_5); gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6); gpio_pin_remap_config(GPIO_CAN0_PARTIAL_REMAP , ENABLE); gpio_pin_remap_config(GPIO_CAN1_REMAP, ENABLE); } void can_config(void) { can_parameter_struct can_parameter; can_fdframe_struct can_fd_parameter; can_fd_tdc_struct can_fd_tdc_parameter; can_struct_para_init(CAN_INIT_STRUCT, &can_parameter); can_deinit(CAN0); can_deinit(CAN1); can_parameter.time_triggered = DISABLE; can_parameter.auto_bus_off_recovery = DISABLE; can_parameter.auto_wake_up = DISABLE; can_parameter.auto_retrans = ENABLE; can_parameter.rec_fifo_overwrite = DISABLE; can_parameter.trans_fifo_order = DISABLE; can_parameter.working_mode = CAN_NORMAL_MODE; can_init(CAN0, &can_parameter); can_init(CAN1, &can_parameter); can_frequency_set(CAN0, CAN_BAUD_RATE); can_frequency_set(CAN1, CAN_BAUD_RATE); can_struct_para_init(CAN_FD_FRAME_STRUCT, &can_fd_parameter); can_fd_parameter.fd_frame = ENABLE; can_fd_parameter.excp_event_detect = ENABLE; can_fd_parameter.delay_compensation = ENABLE; can_fd_tdc_parameter.tdc_filter = 0x04; can_fd_tdc_parameter.tdc_mode = CAN_TDCMOD_CALC_AND_OFFSET; can_fd_tdc_parameter.tdc_offset = 0x04; can_fd_parameter.p_delay_compensation = &can_fd_tdc_parameter; can_fd_parameter.iso_bosch = CAN_FDMOD_ISO; can_fd_parameter.esi_mode = CAN_ESIMOD_HARDWARE; can_fd_init(CAN0, &can_fd_parameter); can_fd_init(CAN1, &can_fd_parameter); can_fd_frequency_set(CAN0, CANFD_BAUD_RATE); can_fd_frequency_set(CAN1, CANFD_BAUD_RATE); can1_filter_start_bank(14); can_filter_mask_mode_init(DEV_CAN0_ID, DEV_CAN0_MASK, CAN_EXTENDED_FIFO0, 0); can_filter_mask_mode_init(DEV_CAN1_ID, DEV_CAN1_MASK, CAN_EXTENDED_FIFO0, 15); nvic_irq_enable(CAN0_RX0_IRQn, 7, 0); nvic_irq_enable(CAN1_RX0_IRQn, 7, 0); can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0); can_interrupt_enable(CAN1, CAN_INTEN_RFNEIE0); }

2023-05-31 上传