当前位置: 首页> 房产> 建筑 > 视觉vi设计_引流推广平台是什么意思_成都百度快照优化排名_百度百度一下你就知道

视觉vi设计_引流推广平台是什么意思_成都百度快照优化排名_百度百度一下你就知道

时间:2025/7/9 7:09:51来源:https://blog.csdn.net/qq_16054639/article/details/142956664 浏览次数:1次
视觉vi设计_引流推广平台是什么意思_成都百度快照优化排名_百度百度一下你就知道

承接上文:arm64 中断处理流程
我们来看一下pcie msi-x中断是怎样注册的,他的中断是写在设备树中的,还是动态分配的。先说一下结论,pcie msi-x的中断是内核动态分配的。

驱动调用过程

我们先来一段示例代码,展示驱动如何申请和使用pcie msi-x中断:

#include <linux/pci.h>
#include <linux/interrupt.h>struct pci_dev *pdev;
int irq_vectors;
int irq;// 假设 pdev 已经指向一个有效的 PCI 设备// 尝试分配 1 到 4 个中断向量,允许使用 MSI-X
irq_vectors = pci_alloc_irq_vectors(pdev, 1, 4, PCI_IRQ_MSIX);if (irq_vectors < 0) {// 处理错误printk(KERN_ERR "Failed to allocate MSI-X vectors: %d\n", irq_vectors);
} else {printk(KERN_INFO "Allocated %d MSI-X vectors\n", irq_vectors);// 获取主中断号(即第一个中断向量的中断号)irq = pci_irq_vector(pdev, 0);if (irq < 0) {printk(KERN_ERR "Failed to get IRQ number for vector 0: %d\n", irq);} else {printk(KERN_INFO "IRQ number for vector 0: %d\n", irq);// 注册中断处理函数if (request_irq(irq, my_interrupt_handler, 0, "my_device", pdev)) {printk(KERN_ERR "Failed to request IRQ %d\n", irq);} else {printk(KERN_INFO "IRQ %d requested successfully\n", irq);}}
}

最重要的有一下三个步骤:

  • pci_alloc_irq_vectors
  • pci_irq_vector
  • request_irq

request_irq我们就忽略了,不清楚的可以看之前的文章

主要模块梳理

pcie msi-x涉及到的模块比较多,主要有三个部分

  1. pcie框架部分
  2. irq框架部分
  3. gic v3 its部分

我们重点来看一下pci_alloc_irq_vectors,这个函数进来过后直接在头文件转到了pci_alloc_irq_vectors_affinity

drivers/pci/msi.c

int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,unsigned int max_vecs, unsigned int flags,struct irq_affinity *affd)
{struct irq_affinity msi_default_affd = {0};int nvecs = -ENOSPC;if (flags & PCI_IRQ_MSIX) {nvecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs,affd, flags);if (nvecs > 0)return nvecs;}if (flags & PCI_IRQ_MSI) {nvecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, affd);if (nvecs > 0)return nvecs;}return nvecs;
}

__pci_enable_msix_range

static int __pci_enable_msix_range(struct pci_dev *dev,struct msix_entry *entries, int minvec,int maxvec, struct irq_affinity *affd,int flags)
{for (;;) {if (affd) {nvec = irq_calc_affinity_vectors(minvec, nvec, affd);if (nvec < minvec)return -ENOSPC;}rc = __pci_enable_msix(dev, entries, nvec, affd, flags);}
}

__pci_enable_msix

static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries,int nvec, struct irq_affinity *affd, int flags)
{nr_entries = pci_msix_vec_count(dev);if (nr_entries < 0)return nr_entries;if (nvec > nr_entries && !(flags & PCI_IRQ_VIRTUAL))return nr_entries;if (entries) {/* Check for any invalid entries */for (i = 0; i < nvec; i++) {if (entries[i].entry >= nr_entries)return -EINVAL;		/* invalid entry */for (j = i + 1; j < nvec; j++) {if (entries[i].entry == entries[j].entry)return -EINVAL;	/* duplicate entry */}}return msix_capability_init(dev, entries, nvec, affd);
}

msix_capability_init

static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,int nvec, struct irq_affinity *affd)
{ret = msix_setup_entries(dev, base, entries, nvec, affd);ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);msix_update_entries(dev, entries);return 0;
}

pci_msi_setup_msi_irqs

