书接上文,本文讲述瑞昱2.5G网卡rtl8125的触发硬件中断相关内容。

目录

1 中断处理函数(ISR)注册

2 触发硬件中断


可以通过下面的命令来看interrupts。

howard@B150:~/Driver/test/r8125-9.010.01/src$ cat /proc/interrupts CPU0       CPU1       CPU2       CPU3       0:          9          0          0          0   IO-APIC    2-edge      timer1:          2          0          0          0   IO-APIC    1-edge      i80428:          0          1          0          0   IO-APIC    8-edge      rtc09:          0          4          0          0   IO-APIC    9-fasteoi   acpi12:          0          0          0          4   IO-APIC   12-edge      i8042120:       4433          0         35          0   PCI-MSI 327680-edge      xhci_hcd121:          0          0       7940      19213   PCI-MSI 376832-edge      ahci[0000:00:17.0]122:          0          0          0         58   PCI-MSI 360448-edge      mei_me123:      25223         42          0          0   PCI-MSI 32768-edge      i915124:          0       1350          0          0   PCI-MSI 514048-edge      snd_hda_intel:card0125:          0          0         33          0   PCI-MSI 1048576-edge      enp2s0-0126:          0          0          0          0   PCI-MSI 1048577-edge      enp2s0-1127:          0          0          0          0   PCI-MSI 1048578-edge      enp2s0-2128:          0          0          0          0   PCI-MSI 1048579-edge      enp2s0-3129:          0          0          0          0   PCI-MSI 1048580-edge      enp2s0-4130:          0          0          0          0   PCI-MSI 1048581-edge      enp2s0-5131:          0          0          0          0   PCI-MSI 1048582-edge      enp2s0-6132:          0          0          0          0   PCI-MSI 1048583-edge      enp2s0-7133:          0          0          0          0   PCI-MSI 1048584-edge      enp2s0-8134:          0          0          0          0   PCI-MSI 1048585-edge      enp2s0-9135:          0          0          0          0   PCI-MSI 1048586-edge      enp2s0-10136:          0          0          0          0   PCI-MSI 1048587-edge      enp2s0-11137:          0          0          0          0   PCI-MSI 1048588-edge      enp2s0-12138:          0          0          0          0   PCI-MSI 1048589-edge      enp2s0-13139:          0          0          0          0   PCI-MSI 1048590-edge      enp2s0-14140:          0          0          0          0   PCI-MSI 1048591-edge      enp2s0-15141:          0          0         45          0   PCI-MSI 1048592-edge      enp2s0-16142:          0          0          0          0   PCI-MSI 1048593-edge      enp2s0-17143:          0          0          0          0   PCI-MSI 1048594-edge      enp2s0-18144:          0          0          0          0   PCI-MSI 1048595-edge      enp2s0-19145:          0          0          0          0   PCI-MSI 1048596-edge      enp2s0-20146:          0          0          0          1   PCI-MSI 1048597-edge      enp2s0-21147:          0          0          0          0   PCI-MSI 1048598-edge      enp2s0-22148:          0          0          0          0   PCI-MSI 1048599-edge      enp2s0-23149:          0          0          0          0   PCI-MSI 1048600-edge      enp2s0-24150:          0          0          0          0   PCI-MSI 1048601-edge      enp2s0-25151:          0          0          0          0   PCI-MSI 1048602-edge      enp2s0-26152:          0          0          0          0   PCI-MSI 1048603-edge      enp2s0-27153:          0          0          0          0   PCI-MSI 1048604-edge      enp2s0-28154:          0          0          0          0   PCI-MSI 1048605-edge      enp2s0-29155:          0          0          0          0   PCI-MSI 1048606-edge      enp2s0-30156:          0          0          0          0   PCI-MSI 1048607-edge      enp2s0-31157:          0          0         31          0   PCI-MSI 1572864-edge      enp3s0-0158:          0          0          0          0   PCI-MSI 1572865-edge      enp3s0-1159:          0          0          0          0   PCI-MSI 1572866-edge      enp3s0-2160:          0          0          0          0   PCI-MSI 1572867-edge      enp3s0-3161:          0          0          0          0   PCI-MSI 1572868-edge      enp3s0-4162:          0          0          0          0   PCI-MSI 1572869-edge      enp3s0-5163:          0          0          0          0   PCI-MSI 1572870-edge      enp3s0-6164:          0          0          0          0   PCI-MSI 1572871-edge      enp3s0-7165:          0          0          0          0   PCI-MSI 1572872-edge      enp3s0-8166:          0          0          0          0   PCI-MSI 1572873-edge      enp3s0-9167:          0          0          0          0   PCI-MSI 1572874-edge      enp3s0-10168:          0          0          0          0   PCI-MSI 1572875-edge      enp3s0-11169:          0          0          0          0   PCI-MSI 1572876-edge      enp3s0-12170:          0          0          0          0   PCI-MSI 1572877-edge      enp3s0-13171:          0          0          0          0   PCI-MSI 1572878-edge      enp3s0-14172:          0          0          0          0   PCI-MSI 1572879-edge      enp3s0-15173:          0          0         48          0   PCI-MSI 1572880-edge      enp3s0-16174:          0          0          0          0   PCI-MSI 1572881-edge      enp3s0-17175:          0          0          0          0   PCI-MSI 1572882-edge      enp3s0-18176:          0          0          0          0   PCI-MSI 1572883-edge      enp3s0-19177:          0          0          0          0   PCI-MSI 1572884-edge      enp3s0-20178:          0          0          0          1   PCI-MSI 1572885-edge      enp3s0-21179:          0          0          0          0   PCI-MSI 1572886-edge      enp3s0-22180:          0          0          0          0   PCI-MSI 1572887-edge      enp3s0-23181:          0          0          0          0   PCI-MSI 1572888-edge      enp3s0-24182:          0          0          0          0   PCI-MSI 1572889-edge      enp3s0-25183:          0          0          0          0   PCI-MSI 1572890-edge      enp3s0-26184:          0          0          0          0   PCI-MSI 1572891-edge      enp3s0-27185:          0          0          0          0   PCI-MSI 1572892-edge      enp3s0-28186:          0          0          0          0   PCI-MSI 1572893-edge      enp3s0-29187:          0          0          0          0   PCI-MSI 1572894-edge      enp3s0-30188:          0          0          0          0   PCI-MSI 1572895-edge      enp3s0-31NMI:          2          1          2          2   Non-maskable interruptsLOC:      31053      22096      25488      29308   Local timer interruptsSPU:          0          0          0          0   Spurious interruptsPMI:          2          1          2          2   Performance monitoring interruptsIWI:       1942         15          8          4   IRQ work interruptsRTR:          0          0          0          0   APIC ICR read retriesRES:       3165       2717       2090       2044   Rescheduling interruptsCAL:       3450       3079       2498       3748   Function call interruptsTLB:        868        687        649       1350   TLB shootdownsTRM:          0          0          0          0   Thermal event interruptsTHR:          0          0          0          0   Threshold APIC interruptsDFR:          0          0          0          0   Deferred Error APIC interruptsMCE:          0          0          0          0   Machine check exceptionsMCP:          1          2          2          2   Machine check pollsERR:          0MIS:          0PIN:          0          0          0          0   Posted-interrupt notification eventNPI:          0          0          0          0   Nested posted-interrupt eventPIW:          0          0          0          0   Posted-interrupt wakeup event

1 中断处理函数(ISR)注册

上文中提及rtl8125_open => rtl8125_alloc_irq。rtl8125_alloc_irq即实现了中断处理函数的注册。


static int rtl8125_alloc_irq(struct rtl8125_private *tp)
{struct net_device *dev = tp->dev;int rc = 0;struct r8125_irq *irq;struct r8125_napi *r8125napi;int i = 0;const int len = sizeof(tp->irq_tbl[0].name);// 这里没有define
#if defined(RTL_USE_NEW_INTR_API)for (i=0; i<tp->irq_nvecs; i++) {irq = &tp->irq_tbl[i];if (tp->features & RTL_FEATURE_MSIX &&tp->HwCurrIsrVer == 2)irq->handler = rtl8125_interrupt_msix;elseirq->handler = rtl8125_interrupt;r8125napi = &tp->r8125napi[i];snprintf(irq->name, len, "%s-%d", dev->name, i);rc = pci_request_irq(tp->pci_dev, i, irq->handler, NULL, r8125napi,irq->name);if (rc)break;irq->vector = pci_irq_vector(tp->pci_dev, i);irq->requested = 1;}
#elseunsigned long irq_flags = 0;
#ifdef ENABLE_LIB_SUPPORTirq_flags |= IRQF_NO_SUSPEND;
#endif//正常情况下是采用MSIXif (tp->features & RTL_FEATURE_MSIX &&tp->HwCurrIsrVer == 2) {for (i=0; i<tp->irq_nvecs; i++) {irq = &tp->irq_tbl[i];//这里指定了中断处理函数是rtl8125_interrupt_msixirq->handler = rtl8125_interrupt_msix;r8125napi = &tp->r8125napi[i];//irq->name是网卡名+index,从之前的介绍里可以对应上snprintf(irq->name, len, "%s-%d", dev->name, i);rc = request_irq(irq->vector, irq->handler, irq_flags, irq->name, r8125napi);if (rc)break;irq->requested = 1;}} else {irq = &tp->irq_tbl[0];irq->handler = rtl8125_interrupt;r8125napi = &tp->r8125napi[0];snprintf(irq->name, len, "%s-0", dev->name);if (!(tp->features & RTL_FEATURE_MSIX))irq->vector = dev->irq;irq_flags |= (tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX)) ? 0 : SA_SHIRQ;rc = request_irq(irq->vector, irq->handler, irq_flags, irq->name, r8125napi);if (rc == 0)irq->requested = 1;}
#endifif (rc)rtl8125_free_irq(tp);return rc;
}

2 触发硬件中断

当没有处于轮询状态时,收到包后就会触发硬件中断,调用中断处理函数rtl8125_interrupt_msix。下面需要注意CONFIG_R8125_NAPI已经在Makefile里define了。

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance, struct pt_regs *regs)
#else
static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance)
#endif
{struct r8125_napi *r8125napi = dev_instance;struct rtl8125_private *tp = r8125napi->priv;struct net_device *dev = tp->dev;int message_id = r8125napi->index;
#ifndef CONFIG_R8125_NAPIu32 budget = ~(u32)0;
#endifdo {
#if defined(RTL_USE_NEW_INTR_API)if (!tp->irq_tbl[message_id].requested)break;
#endif//执行硬件中断函数的时候需要屏蔽新的硬件中断rtl8125_disable_hw_interrupt_v2(tp, message_id);//clear isrrtl8125_clear_hw_isr_v2(tp, message_id);//link changeif (message_id == 21) {//这里的bit 21是Link Change Interruptrtl8125_schedule_linkchg_work(tp);break;}#ifdef CONFIG_R8125_NAPI//napi_schedule_prep()检查是否可以调度napiif (likely(RTL_NETIF_RX_SCHEDULE_PREP(dev, &r8125napi->napi)))//__napi_schedule(napi)__RTL_NETIF_RX_SCHEDULE(dev, &r8125napi->napi);else if (netif_msg_intr(tp))printk(KERN_INFO "%s: interrupt message id %d in poll_msix\n",dev->name, message_id);
#elsertl8125_tx_interrupt_with_vector(tp, message_id, ~(u32)0);if (message_id < tp->num_rx_rings) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], &budget);
#elsertl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget);
#endif  //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)}rtl8125_enable_hw_interrupt_v2(tp, message_id);
#endif} while (false);return IRQ_HANDLED;
}

NAPI 的轮询循环(poll loop)是受硬件中断触发而跑起来的。换句话说,NAPI 功能启用了 ,但是默认是没有工作的,直到第一个包到达的时候,网卡触发的一个硬件将它唤醒。

/*** __napi_schedule - schedule for receive* @n: entry to schedule** The entry's receive function will be scheduled to run.* Consider using __napi_schedule_irqoff() if hard irqs are masked.*/
void __napi_schedule(struct napi_struct *n)
{unsigned long flags;local_irq_save(flags);//获取对应这个 CPU 的 structure softnet_data 变量,作为参数传过去。____napi_schedule(this_cpu_ptr(&softnet_data), n);local_irq_restore(flags);
}
EXPORT_SYMBOL(__napi_schedule);/* Called with irq disabled */
static inline void ____napi_schedule(struct softnet_data *sd,struct napi_struct *napi)
{//将(从驱动的中断函数中传来的)napi_struct 变量,添加到 poll list,后者 attach 到这个 CPU 上的 softnet_datalist_add_tail(&napi->poll_list, &sd->poll_list);//触发一个 NET_RX_SOFTIRQ 类型软中断。这会触发执行 net_rx_action(如果没有正在执行),后者是网络设备初始化的时候注册的__raise_softirq_irqoff(NET_RX_SOFTIRQ);
}

参考文献:

Linux 网络栈接收数据(RX):原理及内核实现(2022)http://arthurchiao.art/blog/linux-net-stack-implementation-rx-zh/

如果觉得这篇文章有用的话,可以点赞、评论或者收藏,万分感谢,goodbye~

Realtek 8125驱动分析第二篇——触发硬件中断相关推荐

  1. Realtek 8125驱动分析第一篇——初始化

    Realtek 8125是瑞昱的2.5G网卡,今天开始分析一下该网卡的驱动程序. 目录 1 驱动模块注册 2 PCI相关初始化 2.1 PCI 驱动列表注册:pci_register_driver() ...

  2. SAP PP COR2下达工单系统报错说-系统状态APNG是激活的- 分析第二篇

    SAP PP COR2下达工单系统报错说-系统状态APNG是激活的- 分析第二篇 笔者所在的项目上启用了ECM(Engineer Change Management)功能,重要数据的修改都要事先创建一 ...

  3. Linux SD卡驱动开发(二) —— SD 卡驱动分析HOST篇

    回顾一下前面的知识,MMC 子系统范围三个部分: HOST 部分是针对不同主机的驱动程序,这一部是驱动程序工程师需要根据自己的特点平台来完成的. CORE 部分: 这是整个MMC 的核心存,这部分完成 ...

  4. nutch代码分析第二篇——crawl.crawl

    2021SC@SDUSC 顾名思义,org.apache.nutch.crawl.Crawl实现的是一个完整的抓取过程,包括各种方法的初始化,url集的建立 /* Perform complete c ...

  5. Linux SD卡驱动开发(五) —— SD 卡驱动分析Core补充篇

    Core层中有两个重要函数 mmc_alloc_host 用于构造host,前面已经学习过,这里不再阐述:另一个就是 mmc_add_host,用于注册host 前面探测函数s3cmci_probe, ...

  6. framebuffer驱动详解4——framebuffer驱动分析2(probe函数讲解)

    以下内容源于朱有鹏<物联网大讲堂>课程的学习,如有侵权,请告知删除. 主要在填充fbdev这个结构体. 二.framebuffer驱动分析2 1.probe函数分析 (1)struct s ...

  7. 【转】android电池(四):电池 电量计(MAX17040)驱动分析篇

    关键词:android 电池  电量计  MAX17040 任务初始化宏 power_supply 平台信息: 内核:linux2.6/linux3.0 系统:android/android4.0  ...

  8. android电池(五):电池 充电IC(PM2301)驱动分析篇

    android电池(五):电池 充电IC(PM2301)驱动分析篇 关键词:android 电池  电量计  PL2301任务初始化宏 power_supply 中断线程化 平台信息: 内核:linu ...

  9. Cyclone V SoC FPGA学习之路第二章:硬件篇

    Cyclone V SoC FPGA学习之路第二章:硬件篇(内部资源) 前言 上一章了解了<cycloneV device datasheet>,其中数据手册里重点介绍了电源要求,时序参数 ...

最新文章

  1. lvs+keepalived实现双实例【双主模型】
  2. 第一篇 webApp启航
  3. python实现pdf转word详解_手把手|20行Python代码教你批量将PDF文件转为Word格式(包教包会)...
  4. Discuz!NT负载均衡方案
  5. ElementTree中的getchildren and getiterator
  6. 《分布式系统:概念与设计》一2.3.2 体系结构模式
  7. mysql+查询新的一条记录表_Mysql 查询表中每个类别最新的一条记录
  8. vSphere 7 With K8s系列09:部署wordpress示例
  9. 软银愿景叕10亿美元砸向无人车,Nuro投后估值27亿美元
  10. 【数据结构 严蔚敏版】 循环队列 基本操作
  11. Java常见异常类【整理】
  12. 花一天时间体验 wintogo 到最终放弃
  13. Python模拟用户自动登陆网易126邮箱
  14. 基于优化LSTM 模型的股票预测
  15. java输入输出流数组_详解Java中ByteArray字节数组的输入输出流的用法
  16. cass简码大全_cass简码实体对照表
  17. 联想笔记本windows10设备管理器找不到蓝牙
  18. vs2017 html插件推荐,收藏!推荐12个超实用的Visual Studio插件
  19. oracle统计日均,oracle效率优化实战——计算3个月的平均值
  20. 运算放大器的性能指标

热门文章

  1. 2022/2/15 Hand Pose Estimation:综述阅读1
  2. 转自MBA lib 时间管理
  3. 微信小程序添加底部导航栏
  4. R语言MIDAS(Mixed Frequency Data Sampling Regression Models)学习分享(一)从下载安装包开始
  5. Oracle Coherence中文教程七:设置群集
  6. IM比较SipDroid/IMSDroid/CSipsimple/Linphone/Webrtc
  7. unity 3D RPG教程(四)
  8. 目前国内外的一些机器视觉公司汇总(2006年11月30日更新)
  9. 迟到的2016年计划
  10. Kubernetes 资源拓扑感知调度优化