ARM Linuxによる割り込みの処理--登録方法の割り込み

5865 ワード

登録メソッドの中断
ドライバでデバイスに割り込みを発生させるには、まずrequest_を呼び出す必要があります.IRq()は、中断線を割り当てる.request_を通過するIRq()関数が割り込みサービスプログラムを登録すると,デバイス割り込み処理プログラムがシステムに追加され,割り込みが発生したときに対応する割り込み処理プログラムが呼び出される.リクエストを見てみましょうIRq()関数の定義:
---------------------------------------------------------------------
include/linux/interrupt.h
121 static inline int __must_check
122 request_irq(unsigned int irq, irq_handler_t handler, unsigned long
123             flags, const char *name, void *dev)
124 {
125         return request_threaded_irq(irq, handler, NULL, flags, name, dev);
126 }
---------------------------------------------------------------------
バージョン2.6.34のカーネルでrequest_IRq()関数はrequest_threaded_IRq()関数のカプセル化、request_threaded_IRq()関数は次のように定義されます.
---------------------------------------------------------------------
kernel/irq/manage.c
1038 int request_threaded_irq(unsigned int irq, irq_handler_t handler,
1039               irq_handler_t thread_fn, unsigned long irqflags,
1040               const char *devname, void *dev_id)
1041 {
1042   struct irqaction *action;
1043   struct irq_desc *desc;
1044   int retval;
1045
1046   /*
1047    * handle_IRQ_event() always ignores IRQF_DISABLED except for
1048    * the _first_ irqaction (sigh).  That can cause oopsing, but
1049    * the behavior is classified as "will not fix" so we need to
1050    * start nudging drivers away from using that idiom.
1051    */
1052   if ((irqflags & (IRQF_SHARED|IRQF_DISABLED)) ==
1053                   (IRQF_SHARED|IRQF_DISABLED)) {
1054      pr_warning(
1055      "IRQ %d/%s: IRQF_DISABLED is not guaranteed on shared IRQs
", 1056 irq, devname); 1057 } 1058 1059 #ifdef CONFIG_LOCKDEP 1060 /* 1061 * Lockdep wants atomic interrupt handlers: 1062 */ 1063 irqflags |= IRQF_DISABLED; 1064 #endif 1065 /* 1066 * Sanity-check: shared interrupts must pass in a real dev-ID, 1067 * otherwise we'll have trouble later trying to figure out 1068 * which interrupt is which (messes up the interrupt freeing 1069 * logic etc). 1070 */ 1071 if ((irqflags & IRQF_SHARED) && !dev_id) 1072 return -EINVAL; 1073 1074 desc = irq_to_desc(irq); 1075 if (!desc) 1076 return -EINVAL; 1077 1078 if (desc->status & IRQ_NOREQUEST) 1079 return -EINVAL; 1080 1081 if (!handler) { 1082 if (!thread_fn) 1083 return -EINVAL; 1084 handler = irq_default_primary_handler; 1085 } 1086 1087 action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); 1088 if (!action) 1089 return -ENOMEM; 1090 1091 action->handler = handler; 1092 action->thread_fn = thread_fn; 1093 action->flags = irqflags; 1094 action->name = devname; 1095 action->dev_id = dev_id; 1096 1097 chip_bus_lock(irq, desc); 1098 retval = __setup_irq(irq, desc, action); 1099 chip_bus_sync_unlock(irq, desc); 1100 1101 if (retval) 1102 kfree(action); 1103 1104 #ifdef CONFIG_DEBUG_SHIRQ 1105 if (!retval && (irqflags & IRQF_SHARED)) { 1106 /* 1107 * It's a shared IRQ -- the driver ought to be prepared for it 1108 * to happen immediately, so let's make sure.... 1109 * We disable the irq to make sure that a 'real' IRQ doesn't 1110 * run in parallel with our fake. 1111 */ 1112 unsigned long flags; 1113 1114 disable_irq(irq); 1115 local_irq_save(flags); 1116 1117 handler(irq, dev_id); 1118 1119 local_irq_restore(flags); 1120 enable_irq(irq); 1121 } 1122 #endif 1123 return retval; 1124 } 1125 EXPORT_SYMBOL(request_threaded_irq);
---------------------------------------------------------------------
カーネルはこの関数を使用して、割り当ての断線を完了します.各パラメータは次のように説明されています.
IRqは、登録するハードウェア割り込み番号です.
handlerは、システムに登録された割り込み処理関数で、それはコールバック関数であり、対応する中断線が割り込みが発生した場合、システムはこの関数を呼び出す.
IRqflags,割り込みタイプフラグ,IRQF_*,割り込み処理の属性であり、IRQF_が設定されている場合DISABLED(旧バージョンのSA_INTERUPT、本バージョンではサポートされていない)は、割り込み処理プログラムが高速処理プログラムであることを示し、高速処理プログラムが呼び出されたときにすべての割り込みをマスクし、低速処理プログラムはマスクしない.IRQFが設定されている場合SHARED(旧バージョンのSA_SHIRQ)は、複数のデバイスが同一の割り込みを共有していることを示す.IRQFが設定されている場合SAMPLE_RANDOM(旧バージョンのSA_SAMPLE_RANDOM)は、システムエントロピーに寄与し、システムの乱数取得に有利であることを示し、IRQF_TRIGGER_*フラグは、割り込みのトリガ方法を指定します.(これらのflagは、または同時に使用することができる).
devnameは、宣言されたデバイスのascii名で、割り込み番号に関連付けられた名前で、/proc/interruptsファイルに表示されます.
dev_idは、I/Oデバイスのプライベートデータフィールドであり、典型的には、I/Oデバイス自体(例えば、プライマリデバイス番号とこのデバイス番号に等しい可能性がある)を識別したり、デバイスドライバのデータを指したりして、handler関数に返されます.共有を中断するときに使用されます.一般的には、このデバイスのドライバの有効なアドレス値またはNULLに設定されます.
thread_fnは、irq handlerスレッドによって呼び出される関数で、NULLの場合、スレッドは作成されません.
 
この呼び出しは、割り込みリソースを割り当て、中断線およびIRQ処理を可能にする.この呼び出しが完了すると、登録された割り込み処理関数がいつでも呼び出される可能性があります.割り込み処理関数は、ボードで発生したすべての割り込みをクリアする必要があるため、ハードウェアの初期化と割り込み処理関数の正しい順序の設定に注意する必要があります.
 
デバイスにスレッド化されたirqプロセッサを設定したい場合は、handlerとthread_を同時に提供する必要があります.fn.handlerは依然としてハードブレークコンテキストで呼び出されているので、ブレークがサービスするデバイスによって生成されたかどうかを確認する必要があります.もしそうならIRQ_を返しますWAKE_THREAD、割り込みハンドラスレッドを起動してthread_を実行するfn.このような別々の割り込みハンドラ設計は、共有割り込みをサポートするために必要である.Dev_idはグローバル一意でなければならない.通常はデバイスデータ構造のアドレスです.使用する共有が中断された場合は、NULL以外のdev_を渡す必要があります.id、これはリリース中断時に必要です.
 
request_threaded_IRq()関数は0を返すことに成功し,EINVALを返すことによって割り込み番号が無効であるか,あるいは処理関数ポインタがNULLであることを示し,EBUSYを返すことによって割り込み番号が占有され共有できないことを示す.この関数は次のように動作します.
1、伝達されたフラグパラメータirqflagsを検査し、IRQF_を同時に設定したかどうかを検査するSHAREDとIRQF_DISABLED、もし警告を出すならば、IRQF_を説明しますDISABLEDは共有の中断において保証されない.
2、irqflagsがIRQF_を設定した場合SHARED、dev_もチェックしますidの有効性.
3、割り込み番号に対応する割り込み記述子を取得し、その有効性を確認する(割り込み記述子statusフィールドのIRQ_NOREQUESTビットを確認する).
4、handlerとthread_を検査するfnの有効性.
5.登録された割り込みハンドラおよび渡されたirqactionフラグのirqaction構造を作成する.
6、呼び出し_setup_IRq(irq,desc,action)は、作成したirqaction構造を対応する割り込み記述子のactionチェーンテーブルに追加します.
 
登録を中断した例については、カーネルでrequest_を検索できます.irq.