static int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
{struct irq_domain *domain;domain = dev_get_msi_domain(&dev->dev);if (domain && irq_domain_is_hierarchy(domain))return msi_domain_alloc_irqs(domain, &dev->dev, nvec);return arch_setup_msi_irqs(dev, nvec, type);
}

这里才到重点,msi_domain_alloc_irqs开始真正干事情
kernel/irq/msi.c

int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,int nvec)
{struct msi_domain_info *info = domain->host_data;struct msi_domain_ops *ops = info->ops;return ops->domain_alloc_irqs(domain, dev, nvec);
}
int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,int nvec)
{ret = msi_domain_prepare_irqs(domain, dev, nvec, &arg);if (ret)return ret;for_each_msi_entry(desc, dev) {ops->set_desc(&arg, desc);virq = __irq_domain_alloc_irqs(domain, -1, desc->nvec_used,dev_to_node(dev), &arg, false,desc->affinity);if (virq < 0) {ret = -ENOSPC;if (ops->handle_error)ret = ops->handle_error(domain, desc, ret);if (ops->msi_finish)ops->msi_finish(&arg, ret);return ret;}for (i = 0; i < desc->nvec_used; i++) {irq_set_msi_desc_off(virq, i, desc);irq_debugfs_copy_devname(virq + i, dev);}}if (ops->msi_finish)ops->msi_finish(&arg, 0);for_each_msi_vector(desc, i, dev) {if (desc->irq == i) {virq = desc->irq;dev_dbg(dev, "irq [%d-%d] for MSI\n",virq, virq + desc->nvec_used - 1);}irq_data = irq_domain_get_irq_data(domain, i);if (!can_reserve) {irqd_clr_can_reserve(irq_data);if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK)irqd_set_msi_nomask_quirk(irq_data);if ((info->flags & MSI_FLAG_ACTIVATE_EARLY) &&irqd_affinity_is_managed(irq_data) &&!cpumask_intersects(irq_data_get_affinity_mask(irq_data),cpu_online_mask)) {irqd_set_managed_shutdown(irq_data);continue;}}ret = irq_domain_activate_irq(irq_data, can_reserve);}
}

这里的主要过程有:

  • msi_domain_prepare_irqs
  • __irq_domain_alloc_irqs
  • irq_domain_activate_irq

__irq_domain_alloc_irqs主要就是分配硬件irq编号,硬件irq编号就是从这里来的,通过irq_domain_alloc_irqs_hierarchy进入ITS分配硬件中断,这里我们就不展开了,我们主要看msi_domain_prepare_irqsirq_domain_activate_irq

msi_domain_prepare_irqs会进入ITS,进行PCIE设备相关映射操作,这里会向ITS添加一个pcie设备到设备查找表
irq_domain_activate_irq会进入ITS,进行irq配置操作,将上面pcie设备的irq配置到ITT表中

int msi_domain_prepare_irqs(struct irq_domain *domain, struct device *dev,int nvec, msi_alloc_info_t *arg)
{ret = ops->msi_check(domain, info, dev);if (ret == 0)ret = ops->msi_prepare(domain, dev, nvec, arg);return ret;
}

msi_prepare由irq-giv-v3-pci-msi.c注册
/drivers/irqchip/irq-giv-v3-pci-msi.c

static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev,int nvec, msi_alloc_info_t *info)
{msi_info = msi_get_domain_info(domain->parent);pdev = to_pci_dev(dev);pci_for_each_dma_alias(pdev, its_get_pci_alias, &alias_dev);if (alias_dev != pdev && alias_dev->subordinate)pci_walk_bus(alias_dev->subordinate, its_pci_msi_vec_count,&alias_count);/* ITS specific DeviceID, as the core ITS ignores dev. */info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain, pdev);return msi_info->ops->msi_prepare(domain->parent, dev, nvec, info);
}static struct msi_domain_ops its_pci_msi_ops = {.msi_prepare	= its_pci_msi_prepare,
};

上面主要是生成device_id,放入info->scratchpad[0].ul中,msi_prepare调用到irq-giv-v3-msi.c中
/drivers/irqchip/irq-giv-v3-its.c

