From 1a3ddedb7616553793e2ccd1b08a394da2979fde Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 18 Mar 2008 21:27:13 -0700 Subject: [PATCH] --- yaml --- r: 87482 b: refs/heads/master c: 2caf470363941b70212a9a843cae02e8e2f751d9 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/ide/ide-taskfile.c | 36 ++++++++++++++++++++++++-------- trunk/mm/slub.c | 12 ++++++++--- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/[refs] b/[refs] index f5be497226a6..76ac160b1b5b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 33b0c4217dcd67b788318c3192a2912b530e4eef +refs/heads/master: 2caf470363941b70212a9a843cae02e8e2f751d9 diff --git a/trunk/drivers/ide/ide-taskfile.c b/trunk/drivers/ide/ide-taskfile.c index 0518a2e948cf..4c86a8d84b4c 100644 --- a/trunk/drivers/ide/ide-taskfile.c +++ b/trunk/drivers/ide/ide-taskfile.c @@ -422,6 +422,25 @@ 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). */ @@ -431,18 +450,17 @@ static ide_startstop_t task_in_intr(ide_drive_t *drive) struct request *rq = HWGROUP(drive)->rq; u8 stat = ide_read_status(drive); - /* 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; - } + /* 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); ide_pio_datablock(drive, rq, 0); - /* If it was the last datablock check status and finish transfer. */ + /* Are we done? 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/mm/slub.c b/trunk/mm/slub.c index 96d63eb3ab17..ca71d5b81e4a 100644 --- a/trunk/mm/slub.c +++ b/trunk/mm/slub.c @@ -1536,9 +1536,15 @@ 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)) - return kmalloc_large(s->objsize, gfpflags); - + 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; + } return NULL; debug: if (!alloc_debug_processing(s, c->page, object, addr))