OSDN Git Service

Revert "usb: dwc3: turn off VBUS when leaving host mode"
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / kernel / softirq.c
index 359be4f..d69b77f 100644 (file)
@@ -57,6 +57,13 @@ static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp
 
 DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
 
+/*
+ * active_softirqs -- per cpu, a mask of softirqs that are being handled,
+ * with the expectation that approximate answers are acceptable and therefore
+ * no synchronization.
+ */
+DEFINE_PER_CPU(__u32, active_softirqs);
+
 const char * const softirq_to_name[NR_SOFTIRQS] = {
        "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL",
        "TASKLET", "SCHED", "HRTIMER", "RCU"
@@ -227,6 +234,16 @@ static inline bool lockdep_softirq_start(void) { return false; }
 static inline void lockdep_softirq_end(bool in_hardirq) { }
 #endif
 
+#define softirq_deferred_for_rt(pending)               \
+({                                                     \
+       __u32 deferred = 0;                             \
+       if (cpupri_check_rt()) {                        \
+               deferred = pending & LONG_SOFTIRQ_MASK; \
+               pending &= ~LONG_SOFTIRQ_MASK;          \
+       }                                               \
+       deferred;                                       \
+})
+
 asmlinkage __visible void __softirq_entry __do_softirq(void)
 {
        unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
@@ -234,6 +251,7 @@ asmlinkage __visible void __softirq_entry __do_softirq(void)
        int max_restart = MAX_SOFTIRQ_RESTART;
        struct softirq_action *h;
        bool in_hardirq;
+       __u32 deferred;
        __u32 pending;
        int softirq_bit;
 
@@ -245,14 +263,15 @@ asmlinkage __visible void __softirq_entry __do_softirq(void)
        current->flags &= ~PF_MEMALLOC;
 
        pending = local_softirq_pending();
+       deferred = softirq_deferred_for_rt(pending);
        account_irq_enter_time(current);
-
        __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);
        in_hardirq = lockdep_softirq_start();
 
 restart:
        /* Reset the pending bitmask before enabling irqs */
-       set_softirq_pending(0);
+       set_softirq_pending(deferred);
+       __this_cpu_write(active_softirqs, pending);
 
        local_irq_enable();
 
@@ -282,18 +301,21 @@ restart:
                pending >>= softirq_bit;
        }
 
+       __this_cpu_write(active_softirqs, 0);
        rcu_bh_qs();
        local_irq_disable();
 
        pending = local_softirq_pending();
+       deferred = softirq_deferred_for_rt(pending);
+
        if (pending) {
                if (time_before(jiffies, end) && !need_resched() &&
                    --max_restart)
                        goto restart;
-
-               wakeup_softirqd();
        }
 
+       if (pending | deferred)
+               wakeup_softirqd();
        lockdep_softirq_end(in_hardirq);
        account_irq_exit_time(current);
        __local_bh_enable(SOFTIRQ_OFFSET);