转自:https://blog.csdn.net/tiantao2012/article/details/78957472

  1. 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tiantao2012/article/details/78957472
  2.  
  3. [html] view plain copy
  4. int setup_irq(unsigned int irq, struct irqaction *act)用于设置irq对应的irqaction.
  5.  
  6. 其使用的例程如下:
  7. struct irq_domain * __init __init_i8259_irqs(struct device_node *node)
  8. {
  9. struct irq_domain *domain;
  10.  
  11. insert_resource(&ioport_resource, &pic1_io_resource);
  12. insert_resource(&ioport_resource, &pic2_io_resource);
  13.  
  14. init_8259A();
  15.  
  16. domain = irq_domain_add_legacy(node, , I8259A_IRQ_BASE, ,
  17. &i8259A_ops, NULL);
  18. if (!domain)
  19. panic("Failed to add i8259 IRQ domain");
  20.  
  21. setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2);
  22. return domain;
  23. }
  24. 其源码分析如下:
  25.  
  26. int setup_irq(unsigned int irq, struct irqaction *act)
  27. {
  28. int retval;
  29. struct irq_desc *desc = irq_to_desc(irq);
  30. #中断描述为null,或者设置了_IRQ_PER_CPU_DEVID 标志的话,则直接退出
  31. if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
  32. return -EINVAL;
  33.  
  34. retval = irq_chip_pm_get(&desc->irq_data);
  35. if (retval < )
  36. return retval;
  37. #核心代码,设置irq对应的irqaction *act
  38. retval = __setup_irq(irq, desc, act);
  39.  
  40. if (retval)
  41. irq_chip_pm_put(&desc->irq_data);
  42.  
  43. return retval;
  44. }
  45. static int
  46. __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
  47. {
  48. struct irqaction *old, **old_ptr;
  49. unsigned long flags, thread_mask = ;
  50. int ret, nested, shared = ;
  51. #中断描述符为null,则退出
  52. if (!desc)
  53. return -EINVAL;
  54. #没有设置irq_data.chip,所以irq_data.chip 会等于no_irq_chip。这属于异常case ,退出.
  55. if (desc->irq_data.chip == &no_irq_chip)
  56. return -ENOSYS;
  57. #增加这个模块的引用计数
  58. if (!try_module_get(desc->owner))
  59. return -ENODEV;
  60. #更新struct irqaction *new 中的irq number
  61. new->irq = irq;
  62.  
  63. /*
  64. * If the trigger type is not specified by the caller,
  65. * then use the default for this interrupt.
  66. */
  67. #没有设置中断触发类型的话,则用默认值.
  68. if (!(new->flags & IRQF_TRIGGER_MASK))
  69. new->flags |= irqd_get_trigger_type(&desc->irq_data);
  70.  
  71. /*
  72. * Check whether the interrupt nests into another interrupt
  73. * thread.
  74. */
  75. #检查这里是否是中断嵌套,正常情况下irq_chip 基本都不支持中断嵌套
  76. nested = irq_settings_is_nested_thread(desc);
  77. if (nested) {
  78. if (!new->thread_fn) {
  79. ret = -EINVAL;
  80. goto out_mput;
  81. }
  82. /*
  83. * Replace the primary handler which was provided from
  84. * the driver for non nested interrupt handling by the
  85. * dummy function which warns when called.
  86. */
  87. new->handler = irq_nested_primary_handler;
  88. } else {
  89. #这里检查是否为这个中断设置一个thread,也就是说是否支持中断线程化
  90. if (irq_settings_can_thread(desc)) {
  91. ret = irq_setup_forced_threading(new);
  92. if (ret)
  93. goto out_mput;
  94. }
  95. }
  96.  
  97. /*
  98. * Create a handler thread when a thread function is supplied
  99. * and the interrupt does not nest into another interrupt
  100. * thread.
  101. */
  102. #在没有支持中断嵌套且用户用设置中断线程的情况下,这里会创建一个中断线程
  103. if (new->thread_fn && !nested) {
  104. ret = setup_irq_thread(new, irq, false);
  105. if (ret)
  106. goto out_mput;
  107. #中断线程化时是否支持第二个线程。如果支持的话,再创建一个中断线程.
  108. if (new->secondary) {
  109. ret = setup_irq_thread(new->secondary, irq, true);
  110. if (ret)
  111. goto out_thread;
  112. }
  113. }
  114.  
  115. /*
  116. * Drivers are often written to work w/o knowledge about the
  117. * underlying irq chip implementation, so a request for a
  118. * threaded irq without a primary hard irq context handler
  119. * requires the ONESHOT flag to be set. Some irq chips like
  120. * MSI based interrupts are per se one shot safe. Check the
  121. * chip flags, so we can avoid the unmask dance at the end of
  122. * the threaded handler for those.
  123. */
  124. #有设置oneshot 标志的话,则清掉这个标志.
  125. if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)
  126. new->flags &= ~IRQF_ONESHOT;
  127.  
  128. /*
  129. * Protects against a concurrent __free_irq() call which might wait
  130. * for synchronize_irq() to complete without holding the optional
  131. * chip bus lock and desc->lock.
  132. */
  133. mutex_lock(&desc->request_mutex);
  134.  
  135. /*
  136. * Acquire bus lock as the irq_request_resources() callback below
  137. * might rely on the serialization or the magic power management
  138. * functions which are abusing the irq_bus_lock() callback,
  139. */
  140. chip_bus_lock(desc);
  141.  
  142. /* First installed action requests resources. */
  143. #中断描述符的action为null的话,则通过irq_request_resources 来申请中断资源.
  144. if (!desc->action) {
  145. ret = irq_request_resources(desc);
  146. if (ret) {
  147. pr_err("Failed to request resources for %s (irq %d) on irqchip %s\n",
  148. new->name, irq, desc->irq_data.chip->name);
  149. goto out_bus_unlock;
  150. }
  151. }
  152.  
  153. /*
  154. * The following block of code has to be executed atomically
  155. * protected against a concurrent interrupt and any of the other
  156. * management calls which are not serialized via
  157. * desc->request_mutex or the optional bus lock.
  158. */
  159. raw_spin_lock_irqsave(&desc->lock, flags);
  160. old_ptr = &desc->action;
  161. old = *old_ptr;
  162. #如果这个中断号对应的中断描述符中的action 不为null,说明这个中断号之前可能已经申请过中断了
  163. #这里同样可以得出结论,同一个中断好,可以重复申请中断,但是可能会继承前一次的中断触发类型.
  164. if (old) {
  165. /*
  166. * Can't share interrupts unless both agree to and are
  167. * the same type (level, edge, polarity). So both flag
  168. * fields must have IRQF_SHARED set and the bits which
  169. * set the trigger type must match. Also all must
  170. * agree on ONESHOT.
  171. */
  172. unsigned int oldtype;
  173.  
  174. /*
  175. * If nobody did set the configuration before, inherit
  176. * the one provided by the requester.
  177. */
  178. if (irqd_trigger_type_was_set(&desc->irq_data)) {
  179. oldtype = irqd_get_trigger_type(&desc->irq_data);
  180. } else {
  181. oldtype = new->flags & IRQF_TRIGGER_MASK;
  182. irqd_set_trigger_type(&desc->irq_data, oldtype);
  183. }
  184.  
  185. if (!((old->flags & new->flags) & IRQF_SHARED) ||
  186. (oldtype != (new->flags & IRQF_TRIGGER_MASK)) ||
  187. ((old->flags ^ new->flags) & IRQF_ONESHOT))
  188. goto mismatch;
  189.  
  190. /* All handlers must agree on per-cpuness */
  191. if ((old->flags & IRQF_PERCPU) !=
  192. (new->flags & IRQF_PERCPU))
  193. goto mismatch;
  194.  
  195. /* add new interrupt at end of irq queue */
  196. do {
  197. /*
  198. * Or all existing action->thread_mask bits,
  199. * so we can find the next zero bit for this
  200. * new action.
  201. */
  202. thread_mask |= old->thread_mask;
  203. old_ptr = &old->next;
  204. old = *old_ptr;
  205. } while (old);
  206. shared = ;
  207. }
  208.  
  209. /*
  210. * Setup the thread mask for this irqaction for ONESHOT. For
  211. * !ONESHOT irqs the thread mask is 0 so we can avoid a
  212. * conditional in irq_wake_thread().
  213. */
  214. if (new->flags & IRQF_ONESHOT) {
  215. /*
  216. * Unlikely to have 32 resp 64 irqs sharing one line,
  217. * but who knows.
  218. */
  219. if (thread_mask == ~0UL) {
  220. ret = -EBUSY;
  221. goto out_unlock;
  222. }
  223. /*
  224. * The thread_mask for the action is or'ed to
  225. * desc->thread_active to indicate that the
  226. * IRQF_ONESHOT thread handler has been woken, but not
  227. * yet finished. The bit is cleared when a thread
  228. * completes. When all threads of a shared interrupt
  229. * line have completed desc->threads_active becomes
  230. * zero and the interrupt line is unmasked. See
  231. * handle.c:irq_wake_thread() for further information.
  232. *
  233. * If no thread is woken by primary (hard irq context)
  234. * interrupt handlers, then desc->threads_active is
  235. * also checked for zero to unmask the irq line in the
  236. * affected hard irq flow handlers
  237. * (handle_[fasteoi|level]_irq).
  238. *
  239. * The new action gets the first zero bit of
  240. * thread_mask assigned. See the loop above which or's
  241. * all existing action->thread_mask bits.
  242. */
  243. new->thread_mask = 1UL << ffz(thread_mask);
  244.  
  245. } else if (new->handler == irq_default_primary_handler &&
  246. !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)) {
  247. /*
  248. * The interrupt was requested with handler = NULL, so
  249. * we use the default primary handler for it. But it
  250. * does not have the oneshot flag set. In combination
  251. * with level interrupts this is deadly, because the
  252. * default primary handler just wakes the thread, then
  253. * the irq lines is reenabled, but the device still
  254. * has the level irq asserted. Rinse and repeat....
  255. *
  256. * While this works for edge type interrupts, we play
  257. * it safe and reject unconditionally because we can't
  258. * say for sure which type this interrupt really
  259. * has. The type flags are unreliable as the
  260. * underlying chip implementation can override them.
  261. */
  262. pr_err("Threaded irq requested with handler=NULL and !ONESHOT for irq %d\n",
  263. irq);
  264. ret = -EINVAL;
  265. goto out_unlock;
  266. }
  267. #非共享中断
  268. if (!shared) {
  269. #初始化一个等待队列,这个等待队列包含在中断描述符中
  270. init_waitqueue_head(&desc->wait_for_threads);
  271.  
  272. /* Setup the type (level, edge polarity) if configured: */
  273. if (new->flags & IRQF_TRIGGER_MASK) {
  274. ret = __irq_set_trigger(desc,
  275. new->flags & IRQF_TRIGGER_MASK);
  276.  
  277. if (ret)
  278. goto out_unlock;
  279. }
  280.  
  281. /*
  282. * Activate the interrupt. That activation must happen
  283. * independently of IRQ_NOAUTOEN. request_irq() can fail
  284. * and the callers are supposed to handle
  285. * that. enable_irq() of an interrupt requested with
  286. * IRQ_NOAUTOEN is not supposed to fail. The activation
  287. * keeps it in shutdown mode, it merily associates
  288. * resources if necessary and if that's not possible it
  289. * fails. Interrupts which are in managed shutdown mode
  290. * will simply ignore that activation request.
  291. */
  292. #激活这个中断
  293. ret = irq_activate(desc);
  294. if (ret)
  295. goto out_unlock;
  296.  
  297. desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \
  298. IRQS_ONESHOT | IRQS_WAITING);
  299. irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
  300. #是不是percpu中断
  301. if (new->flags & IRQF_PERCPU) {
  302. irqd_set(&desc->irq_data, IRQD_PER_CPU);
  303. irq_settings_set_per_cpu(desc);
  304. }
  305.  
  306. if (new->flags & IRQF_ONESHOT)
  307. desc->istate |= IRQS_ONESHOT;
  308.  
  309. /* Exclude IRQ from balancing if requested */
  310. #不用设置irq balance
  311. if (new->flags & IRQF_NOBALANCING) {
  312. irq_settings_set_no_balancing(desc);
  313. irqd_set(&desc->irq_data, IRQD_NO_BALANCING);
  314. }
  315. #开始中断
  316. if (irq_settings_can_autoenable(desc)) {
  317. irq_startup(desc, IRQ_RESEND, IRQ_START_COND);
  318. } else {
  319. /*
  320. * Shared interrupts do not go well with disabling
  321. * auto enable. The sharing interrupt might request
  322. * it while it's still disabled and then wait for
  323. * interrupts forever.
  324. */
  325. WARN_ON_ONCE(new->flags & IRQF_SHARED);
  326. /* Undo nested disables: */
  327. desc->depth = ;
  328. }
  329.  
  330. } else if (new->flags & IRQF_TRIGGER_MASK) {
  331. unsigned int nmsk = new->flags & IRQF_TRIGGER_MASK;
  332. unsigned int omsk = irqd_get_trigger_type(&desc->irq_data);
  333.  
  334. if (nmsk != omsk)
  335. /* hope the handler works with current trigger mode */
  336. pr_warn("irq %d uses trigger mode %u; requested %u\n",
  337. irq, omsk, nmsk);
  338. }
  339.  
  340. *old_ptr = new;
  341. #设置power相关
  342. irq_pm_install_action(desc, new);
  343.  
  344. /* Reset broken irq detection when installing new handler */
  345. desc->irq_count = ;
  346. desc->irqs_unhandled = ;
  347.  
  348. /*
  349. * Check whether we disabled the irq via the spurious handler
  350. * before. Reenable it and give it another chance.
  351. */
  352. if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) {
  353. desc->istate &= ~IRQS_SPURIOUS_DISABLED;
  354. __enable_irq(desc);
  355. }
  356.  
  357. raw_spin_unlock_irqrestore(&desc->lock, flags);
  358. chip_bus_sync_unlock(desc);
  359. mutex_unlock(&desc->request_mutex);
  360.  
  361. irq_setup_timings(desc, new);
  362.  
  363. /*
  364. * Strictly no need to wake it up, but hung_task complains
  365. * when no hard interrupt wakes the thread up.
  366. */
  367. # 如果有中断线程的话,则wakeup线程
  368. if (new->thread)
  369. wake_up_process(new->thread);
  370. if (new->secondary)
  371. wake_up_process(new->secondary->thread);
  372. #注册irq在proc中的接口
  373. register_irq_proc(irq, desc);
  374. new->dir = NULL;
  375. register_handler_proc(irq, new);
  376. return ;
  377.  
  378. mismatch:
  379. if (!(new->flags & IRQF_PROBE_SHARED)) {
  380. pr_err("Flags mismatch irq %d. %08x (%s) vs. %08x (%s)\n",
  381. irq, new->flags, new->name, old->flags, old->name);
  382. #ifdef CONFIG_DEBUG_SHIRQ
  383. dump_stack();
  384. #endif
  385. }
  386. ret = -EBUSY;
  387. #一下都是异常case
  388. out_unlock:
  389. raw_spin_unlock_irqrestore(&desc->lock, flags);
  390.  
  391. if (!desc->action)
  392. irq_release_resources(desc);
  393. out_bus_unlock:
  394. chip_bus_sync_unlock(desc);
  395. mutex_unlock(&desc->request_mutex);
  396.  
  397. out_thread:
  398. if (new->thread) {
  399. struct task_struct *t = new->thread;
  400.  
  401. new->thread = NULL;
  402. kthread_stop(t);
  403. put_task_struct(t);
  404. }
  405. if (new->secondary && new->secondary->thread) {
  406. struct task_struct *t = new->secondary->thread;
  407.  
  408. new->secondary->thread = NULL;
  409. kthread_stop(t);
  410. put_task_struct(t);
  411. }
  412. out_mput:
  413. module_put(desc->owner);
  414. return ret;
  415. }

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tiantao2012/article/details/78957472