static int its_msi_prepare(struct irq_domain *domain, struct device *dev,int nvec, msi_alloc_info_t *info)
{its_dev = its_create_device(its, dev_id, nvec, true);
}static struct msi_domain_ops its_msi_domain_ops = {.msi_prepare	= its_msi_prepare,
};
static struct its_device *its_create_device(struct its_node *its, u32 dev_id,int nvecs, bool alloc_lpis)
{struct its_device *dev;unsigned long *lpi_map = NULL;unsigned long flags;u16 *col_map = NULL;void *itt;int lpi_base;int nr_lpis;int nr_ites;int sz;gfp_t gfp_flags;if (!its_alloc_device_table(its, dev_id))return NULL;if (WARN_ON(!is_power_of_2(nvecs)))nvecs = roundup_pow_of_two(nvecs);dev = kzalloc(sizeof(*dev), GFP_KERNEL);/** Even if the device wants a single LPI, the ITT must be* sized as a power of two (and you need at least one bit...).*/nr_ites = max(2, nvecs);sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;gfp_flags = GFP_KERNEL;if (of_machine_is_compatible("rockchip,rk3568") || of_machine_is_compatible("rockchip,rk3566")) {gfp_flags |= GFP_DMA32;itt = (void *)__get_free_pages(gfp_flags, get_order(sz));} else {itt = kzalloc_node(sz, gfp_flags, its->numa_node);}if (alloc_lpis) {lpi_map = its_lpi_alloc(nvecs, &lpi_base, &nr_lpis);if (lpi_map)col_map = kcalloc(nr_lpis, sizeof(*col_map),GFP_KERNEL);} else {col_map = kcalloc(nr_ites, sizeof(*col_map), GFP_KERNEL);nr_lpis = 0;lpi_base = 0;}if (!dev || !itt ||  !col_map || (!lpi_map && alloc_lpis)) {kfree(dev);if (of_machine_is_compatible("rockchip,rk3568") ||of_machine_is_compatible("rockchip,rk3566"))free_pages((unsigned long)itt, get_order(sz));elsekfree(itt);kfree(lpi_map);kfree(col_map);return NULL;}gic_flush_dcache_to_poc(itt, sz);dev->its = its;dev->itt = itt;dev->itt_sz = sz;dev->nr_ites = nr_ites;dev->event_map.lpi_map = lpi_map;dev->event_map.col_map = col_map;dev->event_map.lpi_base = lpi_base;dev->event_map.nr_lpis = nr_lpis;raw_spin_lock_init(&dev->event_map.vlpi_lock);dev->device_id = dev_id;INIT_LIST_HEAD(&dev->entry);raw_spin_lock_irqsave(&its->lock, flags);list_add(&dev->entry, &its->its_device_list);raw_spin_unlock_irqrestore(&its->lock, flags);/* Map device to its ITT */its_send_mapd(dev, 1);return dev;
}

这里主要是构造ITS命令,最后通过its_send_mapd发送到硬件执行,具体过程参见GIC v3 详解

好,我们回过头来看一下irq_domain_activate_irq

static int __irq_domain_activate_irq(struct irq_data *irqd, bool reserve)
{int ret = 0;if (irqd && irqd->domain) {struct irq_domain *domain = irqd->domain;if (irqd->parent_data)ret = __irq_domain_activate_irq(irqd->parent_data,reserve);if (!ret && domain->ops->activate) {ret = domain->ops->activate(domain, irqd, reserve);/* Rollback in case of error */if (ret && irqd->parent_data)__irq_domain_deactivate_irq(irqd->parent_data);}}return ret;
}int irq_domain_activate_irq(struct irq_data *irq_data, bool reserve)
{int ret = 0;if (!irqd_is_activated(irq_data))ret = __irq_domain_activate_irq(irq_data, reserve);if (!ret)irqd_set_activated(irq_data);return ret;
}

上面的关键点在domain->ops->activate这一句,这里进入到ITS进行中断配置

static int its_irq_domain_activate(struct irq_domain *domain,struct irq_data *d, bool reserve)
{struct its_device *its_dev = irq_data_get_irq_chip_data(d);u32 event = its_get_event_id(d);int cpu;cpu = its_select_cpu(d, cpu_online_mask);if (cpu < 0 || cpu >= nr_cpu_ids)return -EINVAL;its_inc_lpi_count(d, cpu);its_dev->event_map.col_map[event] = cpu;irq_data_update_effective_affinity(d, cpumask_of(cpu));/* Map the GIC IRQ and event to the device */its_send_mapti(its_dev, d->hwirq, event);return 0;
}

也是构造命令,最后通过its_send_mapti发送给硬件执行。

关键字:视觉vi设计_引流推广平台是什么意思_成都百度快照优化排名_百度百度一下你就知道

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: