网络设备的中断处理

我们这里描述的是硬件中断。

设备和内核之间的交互有两种方法。

1 polling(轮询)

也就是kernel来操作交互,由kernel来检测某一个状态,看是否需要让设备做什么。

2 interrupt(中断)

设备来发起交互,设备发出一个硬件中断请求给kernel当他需要kernel的注意时。


当中断来的时候被调用的函数称为interrupt handler,他必须通过设备的驱动来安装。当一个设备驱动注册一个NIC(Network Interface Card),他请求并标记了一个IRQ,然后他为这个中断请求注册一个回调函数.

其中注册回调函数与remove回调函数用下面的两个方法。

int request_irq(unsigned int irq,
irq_handler_t handler,
unsigned long irqflags, const char * devname, void *dev_id)

void free_irq(unsigned int irq, void *dev_id)


irq也就是中断请求号,handler就是中断抵达时的回调函数。irqflags是中断的类型,比如IRQF_SHARED(中断共享)等。dev_id也就是设备注册时的id。

NIC的中断的发生一般有下面的几种类型。

1 互联网帧的到达,也就是NIC接到数据。

2 传输失败。体现在用户层就是超时,等等。。

3 DMA传输成功完成。

比如有数据,通过DMA传递给NIC,由于DMA是异步的,因此设备驱动必须等待从NIC的一个显式的中断。

4 设备有足够的内存处理一个新的传输。

当egress queue没有足够的空间,也就是无法放入一帧时,NIC的驱动会关闭掉传输,并要求NIC当有比给定的内存更大的内存时发出一个中断,然后当中断来的时候会重新打开传输。

这里看一个例子:

3c509.c中的hard_start_xmit方法

netif_stop_queue (dev);

.................
if (inw(ioaddr + TX_FREE) > 1536)
netif_start_queue(dev);
else
/* Interrupt us when the FIFO has room for max-sized packet. */
outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);


这里只摘要了主要的代码,第一行停止了设备的传输队列,然后监测是否设备有足够的空间存放一帧(1536字节).如果有的话打开传输队列,否则指示设备当有足够空间的时候产生一个中断(使用outw来操作寄存器).当中断来的时候会调用netif_start_queue.


共享中断

共享中断也就是一个中断请求号关联了多个中断处理函数,当没一个设备注册中断请求号时候传递的参数声明是否这个中断能被共享。

接下来看下中断的数据结构:


struct irq_desc {
irq_flow_handler_t handle_irq;
struct irq_chip *chip;
struct msi_desc *msi_desc;
void *handler_data;
void *chip_data;
struct irqaction *action; /* IRQ action list */
unsigned int status; /* IRQ status */

unsigned int depth; /* nested irq disables */
unsigned int wake_depth; /* nested wake enables */
unsigned int irq_count; /* For detecting broken IRQs */
unsigned int irqs_unhandled;
unsigned long last_unhandled; /* Aging timer for unhandled count */
spinlock_t lock;
#ifdef CONFIG_SMP
cpumask_t affinity;
unsigned int cpu;
#endif
#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
cpumask_t pending_mask;
#endif
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *dir;
#endif
const char *name;
}


irq_desc 代表中断的描述符(他是全局的)而且是与平台相关的,因此我们可以看到不同的平台实现了自己的中断处理的相关函数,而中断的处理函数是包含在action中的,其中如果action多于一个元素,就代表这个irq是共享irq。

struct irqaction {
irq_handler_t handler; ///中断处理函数
unsigned long flags;
cpumask_t mask;
const char *name;
void *dev_id;
struct irqaction *next; ///链表的指针
int irq; ///中断号
struct proc_dir_entry *dir;
};


下面的图很好的显示了irq_desc的结构。

[img]/upload/attachment/91169/151d5bab-f3ef-391d-b452-62879850b54b.jpg[/img]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值