[html] view plain copy

 
  1. int setup_irq(unsigned int irq, struct irqaction *act)用于设置irq对应的irqaction.
  2. 其使用的例程如下:
  3. struct irq_domain * __init __init_i8259_irqs(struct device_node *node)
  4. {
  5. struct irq_domain *domain;
  6. insert_resource(&ioport_resource, &pic1_io_resource);
  7. insert_resource(&ioport_resource, &pic2_io_resource);
  8. init_8259A(0);
  9. domain = irq_domain_add_legacy(node, 16, I8259A_IRQ_BASE, 0,
  10. &i8259A_ops, NULL);
  11. if (!domain)
  12. panic("Failed to add i8259 IRQ domain");
  13. setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2);
  14. return domain;
  15. }
  16. 其源码分析如下:
  17. int setup_irq(unsigned int irq, struct irqaction *act)
  18. {
  19. int retval;
  20. struct irq_desc *desc = irq_to_desc(irq);
  21. #中断描述为null,或者设置了_IRQ_PER_CPU_DEVID 标志的话,则直接退出
  22. if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
  23. return -EINVAL;
  24. retval = irq_chip_pm_get(&desc->irq_data);
  25. if (retval < 0)
  26. return retval;
  27. #核心代码,设置irq对应的irqaction *act
  28. retval = __setup_irq(irq, desc, act);
  29. if (retval)
  30. irq_chip_pm_put(&desc->irq_data);
  31. return retval;
  32. }
  33. static int
  34. __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
  35. {
  36. struct irqaction *old, **old_ptr;
  37. unsigned long flags, thread_mask = 0;
  38. int ret, nested, shared = 0;
  39. #中断描述符为null,则退出
  40. if (!desc)
  41. return -EINVAL;
  42. #没有设置irq_data.chip,所以irq_data.chip 会等于no_irq_chip。这属于异常case ,退出.
  43. if (desc->irq_data.chip == &no_irq_chip)
  44. return -ENOSYS;
  45. #增加这个模块的引用计数
  46. if (!try_module_get(desc->owner))
  47. return -ENODEV;
  48. #更新struct irqaction *new 中的irq number
  49. new->irq = irq;
  50. /*
  51. * If the trigger type is not specified by the caller,
  52. * then use the default for this interrupt.
  53. */
  54. #没有设置中断触发类型的话,则用默认值.
  55. if (!(new->flags & IRQF_TRIGGER_MASK))
  56. new->flags |= irqd_get_trigger_type(&desc->irq_data);
  57. /*
  58. * Check whether the interrupt nests into another interrupt
  59. * thread.
  60. */
  61. #检查这里是否是中断嵌套,正常情况下irq_chip 基本都不支持中断嵌套
  62. nested = irq_settings_is_nested_thread(desc);
  63. if (nested) {
  64. if (!new->thread_fn) {
  65. ret = -EINVAL;
  66. goto out_mput;
  67. }
  68. /*
  69. * Replace the primary handler which was provided from
  70. * the driver for non nested interrupt handling by the
  71. * dummy function which warns when called.
  72. */
  73. new->handler = irq_nested_primary_handler;
  74. } else {
  75. #这里检查是否为这个中断设置一个thread,也就是说是否支持中断线程化
  76. if (irq_settings_can_thread(desc)) {
  77. ret = irq_setup_forced_threading(new);
  78. if (ret)
  79. goto out_mput;
  80. }
  81. }
  82. /*
  83. * Create a handler thread when a thread function is supplied
  84. * and the interrupt does not nest into another interrupt
  85. * thread.
  86. */
  87. #在没有支持中断嵌套且用户用设置中断线程的情况下,这里会创建一个中断线程
  88. if (new->thread_fn && !nested) {
  89. ret = setup_irq_thread(new, irq, false);
  90. if (ret)
  91. goto out_mput;
  92. #中断线程化时是否支持第二个线程。如果支持的话,再创建一个中断线程.
  93. if (new->secondary) {
  94. ret = setup_irq_thread(new->secondary, irq, true);
  95. if (ret)
  96. goto out_thread;
  97. }
  98. }
  99. /*
  100. * Drivers are often written to work w/o knowledge about the
  101. * underlying irq chip implementation, so a request for a
  102. * threaded irq without a primary hard irq context handler
  103. * requires the ONESHOT flag to be set. Some irq chips like
  104. * MSI based interrupts are per se one shot safe. Check the
  105. * chip flags, so we can avoid the unmask dance at the end of
  106. * the threaded handler for those.
  107. */
  108. #有设置oneshot 标志的话,则清掉这个标志.
  109. if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)
  110. new->flags &= ~IRQF_ONESHOT;
  111. /*
  112. * Protects against a concurrent __free_irq() call which might wait
  113. * for synchronize_irq() to complete without holding the optional
  114. * chip bus lock and desc->lock.
  115. */
  116. mutex_lock(&desc->request_mutex);
  117. /*
  118. * Acquire bus lock as the irq_request_resources() callback below
  119. * might rely on the serialization or the magic power management
  120. * functions which are abusing the irq_bus_lock() callback,
  121. */
  122. chip_bus_lock(desc);
  123. /* First installed action requests resources. */
  124. #中断描述符的action为null的话,则通过irq_request_resources 来申请中断资源.
  125. if (!desc->action) {
  126. ret = irq_request_resources(desc);
  127. if (ret) {
  128. pr_err("Failed to request resources for %s (irq %d) on irqchip %s\n",
  129. new->name, irq, desc->irq_data.chip->name);
  130. goto out_bus_unlock;
  131. }
  132. }
  133. /*
  134. * The following block of code has to be executed atomically
  135. * protected against a concurrent interrupt and any of the other
  136. * management calls which are not serialized via
  137. * desc->request_mutex or the optional bus lock.
  138. */
  139. raw_spin_lock_irqsave(&desc->lock, flags);
  140. old_ptr = &desc->action;
  141. old = *old_ptr;
  142. #如果这个中断号对应的中断描述符中的action 不为null,说明这个中断号之前可能已经申请过中断了
  143. #这里同样可以得出结论,同一个中断好,可以重复申请中断,但是可能会继承前一次的中断触发类型.
  144. if (old) {
  145. /*
  146. * Can't share interrupts unless both agree to and are
  147. * the same type (level, edge, polarity). So both flag
  148. * fields must have IRQF_SHARED set and the bits which
  149. * set the trigger type must match. Also all must
  150. * agree on ONESHOT.
  151. */
  152. unsigned int oldtype;
  153. /*
  154. * If nobody did set the configuration before, inherit
  155. * the one provided by the requester.
  156. */
  157. if (irqd_trigger_type_was_set(&desc->irq_data)) {
  158. oldtype = irqd_get_trigger_type(&desc->irq_data);
  159. } else {
  160. oldtype = new->flags & IRQF_TRIGGER_MASK;
  161. irqd_set_trigger_type(&desc->irq_data, oldtype);
  162. }
  163. if (!((old->flags & new->flags) & IRQF_SHARED) ||
  164. (oldtype != (new->flags & IRQF_TRIGGER_MASK)) ||
  165. ((old->flags ^ new->flags) & IRQF_ONESHOT))
  166. goto mismatch;
  167. /* All handlers must agree on per-cpuness */
  168. if ((old->flags & IRQF_PERCPU) !=
  169. (new->flags & IRQF_PERCPU))
  170. goto mismatch;
  171. /* add new interrupt at end of irq queue */
  172. do {
  173. /*
  174. * Or all existing action->thread_mask bits,
  175. * so we can find the next zero bit for this
  176. * new action.
  177. */
  178. thread_mask |= old->thread_mask;
  179. old_ptr = &old->next;
  180. old = *old_ptr;
  181. } while (old);
  182. shared = 1;
  183. }
  184. /*
  185. * Setup the thread mask for this irqaction for ONESHOT. For
  186. * !ONESHOT irqs the thread mask is 0 so we can avoid a
  187. * conditional in irq_wake_thread().
  188. */
  189. if (new->flags & IRQF_ONESHOT) {
  190. /*
  191. * Unlikely to have 32 resp 64 irqs sharing one line,
  192. * but who knows.
  193. */
  194. if (thread_mask == ~0UL) {
  195. ret = -EBUSY;
  196. goto out_unlock;
  197. }
  198. /*
  199. * The thread_mask for the action is or'ed to
  200. * desc->thread_active to indicate that the
  201. * IRQF_ONESHOT thread handler has been woken, but not
  202. * yet finished. The bit is cleared when a thread
  203. * completes. When all threads of a shared interrupt
  204. * line have completed desc->threads_active becomes
  205. * zero and the interrupt line is unmasked. See
  206. * handle.c:irq_wake_thread() for further information.
  207. *
  208. * If no thread is woken by primary (hard irq context)
  209. * interrupt handlers, then desc->threads_active is
  210. * also checked for zero to unmask the irq line in the
  211. * affected hard irq flow handlers
  212. * (handle_[fasteoi|level]_irq).
  213. *
  214. * The new action gets the first zero bit of
  215. * thread_mask assigned. See the loop above which or's
  216. * all existing action->thread_mask bits.
  217. */
  218. new->thread_mask = 1UL << ffz(thread_mask);
  219. } else if (new->handler == irq_default_primary_handler &&
  220. !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)) {
  221. /*
  222. * The interrupt was requested with handler = NULL, so
  223. * we use the default primary handler for it. But it
  224. * does not have the oneshot flag set. In combination
  225. * with level interrupts this is deadly, because the
  226. * default primary handler just wakes the thread, then
  227. * the irq lines is reenabled, but the device still
  228. * has the level irq asserted. Rinse and repeat....
  229. *
  230. * While this works for edge type interrupts, we play
  231. * it safe and reject unconditionally because we can't
  232. * say for sure which type this interrupt really
  233. * has. The type flags are unreliable as the
  234. * underlying chip implementation can override them.
  235. */
  236. pr_err("Threaded irq requested with handler=NULL and !ONESHOT for irq %d\n",
  237. irq);
  238. ret = -EINVAL;
  239. goto out_unlock;
  240. }
  241. #非共享中断
  242. if (!shared) {
  243. #初始化一个等待队列,这个等待队列包含在中断描述符中
  244. init_waitqueue_head(&desc->wait_for_threads);
  245. /* Setup the type (level, edge polarity) if configured: */
  246. if (new->flags & IRQF_TRIGGER_MASK) {
  247. ret = __irq_set_trigger(desc,
  248. new->flags & IRQF_TRIGGER_MASK);
  249. if (ret)
  250. goto out_unlock;
  251. }
  252. /*
  253. * Activate the interrupt. That activation must happen
  254. * independently of IRQ_NOAUTOEN. request_irq() can fail
  255. * and the callers are supposed to handle
  256. * that. enable_irq() of an interrupt requested with
  257. * IRQ_NOAUTOEN is not supposed to fail. The activation
  258. * keeps it in shutdown mode, it merily associates
  259. * resources if necessary and if that's not possible it
  260. * fails. Interrupts which are in managed shutdown mode
  261. * will simply ignore that activation request.
  262. */
  263. #激活这个中断
  264. ret = irq_activate(desc);
  265. if (ret)
  266. goto out_unlock;
  267. desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \
  268. IRQS_ONESHOT | IRQS_WAITING);
  269. irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
  270. #是不是percpu中断
  271. if (new->flags & IRQF_PERCPU) {
  272. irqd_set(&desc->irq_data, IRQD_PER_CPU);
  273. irq_settings_set_per_cpu(desc);
  274. }
  275. if (new->flags & IRQF_ONESHOT)
  276. desc->istate |= IRQS_ONESHOT;
  277. /* Exclude IRQ from balancing if requested */
  278. #不用设置irq balance
  279. if (new->flags & IRQF_NOBALANCING) {
  280. irq_settings_set_no_balancing(desc);
  281. irqd_set(&desc->irq_data, IRQD_NO_BALANCING);
  282. }
  283. #开始中断
  284. if (irq_settings_can_autoenable(desc)) {
  285. irq_startup(desc, IRQ_RESEND, IRQ_START_COND);
  286. } else {
  287. /*
  288. * Shared interrupts do not go well with disabling
  289. * auto enable. The sharing interrupt might request
  290. * it while it's still disabled and then wait for
  291. * interrupts forever.
  292. */
  293. WARN_ON_ONCE(new->flags & IRQF_SHARED);
  294. /* Undo nested disables: */
  295. desc->depth = 1;
  296. }
  297. } else if (new->flags & IRQF_TRIGGER_MASK) {
  298. unsigned int nmsk = new->flags & IRQF_TRIGGER_MASK;
  299. unsigned int omsk = irqd_get_trigger_type(&desc->irq_data);
  300. if (nmsk != omsk)
  301. /* hope the handler works with current  trigger mode */
  302. pr_warn("irq %d uses trigger mode %u; requested %u\n",
  303. irq, omsk, nmsk);
  304. }
  305. *old_ptr = new;
  306. #设置power相关
  307. irq_pm_install_action(desc, new);
  308. /* Reset broken irq detection when installing new handler */
  309. desc->irq_count = 0;
  310. desc->irqs_unhandled = 0;
  311. /*
  312. * Check whether we disabled the irq via the spurious handler
  313. * before. Reenable it and give it another chance.
  314. */
  315. if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) {
  316. desc->istate &= ~IRQS_SPURIOUS_DISABLED;
  317. __enable_irq(desc);
  318. }
  319. raw_spin_unlock_irqrestore(&desc->lock, flags);
  320. chip_bus_sync_unlock(desc);
  321. mutex_unlock(&desc->request_mutex);
  322. irq_setup_timings(desc, new);
  323. /*
  324. * Strictly no need to wake it up, but hung_task complains
  325. * when no hard interrupt wakes the thread up.
  326. */
  327. # 如果有中断线程的话,则wakeup线程
  328. if (new->thread)
  329. wake_up_process(new->thread);
  330. if (new->secondary)
  331. wake_up_process(new->secondary->thread);
  332. #注册irq在proc中的接口
  333. register_irq_proc(irq, desc);
  334. new->dir = NULL;
  335. register_handler_proc(irq, new);
  336. return 0;
  337. mismatch:
  338. if (!(new->flags & IRQF_PROBE_SHARED)) {
  339. pr_err("Flags mismatch irq %d. %08x (%s) vs. %08x (%s)\n",
  340. irq, new->flags, new->name, old->flags, old->name);
  341. #ifdef CONFIG_DEBUG_SHIRQ
  342. dump_stack();
  343. #endif
  344. }
  345. ret = -EBUSY;
  346. #一下都是异常case
  347. out_unlock:
  348. raw_spin_unlock_irqrestore(&desc->lock, flags);
  349. if (!desc->action)
  350. irq_release_resources(desc);
  351. out_bus_unlock:
  352. chip_bus_sync_unlock(desc);
  353. mutex_unlock(&desc->request_mutex);
  354. out_thread:
  355. if (new->thread) {
  356. struct task_struct *t = new->thread;
  357. new->thread = NULL;
  358. kthread_stop(t);
  359. put_task_struct(t);
  360. }
  361. if (new->secondary && new->secondary->thread) {
  362. struct task_struct *t = new->secondary->thread;
  363. new->secondary->thread = NULL;
  364. kthread_stop(t);
  365. put_task_struct(t);
  366. }
  367. out_mput:
  368. module_put(desc->owner);
  369. return ret;
  370. }

中断API之setup_irq【转】的更多相关文章

  1. Linux kernel的中断子系统之(五):驱动申请中断API

    返回目录:<ARM-Linux中断系统>. 总结:二重点区分了抢占式内核和非抢占式内核的区别:抢占式内核可以在内核空间进行抢占,通过对中断处理进行线程化可以提高Linux内核实时性. 三介 ...

  2. Linux中断 - 驱动申请中断API

    一.前言 本文主要的议题是作为一个普通的驱动工程师,在撰写自己负责的驱动的时候,如何向Linux Kernel中的中断子系统注册中断处理函数?为了理解注册中断的接口,必须了解一些中断线程化(threa ...

  3. Linux kernel中断子系统之(五):驱动申请中断API【转】

    转自:http://www.wowotech.net/linux_kenrel/request_threaded_irq.html 一.前言 本文主要的议题是作为一个普通的驱动工程师,在撰写自己负责的 ...

  4. GPIO口及中断API函数【转】

    本文转载自:http://blog.sina.com.cn/s/blog_a6559d9201015vx9.htmlG #include <linux/gpio.h> // 标准 GPIO ...

  5. 中断API之enable_irq

    void enable_irq(unsigned int irq) 用于使能一个irq. void disable_irq(unsigned int irq)则用于禁止一个irq 其使用的例程如下: ...

  6. 非常好!!!Linux源代码阅读——中断【转】

    Linux源代码阅读——中断 转自:http://home.ustc.edu.cn/~boj/courses/linux_kernel/2_int.html 目录 为什么要有中断 中断的作用 中断的处 ...

  7. Intel 80x86 Linux Kernel Interrupt(中断)、Interrupt Priority、Interrupt nesting、Prohibit Things Whthin CPU In The Interrupt Off State

    目录 . 引言 . Linux 中断的概念 . 中断处理流程 . Linux 中断相关的源代码分析 . Linux 硬件中断 . Linux 软中断 . 中断优先级 . CPU在关中断状态下编程要注意 ...

  8. 基於tiny4412的Linux內核移植 --- 实例学习中断背后的知识(1)

    作者:彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台 tiny4412 ADK Linux-4.9 概述 前面几篇博文列举了在有设备树的时候,gpio中断的 ...

  9. ARM-Linux中断系统

    1.前言 了解Linux中断子系统,同时也需要了解ARM体系结构中断处理流程:在熟悉整个软硬件架构和流程基础上,才能对流程进行细化,然后找出问题的瓶颈.<2. 梳理中断处理子系统> 但是所 ...

随机推荐

  1. NetFPGA-1G-CML从零开始环境配置

    NetFPGA-1G-CML从零开始环境配置 前言 偶得一块NetFPGA-1G-CML,跟着github对NetFPGA-1G-CML的入门指南,一步步把配置环境终于搭建起来,下面重新复现一下此过程 ...

  2. eclipse maven项目目录

    今天遇见一个错误,关于eclipse项目的路径问题,web-inf的路径,上图和下图出现了两种web-INF,src的web-INFf和webContent的web-INF,src里面的文件需要编译以 ...

  3. python全栈开发-json和pickle模块(数据的序列化)

    一.什么是序列化? 我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flat ...

  4. 用C#(.NET Core) 实现简单工厂和工厂方法模式

    本文源自深入浅出设计模式. 只不过我是使用C#/.NET Core实现的例子. 前言 当你看见new这个关键字的时候, 就应该想到它是具体的实现. 这就是一个具体的类, 为了更灵活, 我们应该使用的是 ...

  5. Spring知识点回顾(08)spring aware

    Spring知识点回顾(08)spring aware BeanNameAware 获得容器中的bean名称 BeanFactoryAware 获得当前的bean factory Applicatio ...

  6. c# 工具类(字符串和时间,文件)

    using System; using System.IO; using System.Text.RegularExpressions; using System.Windows.Browser; n ...

  7. python中的turtle库绘制图形

    1. 前奏: 在用turtle绘制图形时,需要安装对应python的解释器以及IDE,我安装的是pycharm,在安装完pycharm后,在pycharm安装相应库的模块,绘图可以引入turtle模块 ...

  8. Django实现发邮件

    1 首先去自己的邮箱申请,在设置里面找,申请开通smtp服务,我用的是163邮箱 2 在项目下settings.py中添加设置: # 配置邮箱发邮件的相关功能 #这一项是固定的 EMAIL_BACKE ...

  9. JavaScript 重点笔记

    JavaScript 重点笔记 ## 数组 // 必须掌握 - arr.length:获取数组元素的长度 - arr.splice(起始位置,长度):从数组中添加或删除元素. - arr.indexO ...

  10. Linux-centos-7.2-64bit 安装配置mysql

    2018-04-12 安装在/usr/local/下,配置文件在/etc/my.ini 1.下载mysql安装包到 /usr/local/software cd /usr/local/software ...