diff --git a/[refs] b/[refs] index 664f8a63bcf0..b3eda39f4d17 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d7a0e1f56472db0825e13f9dd39f0ad79b8c8b3e +refs/heads/master: f79abb627f033c85a6088231f20c85bc4a9bd757 diff --git a/trunk/drivers/acpi/ec.c b/trunk/drivers/acpi/ec.c index 7222a18a0319..e7e197e3a4ff 100644 --- a/trunk/drivers/acpi/ec.c +++ b/trunk/drivers/acpi/ec.c @@ -129,6 +129,7 @@ static struct acpi_ec { struct mutex lock; wait_queue_head_t wait; struct list_head list; + atomic_t irq_count; u8 handlers_installed; } *boot_ec, *first_ec; @@ -181,6 +182,8 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) { int ret = 0; + atomic_set(&ec->irq_count, 0); + if (unlikely(event == ACPI_EC_EVENT_OBF_1 && test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags))) force_poll = 1; @@ -227,6 +230,7 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) while (time_before(jiffies, delay)) { if (acpi_ec_check_status(ec, event)) goto end; + msleep(5); } } pr_err(PREFIX "acpi_ec_wait timeout," @@ -529,6 +533,13 @@ static u32 acpi_ec_gpe_handler(void *data) struct acpi_ec *ec = data; pr_debug(PREFIX "~~~> interrupt\n"); + atomic_inc(&ec->irq_count); + if (atomic_read(&ec->irq_count) > 5) { + pr_err(PREFIX "GPE storm detected, disabling EC GPE\n"); + acpi_disable_gpe(NULL, ec->gpe, ACPI_ISR); + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + return ACPI_INTERRUPT_HANDLED; + } clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) wake_up(&ec->wait); diff --git a/trunk/drivers/dma/fsldma.c b/trunk/drivers/dma/fsldma.c index ad2f938597e2..72692309398a 100644 --- a/trunk/drivers/dma/fsldma.c +++ b/trunk/drivers/dma/fsldma.c @@ -123,6 +123,11 @@ static dma_addr_t get_ndar(struct fsl_dma_chan *fsl_chan) return DMA_IN(fsl_chan, &fsl_chan->reg_base->ndar, 64); } +static u32 get_bcr(struct fsl_dma_chan *fsl_chan) +{ + return DMA_IN(fsl_chan, &fsl_chan->reg_base->bcr, 32); +} + static int dma_is_idle(struct fsl_dma_chan *fsl_chan) { u32 sr = get_sr(fsl_chan); @@ -426,6 +431,9 @@ fsl_dma_prep_interrupt(struct dma_chan *chan) new->async_tx.cookie = -EBUSY; new->async_tx.ack = 0; + /* Insert the link descriptor to the LD ring */ + list_add_tail(&new->node, &new->async_tx.tx_list); + /* Set End-of-link to the last link descriptor of new list*/ set_ld_eol(fsl_chan, new); @@ -701,6 +709,23 @@ static irqreturn_t fsl_dma_chan_do_interrupt(int irq, void *data) if (stat & FSL_DMA_SR_TE) dev_err(fsl_chan->dev, "Transfer Error!\n"); + /* Programming Error + * The DMA_INTERRUPT async_tx is a NULL transfer, which will + * triger a PE interrupt. + */ + if (stat & FSL_DMA_SR_PE) { + dev_dbg(fsl_chan->dev, "event: Programming Error INT\n"); + if (get_bcr(fsl_chan) == 0) { + /* BCR register is 0, this is a DMA_INTERRUPT async_tx. + * Now, update the completed cookie, and continue the + * next uncompleted transfer. + */ + fsl_dma_update_completed_cookie(fsl_chan); + fsl_chan_xfer_ld_queue(fsl_chan); + } + stat &= ~FSL_DMA_SR_PE; + } + /* If the link descriptor segment transfer finishes, * we will recycle the used descriptor. */ @@ -841,6 +866,11 @@ static int fsl_dma_self_test(struct fsl_dma_chan *fsl_chan) tx3 = fsl_dma_prep_memcpy(chan, dma_dest, dma_src, test_size / 4, 0); async_tx_ack(tx3); + /* Interrupt tx test */ + tx1 = fsl_dma_prep_interrupt(chan); + async_tx_ack(tx1); + cookie = fsl_dma_tx_submit(tx1); + /* Test exchanging the prepared tx sort */ cookie = fsl_dma_tx_submit(tx3); cookie = fsl_dma_tx_submit(tx2); diff --git a/trunk/drivers/dma/fsldma.h b/trunk/drivers/dma/fsldma.h index ba78c42121ba..fddd6aee2a63 100644 --- a/trunk/drivers/dma/fsldma.h +++ b/trunk/drivers/dma/fsldma.h @@ -40,6 +40,7 @@ #define FSL_DMA_MR_EOTIE 0x00000080 #define FSL_DMA_SR_CH 0x00000020 +#define FSL_DMA_SR_PE 0x00000010 #define FSL_DMA_SR_CB 0x00000004 #define FSL_DMA_SR_TE 0x00000080 #define FSL_DMA_SR_EOSI 0x00000002 diff --git a/trunk/drivers/ide/ide-taskfile.c b/trunk/drivers/ide/ide-taskfile.c index 4c86a8d84b4c..0518a2e948cf 100644 --- a/trunk/drivers/ide/ide-taskfile.c +++ b/trunk/drivers/ide/ide-taskfile.c @@ -422,25 +422,6 @@ void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) ide_end_request(drive, 1, rq->nr_sectors); } -/* - * We got an interrupt on a task_in case, but no errors and no DRQ. - * - * It might be a spurious irq (shared irq), but it might be a - * command that had no output. - */ -static ide_startstop_t task_in_unexpected(ide_drive_t *drive, struct request *rq, u8 stat) -{ - /* Command all done? */ - if (OK_STAT(stat, READY_STAT, BUSY_STAT)) { - task_end_request(drive, rq, stat); - return ide_stopped; - } - - /* Assume it was a spurious irq */ - ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL); - return ide_started; -} - /* * Handler for command with PIO data-in phase (Read/Read Multiple). */ @@ -450,17 +431,18 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive) struct request *rq = HWGROUP(drive)->rq; u8 stat = ide_read_status(drive); - /* Error? */ - if (stat & ERR_STAT) - return task_error(drive, rq, __FUNCTION__, stat); - - /* Didn't want any data? Odd. */ - if (!(stat & DRQ_STAT)) - return task_in_unexpected(drive, rq, stat); + /* new way for dealing with premature shared PCI interrupts */ + if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) { + if (stat & (ERR_STAT | DRQ_STAT)) + return task_error(drive, rq, __FUNCTION__, stat); + /* No data yet, so wait for another IRQ. */ + ide_set_handler(drive, &task_in_intr, WAIT_WORSTCASE, NULL); + return ide_started; + } ide_pio_datablock(drive, rq, 0); - /* Are we done? Check status and finish transfer. */ + /* If it was the last datablock check status and finish transfer. */ if (!hwif->nleft) { stat = wait_drive_not_busy(drive); if (!OK_STAT(stat, 0, BAD_STAT)) diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 3625fcaf5d0f..11d8e9a74eff 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -929,9 +929,6 @@ struct sched_entity { u64 vruntime; u64 prev_sum_exec_runtime; - u64 last_wakeup; - u64 avg_overlap; - #ifdef CONFIG_SCHEDSTATS u64 wait_start; u64 wait_max; diff --git a/trunk/include/linux/topology.h b/trunk/include/linux/topology.h index 2d8dac8799cf..2352f46160d3 100644 --- a/trunk/include/linux/topology.h +++ b/trunk/include/linux/topology.h @@ -138,6 +138,7 @@ | SD_BALANCE_FORK \ | SD_BALANCE_EXEC \ | SD_WAKE_AFFINE \ + | SD_WAKE_IDLE \ | SD_SHARE_PKG_RESOURCES\ | BALANCE_FOR_MC_POWER, \ .last_balance = jiffies, \ diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index 3f7c5eb254e2..d1ad69b270ca 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -1396,12 +1396,6 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd) { s64 delta; - /* - * Buddy candidates are cache hot: - */ - if (&p->se == cfs_rq_of(&p->se)->next) - return 1; - if (p->sched_class != &fair_sched_class) return 0; @@ -1861,11 +1855,10 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync) schedstat_inc(p, se.nr_wakeups_remote); update_rq_clock(rq); activate_task(rq, p, 1); + check_preempt_curr(rq, p); success = 1; out_running: - check_preempt_curr(rq, p); - p->state = TASK_RUNNING; #ifdef CONFIG_SMP if (p->sched_class->task_wake_up) @@ -1899,8 +1892,6 @@ static void __sched_fork(struct task_struct *p) p->se.exec_start = 0; p->se.sum_exec_runtime = 0; p->se.prev_sum_exec_runtime = 0; - p->se.last_wakeup = 0; - p->se.avg_overlap = 0; #ifdef CONFIG_SCHEDSTATS p->se.wait_start = 0; diff --git a/trunk/kernel/sched_debug.c b/trunk/kernel/sched_debug.c index ef358ba07683..4b5e24cf2f4a 100644 --- a/trunk/kernel/sched_debug.c +++ b/trunk/kernel/sched_debug.c @@ -288,7 +288,6 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) PN(se.exec_start); PN(se.vruntime); PN(se.sum_exec_runtime); - PN(se.avg_overlap); nr_switches = p->nvcsw + p->nivcsw; diff --git a/trunk/kernel/sched_fair.c b/trunk/kernel/sched_fair.c index b85cac4b5e25..f2cc59080efa 100644 --- a/trunk/kernel/sched_fair.c +++ b/trunk/kernel/sched_fair.c @@ -73,13 +73,13 @@ unsigned int sysctl_sched_batch_wakeup_granularity = 10000000UL; /* * SCHED_OTHER wake-up granularity. - * (default: 5 msec * (1 + ilog(ncpus)), units: nanoseconds) + * (default: 10 msec * (1 + ilog(ncpus)), units: nanoseconds) * * This option delays the preemption effects of decoupled workloads * and reduces their over-scheduling. Synchronous workloads will still * have immediate wakeup/sleep latencies. */ -unsigned int sysctl_sched_wakeup_granularity = 5000000UL; +unsigned int sysctl_sched_wakeup_granularity = 10000000UL; const_debug unsigned int sysctl_sched_migration_cost = 500000UL; @@ -556,21 +556,6 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup) account_entity_enqueue(cfs_rq, se); } -static void update_avg(u64 *avg, u64 sample) -{ - s64 diff = sample - *avg; - *avg += diff >> 3; -} - -static void update_avg_stats(struct cfs_rq *cfs_rq, struct sched_entity *se) -{ - if (!se->last_wakeup) - return; - - update_avg(&se->avg_overlap, se->sum_exec_runtime - se->last_wakeup); - se->last_wakeup = 0; -} - static void dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) { @@ -581,7 +566,6 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) update_stats_dequeue(cfs_rq, se); if (sleep) { - update_avg_stats(cfs_rq, se); #ifdef CONFIG_SCHEDSTATS if (entity_is_task(se)) { struct task_struct *tsk = task_of(se); @@ -996,121 +980,96 @@ static inline int wake_idle(int cpu, struct task_struct *p) #endif #ifdef CONFIG_SMP - -static const struct sched_class fair_sched_class; - -static int -wake_affine(struct rq *rq, struct sched_domain *this_sd, struct rq *this_rq, - struct task_struct *p, int prev_cpu, int this_cpu, int sync, - int idx, unsigned long load, unsigned long this_load, - unsigned int imbalance) -{ - struct task_struct *curr = this_rq->curr; - unsigned long tl = this_load; - unsigned long tl_per_task; - - if (!(this_sd->flags & SD_WAKE_AFFINE)) - return 0; - - /* - * If the currently running task will sleep within - * a reasonable amount of time then attract this newly - * woken task: - */ - if (sync && curr->sched_class == &fair_sched_class) { - if (curr->se.avg_overlap < sysctl_sched_migration_cost && - p->se.avg_overlap < sysctl_sched_migration_cost) - return 1; - } - - schedstat_inc(p, se.nr_wakeups_affine_attempts); - tl_per_task = cpu_avg_load_per_task(this_cpu); - - /* - * If sync wakeup then subtract the (maximum possible) - * effect of the currently running task from the load - * of the current CPU: - */ - if (sync) - tl -= current->se.load.weight; - - if ((tl <= load && tl + target_load(prev_cpu, idx) <= tl_per_task) || - 100*(tl + p->se.load.weight) <= imbalance*load) { - /* - * This domain has SD_WAKE_AFFINE and - * p is cache cold in this domain, and - * there is no bad imbalance. - */ - schedstat_inc(this_sd, ttwu_move_affine); - schedstat_inc(p, se.nr_wakeups_affine); - - return 1; - } - return 0; -} - static int select_task_rq_fair(struct task_struct *p, int sync) { + int cpu, this_cpu; + struct rq *rq; struct sched_domain *sd, *this_sd = NULL; - int prev_cpu, this_cpu, new_cpu; - unsigned long load, this_load; - struct rq *rq, *this_rq; - unsigned int imbalance; - int idx; - - prev_cpu = task_cpu(p); - rq = task_rq(p); - this_cpu = smp_processor_id(); - this_rq = cpu_rq(this_cpu); - new_cpu = prev_cpu; + int new_cpu; + + cpu = task_cpu(p); + rq = task_rq(p); + this_cpu = smp_processor_id(); + new_cpu = cpu; + + if (cpu == this_cpu) + goto out_set_cpu; - /* - * 'this_sd' is the first domain that both - * this_cpu and prev_cpu are present in: - */ for_each_domain(this_cpu, sd) { - if (cpu_isset(prev_cpu, sd->span)) { + if (cpu_isset(cpu, sd->span)) { this_sd = sd; break; } } if (unlikely(!cpu_isset(this_cpu, p->cpus_allowed))) - goto out; + goto out_set_cpu; /* * Check for affine wakeup and passive balancing possibilities. */ - if (!this_sd) - goto out; - - idx = this_sd->wake_idx; - - imbalance = 100 + (this_sd->imbalance_pct - 100) / 2; - - load = source_load(prev_cpu, idx); - this_load = target_load(this_cpu, idx); - - if (wake_affine(rq, this_sd, this_rq, p, prev_cpu, this_cpu, sync, idx, - load, this_load, imbalance)) - return this_cpu; - - if (prev_cpu == this_cpu) - goto out; + if (this_sd) { + int idx = this_sd->wake_idx; + unsigned int imbalance; + unsigned long load, this_load; + + imbalance = 100 + (this_sd->imbalance_pct - 100) / 2; + + load = source_load(cpu, idx); + this_load = target_load(this_cpu, idx); + + new_cpu = this_cpu; /* Wake to this CPU if we can */ + + if (this_sd->flags & SD_WAKE_AFFINE) { + unsigned long tl = this_load; + unsigned long tl_per_task; + + /* + * Attract cache-cold tasks on sync wakeups: + */ + if (sync && !task_hot(p, rq->clock, this_sd)) + goto out_set_cpu; + + schedstat_inc(p, se.nr_wakeups_affine_attempts); + tl_per_task = cpu_avg_load_per_task(this_cpu); + + /* + * If sync wakeup then subtract the (maximum possible) + * effect of the currently running task from the load + * of the current CPU: + */ + if (sync) + tl -= current->se.load.weight; + + if ((tl <= load && + tl + target_load(cpu, idx) <= tl_per_task) || + 100*(tl + p->se.load.weight) <= imbalance*load) { + /* + * This domain has SD_WAKE_AFFINE and + * p is cache cold in this domain, and + * there is no bad imbalance. + */ + schedstat_inc(this_sd, ttwu_move_affine); + schedstat_inc(p, se.nr_wakeups_affine); + goto out_set_cpu; + } + } - /* - * Start passive balancing when half the imbalance_pct - * limit is reached. - */ - if (this_sd->flags & SD_WAKE_BALANCE) { - if (imbalance*this_load <= 100*load) { - schedstat_inc(this_sd, ttwu_move_balance); - schedstat_inc(p, se.nr_wakeups_passive); - return this_cpu; + /* + * Start passive balancing when half the imbalance_pct + * limit is reached. + */ + if (this_sd->flags & SD_WAKE_BALANCE) { + if (imbalance*this_load <= 100*load) { + schedstat_inc(this_sd, ttwu_move_balance); + schedstat_inc(p, se.nr_wakeups_passive); + goto out_set_cpu; + } } } -out: + new_cpu = cpu; /* Could not wake to this_cpu. Wake to cpu instead */ +out_set_cpu: return wake_idle(new_cpu, p); } #endif /* CONFIG_SMP */ @@ -1133,10 +1092,6 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p) return; } - se->last_wakeup = se->sum_exec_runtime; - if (unlikely(se == pse)) - return; - cfs_rq_of(pse)->next = pse; /* diff --git a/trunk/mm/slub.c b/trunk/mm/slub.c index ca71d5b81e4a..96d63eb3ab17 100644 --- a/trunk/mm/slub.c +++ b/trunk/mm/slub.c @@ -1536,15 +1536,9 @@ static void *__slab_alloc(struct kmem_cache *s, * That is only possible if certain conditions are met that are being * checked when a slab is created. */ - if (!(gfpflags & __GFP_NORETRY) && - (s->flags & __PAGE_ALLOC_FALLBACK)) { - if (gfpflags & __GFP_WAIT) - local_irq_enable(); - object = kmalloc_large(s->objsize, gfpflags); - if (gfpflags & __GFP_WAIT) - local_irq_disable(); - return object; - } + if (!(gfpflags & __GFP_NORETRY) && (s->flags & __PAGE_ALLOC_FALLBACK)) + return kmalloc_large(s->objsize, gfpflags); + return NULL; debug: if (!alloc_debug_processing(s, c->page, object, addr)) diff --git a/trunk/net/core/sock.c b/trunk/net/core/sock.c index 2654c147c004..09cb3a74de7f 100644 --- a/trunk/net/core/sock.c +++ b/trunk/net/core/sock.c @@ -1621,7 +1621,7 @@ static void sock_def_readable(struct sock *sk, int len) { read_lock(&sk->sk_callback_lock); if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) - wake_up_interruptible_sync(sk->sk_sleep); + wake_up_interruptible(sk->sk_sleep); sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); read_unlock(&sk->sk_callback_lock); } @@ -1635,7 +1635,7 @@ static void sock_def_write_space(struct sock *sk) */ if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) - wake_up_interruptible_sync(sk->sk_sleep); + wake_up_interruptible(sk->sk_sleep); /* Should agree with poll, otherwise some programs break */ if (sock_writeable(sk))