From 820ec411e67c8dab645fb7e180875d619b6ab7e7 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 4 May 2018 16:24:43 +0200 Subject: alim15x3: move irq-restore before pci_dev_put() init_chipset_ali15x3() initializes the chipset during init with disabled interrupts. There is no need to keep the interrupts disabled during pci_dev_put(). Move the irq-restore before pci_dev_put() is invoked. Side note: The same init is performed in drivers/ata/pata_ali.c::ali_init_chipset() without disabled interrupts. It looks that the same hardware is supported in the ATA land. Would it make sense to remove this driver since it is supported in the other subsystem? Signed-off-by: Sebastian Andrzej Siewior Acked-by: David S. Miller Signed-off-by: David S. Miller --- drivers/ide/alim15x3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index 36f76e28a0bf..3265970aee34 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c @@ -323,9 +323,9 @@ out: pci_write_config_byte(dev, 0x53, tmpbyte); } + local_irq_restore(flags); pci_dev_put(north); pci_dev_put(isa_dev); - local_irq_restore(flags); return 0; } -- cgit From 56f0ddadcea9dc264f1c8eed6cc984071b141554 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 4 May 2018 16:24:44 +0200 Subject: ide: Handle irq disabling consistently ide_timer_expiry() disables interrupt at function entry when acquiring hwif->lock. Before disabling the device interrupt it unlocks hwif->lock, but interrupts stay disabled. After the call to disable_irq() interrupts are disabled again, which is a pointless exercise. After the device irq handler has been invoked with interrupts disabled, hwif->lock is acquired again with spin_lock_irq() because the device irq handler might have reenabled interrupts. This is not documented and confusing for the casual reader. Remove the redundant local_irq_disable() and add a comment which explains why hwif->lock has to be reacquired with spin_lock_irq(). Signed-off-by: Sebastian Andrzej Siewior Acked-by: David S. Miller Signed-off-by: David S. Miller --- drivers/ide/ide-io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 6f25da56a169..a444bad7a2aa 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -659,8 +659,7 @@ void ide_timer_expiry (struct timer_list *t) spin_unlock(&hwif->lock); /* disable_irq_nosync ?? */ disable_irq(hwif->irq); - /* local CPU only, as if we were handling an interrupt */ - local_irq_disable(); + if (hwif->polling) { startstop = handler(drive); } else if (drive_is_ready(drive)) { @@ -679,6 +678,7 @@ void ide_timer_expiry (struct timer_list *t) startstop = ide_error(drive, "irq timeout", hwif->tp_ops->read_status(hwif)); } + /* Disable interrupts again, `handler' might have enabled it */ spin_lock_irq(&hwif->lock); enable_irq(hwif->irq); if (startstop == ide_stopped && hwif->polling == 0) { -- cgit From ce1e518190ea71d1ecf1a91a8b0794ba9bd78e89 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 4 May 2018 16:24:45 +0200 Subject: ide: don't disable interrupts during kmap_atomic() ide_pio_bytes() disables interrupts around kmap_atomic(). This is a leftover from the old kmap_atomic() implementation which relied on fixed mapping slots, so the caller had to make sure that the same slot could not be reused from an interrupting context. kmap_atomic() was changed to dynamic slots long ago and commit 1ec9c5ddc17a ("include/linux/highmem.h: remove the second argument of k[un]map_atomic()") removed the slot assignements, but the callers were not checked for now redundant interrupt disabling. Remove the conditional interrupt disable. Signed-off-by: Sebastian Andrzej Siewior Acked-by: David S. Miller Signed-off-by: David S. Miller --- drivers/ide/ide-taskfile.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index c034cd965831..14bdab15a454 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -237,7 +237,6 @@ void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd, while (len) { unsigned nr_bytes = min(len, cursg->length - cmd->cursg_ofs); - int page_is_high; page = sg_page(cursg); offset = cursg->offset + cmd->cursg_ofs; @@ -248,10 +247,6 @@ void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd, nr_bytes = min_t(unsigned, nr_bytes, (PAGE_SIZE - offset)); - page_is_high = PageHighMem(page); - if (page_is_high) - local_irq_save(flags); - buf = kmap_atomic(page) + offset; cmd->nleft -= nr_bytes; @@ -270,9 +265,6 @@ void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd, kunmap_atomic(buf); - if (page_is_high) - local_irq_restore(flags); - len -= nr_bytes; } } -- cgit From 47b82e88180c3c6db795a43373beab47cb073f7a Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 4 May 2018 16:24:46 +0200 Subject: ide: don't enable/disable interrupts in force threaded-IRQ mode The interrupts are enabled/disabled so the interrupt handler can run with enabled interrupts while serving the interrupt and not lose other interrupts especially the timer tick. If the system runs with force-threaded interrupts then there is no need to enable the interrupts. Signed-off-by: Sebastian Andrzej Siewior Acked-by: David S. Miller Signed-off-by: David S. Miller --- drivers/ide/ide-iops.c | 13 +++++++++---- drivers/ide/ide-taskfile.c | 2 +- kernel/irq/manage.c | 1 + 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 210a0887dd29..d55e9ebd5628 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -108,6 +108,7 @@ int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; unsigned long flags; + bool irqs_threaded = force_irqthreads; int i; u8 stat; @@ -115,8 +116,10 @@ int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, stat = tp_ops->read_status(hwif); if (stat & ATA_BUSY) { - local_save_flags(flags); - local_irq_enable_in_hardirq(); + if (!irqs_threaded) { + local_save_flags(flags); + local_irq_enable_in_hardirq(); + } timeout += jiffies; while ((stat = tp_ops->read_status(hwif)) & ATA_BUSY) { if (time_after(jiffies, timeout)) { @@ -129,12 +132,14 @@ int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, if ((stat & ATA_BUSY) == 0) break; - local_irq_restore(flags); + if (!irqs_threaded) + local_irq_restore(flags); *rstat = stat; return -EBUSY; } } - local_irq_restore(flags); + if (!irqs_threaded) + local_irq_restore(flags); } /* * Allow status to settle, then read it again. diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 14bdab15a454..89b29028d315 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -405,7 +405,7 @@ static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, return startstop; } - if ((drive->dev_flags & IDE_DFLAG_UNMASK) == 0) + if (!force_irqthreads && (drive->dev_flags & IDE_DFLAG_UNMASK) == 0) local_irq_disable(); ide_set_handler(drive, &task_pio_intr, WAIT_WORSTCASE); diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index e3336d904f64..4c2ef8084e32 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -24,6 +24,7 @@ #ifdef CONFIG_IRQ_FORCED_THREADING __read_mostly bool force_irqthreads; +EXPORT_SYMBOL_GPL(force_irqthreads); static int __init setup_forced_irqthreads(char *arg) { -- cgit