diff options
Diffstat (limited to 'kernel/irq/manage.c')
| -rw-r--r-- | kernel/irq/manage.c | 38 |
1 files changed, 17 insertions, 21 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 8c548232ba39..4c69326aa773 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
| @@ -781,7 +781,7 @@ static void wake_threads_waitq(struct irq_desc *desc) | |||
| 781 | wake_up(&desc->wait_for_threads); | 781 | wake_up(&desc->wait_for_threads); |
| 782 | } | 782 | } |
| 783 | 783 | ||
| 784 | static void irq_thread_dtor(struct task_work *unused) | 784 | static void irq_thread_dtor(struct callback_head *unused) |
| 785 | { | 785 | { |
| 786 | struct task_struct *tsk = current; | 786 | struct task_struct *tsk = current; |
| 787 | struct irq_desc *desc; | 787 | struct irq_desc *desc; |
| @@ -813,7 +813,7 @@ static void irq_thread_dtor(struct task_work *unused) | |||
| 813 | */ | 813 | */ |
| 814 | static int irq_thread(void *data) | 814 | static int irq_thread(void *data) |
| 815 | { | 815 | { |
| 816 | struct task_work on_exit_work; | 816 | struct callback_head on_exit_work; |
| 817 | static const struct sched_param param = { | 817 | static const struct sched_param param = { |
| 818 | .sched_priority = MAX_USER_RT_PRIO/2, | 818 | .sched_priority = MAX_USER_RT_PRIO/2, |
| 819 | }; | 819 | }; |
| @@ -830,7 +830,7 @@ static int irq_thread(void *data) | |||
| 830 | 830 | ||
| 831 | sched_setscheduler(current, SCHED_FIFO, ¶m); | 831 | sched_setscheduler(current, SCHED_FIFO, ¶m); |
| 832 | 832 | ||
| 833 | init_task_work(&on_exit_work, irq_thread_dtor, NULL); | 833 | init_task_work(&on_exit_work, irq_thread_dtor); |
| 834 | task_work_add(current, &on_exit_work, false); | 834 | task_work_add(current, &on_exit_work, false); |
| 835 | 835 | ||
| 836 | while (!irq_wait_for_interrupt(action)) { | 836 | while (!irq_wait_for_interrupt(action)) { |
| @@ -893,22 +893,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 893 | return -ENOSYS; | 893 | return -ENOSYS; |
| 894 | if (!try_module_get(desc->owner)) | 894 | if (!try_module_get(desc->owner)) |
| 895 | return -ENODEV; | 895 | return -ENODEV; |
| 896 | /* | ||
| 897 | * Some drivers like serial.c use request_irq() heavily, | ||
| 898 | * so we have to be careful not to interfere with a | ||
| 899 | * running system. | ||
| 900 | */ | ||
| 901 | if (new->flags & IRQF_SAMPLE_RANDOM) { | ||
| 902 | /* | ||
| 903 | * This function might sleep, we want to call it first, | ||
| 904 | * outside of the atomic block. | ||
| 905 | * Yes, this might clear the entropy pool if the wrong | ||
| 906 | * driver is attempted to be loaded, without actually | ||
| 907 | * installing a new handler, but is this really a problem, | ||
| 908 | * only the sysadmin is able to do this. | ||
| 909 | */ | ||
| 910 | rand_initialize_irq(irq); | ||
| 911 | } | ||
| 912 | 896 | ||
| 913 | /* | 897 | /* |
| 914 | * Check whether the interrupt nests into another interrupt | 898 | * Check whether the interrupt nests into another interrupt |
| @@ -960,6 +944,18 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 960 | } | 944 | } |
| 961 | 945 | ||
| 962 | /* | 946 | /* |
| 947 | * Drivers are often written to work w/o knowledge about the | ||
| 948 | * underlying irq chip implementation, so a request for a | ||
| 949 | * threaded irq without a primary hard irq context handler | ||
| 950 | * requires the ONESHOT flag to be set. Some irq chips like | ||
| 951 | * MSI based interrupts are per se one shot safe. Check the | ||
| 952 | * chip flags, so we can avoid the unmask dance at the end of | ||
| 953 | * the threaded handler for those. | ||
| 954 | */ | ||
| 955 | if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE) | ||
| 956 | new->flags &= ~IRQF_ONESHOT; | ||
| 957 | |||
| 958 | /* | ||
| 963 | * The following block of code has to be executed atomically | 959 | * The following block of code has to be executed atomically |
| 964 | */ | 960 | */ |
| 965 | raw_spin_lock_irqsave(&desc->lock, flags); | 961 | raw_spin_lock_irqsave(&desc->lock, flags); |
| @@ -1033,7 +1029,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 1033 | */ | 1029 | */ |
| 1034 | new->thread_mask = 1 << ffz(thread_mask); | 1030 | new->thread_mask = 1 << ffz(thread_mask); |
| 1035 | 1031 | ||
| 1036 | } else if (new->handler == irq_default_primary_handler) { | 1032 | } else if (new->handler == irq_default_primary_handler && |
| 1033 | !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)) { | ||
| 1037 | /* | 1034 | /* |
| 1038 | * The interrupt was requested with handler = NULL, so | 1035 | * The interrupt was requested with handler = NULL, so |
| 1039 | * we use the default primary handler for it. But it | 1036 | * we use the default primary handler for it. But it |
| @@ -1354,7 +1351,6 @@ EXPORT_SYMBOL(free_irq); | |||
| 1354 | * Flags: | 1351 | * Flags: |
| 1355 | * | 1352 | * |
| 1356 | * IRQF_SHARED Interrupt is shared | 1353 | * IRQF_SHARED Interrupt is shared |
| 1357 | * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy | ||
| 1358 | * IRQF_TRIGGER_* Specify active edge(s) or level | 1354 | * IRQF_TRIGGER_* Specify active edge(s) or level |
| 1359 | * | 1355 | * |
| 1360 | */ | 1356 | */ |
