diff options
author | David Howells <dhowells@redhat.com> | 2006-10-05 14:55:46 +0100 |
---|---|---|
committer | David Howells <dhowells@warthog.cambridge.redhat.com> | 2006-10-05 15:10:12 +0100 |
commit | 7d12e780e003f93433d49ce78cfedf4b4c52adc5 (patch) | |
tree | 6748550400445c11a306b132009f3001e3525df8 /drivers/scsi | |
parent | da482792a6d1a3fbaaa25fae867b343fb4db3246 (diff) |
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
Diffstat (limited to 'drivers/scsi')
99 files changed, 185 insertions, 220 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index da173159ced..5f8c26cd66c 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -1192,7 +1192,7 @@ out: } /* End twa_initialize_device_extension() */ /* This function is the interrupt service routine */ -static irqreturn_t twa_interrupt(int irq, void *dev_instance, struct pt_regs *regs) +static irqreturn_t twa_interrupt(int irq, void *dev_instance) { int request_id, error = 0; u32 status_reg_value; diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 2d4cb6721fa..99a259c5a0c 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -2078,8 +2078,7 @@ static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd } /* End tw_scsi_queue() */ /* This function is the interrupt service routine */ -static irqreturn_t tw_interrupt(int irq, void *dev_instance, - struct pt_regs *regs) +static irqreturn_t tw_interrupt(int irq, void *dev_instance) { int request_id; u32 status_reg_value; diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 15ce40a7053..562432d017b 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -1462,7 +1462,7 @@ NCR_700_start_command(struct scsi_cmnd *SCp) } irqreturn_t -NCR_700_intr(int irq, void *dev_id, struct pt_regs *regs) +NCR_700_intr(int irq, void *dev_id) { struct Scsi_Host *host = (struct Scsi_Host *)dev_id; struct NCR_700_Host_Parameters *hostdata = diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h index 97ebe71b701..f5c3caf344a 100644 --- a/drivers/scsi/53c700.h +++ b/drivers/scsi/53c700.h @@ -57,7 +57,7 @@ struct NCR_700_Host_Parameters; struct Scsi_Host *NCR_700_detect(struct scsi_host_template *, struct NCR_700_Host_Parameters *, struct device *); int NCR_700_release(struct Scsi_Host *host); -irqreturn_t NCR_700_intr(int, void *, struct pt_regs *); +irqreturn_t NCR_700_intr(int, void *); enum NCR_700_Host_State { diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c index acf292736b4..640536ef77d 100644 --- a/drivers/scsi/53c7xx.c +++ b/drivers/scsi/53c7xx.c @@ -323,7 +323,7 @@ static int shutdown (struct Scsi_Host *host); static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result); static int disable (struct Scsi_Host *host); static int NCR53c7xx_run_tests (struct Scsi_Host *host); -static irqreturn_t NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs); +static irqreturn_t NCR53c7x0_intr(int irq, void *dev_id); static void NCR53c7x0_intfly (struct Scsi_Host *host); static int ncr_halt (struct Scsi_Host *host); static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd @@ -4227,7 +4227,7 @@ restart: } /* - * Function : static irqreturn_t NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs) + * Function : static irqreturn_t NCR53c7x0_intr (int irq, void *dev_id) * * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing * the same IRQ line. @@ -4241,7 +4241,7 @@ restart: */ static irqreturn_t -NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs) +NCR53c7x0_intr (int irq, void *dev_id) { NCR53c7x0_local_declare(); struct Scsi_Host *host; /* Host we are looking at */ diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 4ea49fd7965..7c59bba9879 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -2653,7 +2653,7 @@ static void BusLogic_ProcessCompletedCCBs(struct BusLogic_HostAdapter *HostAdapt Adapters. */ -static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier, struct pt_regs *InterruptRegisters) +static irqreturn_t BusLogic_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier) { struct BusLogic_HostAdapter *HostAdapter = (struct BusLogic_HostAdapter *) DeviceIdentifier; unsigned long ProcessorFlags; diff --git a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h index d6d1d5613c8..cca6d45eee4 100644 --- a/drivers/scsi/BusLogic.h +++ b/drivers/scsi/BusLogic.h @@ -1347,7 +1347,7 @@ static int BusLogic_BIOSDiskParameters(struct scsi_device *, struct block_device static int BusLogic_ProcDirectoryInfo(struct Scsi_Host *, char *, char **, off_t, int, int); static int BusLogic_SlaveConfigure(struct scsi_device *); static void BusLogic_QueueCompletedCCB(struct BusLogic_CCB *); -static irqreturn_t BusLogic_InterruptHandler(int, void *, struct pt_regs *); +static irqreturn_t BusLogic_InterruptHandler(int, void *); static int BusLogic_ResetHostAdapter(struct BusLogic_HostAdapter *, boolean HardReset); static void BusLogic_Message(enum BusLogic_MessageLevel, char *, struct BusLogic_HostAdapter *, ...); static int __init BusLogic_Setup(char *); diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 616810ad17d..a6aa9107288 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -558,8 +558,7 @@ static int probe_irq __initdata = 0; * used by the IRQ probe code. */ -static irqreturn_t __init probe_intr(int irq, void *dev_id, - struct pt_regs *regs) +static irqreturn_t __init probe_intr(int irq, void *dev_id) { probe_irq = irq; return IRQ_HANDLED; @@ -1148,7 +1147,6 @@ static void NCR5380_main(void *p) * NCR5380_intr - generic NCR5380 irq handler * @irq: interrupt number * @dev_id: device info - * @regs: registers (unused) * * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses * from the disconnected queue, and restarting NCR5380_main() @@ -1157,7 +1155,7 @@ static void NCR5380_main(void *p) * Locks: takes the needed instance locks */ -static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t NCR5380_intr(int irq, void *dev_id) { NCR5380_local_declare(); struct Scsi_Host *instance = (struct Scsi_Host *)dev_id; diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index c3462e358d1..1bc73de496b 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -296,7 +296,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags); static void NCR5380_exit(struct Scsi_Host *instance); static void NCR5380_information_transfer(struct Scsi_Host *instance); #ifndef DONT_USE_INTR -static irqreturn_t NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t NCR5380_intr(int irq, void *dev_id); #endif static void NCR5380_main(void *ptr); static void NCR5380_print_options(struct Scsi_Host *instance); diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c index bdc6bb262bc..3c912ee29da 100644 --- a/drivers/scsi/NCR53C9x.c +++ b/drivers/scsi/NCR53C9x.c @@ -96,7 +96,7 @@ enum { static struct NCR_ESP *espchain; int nesps = 0, esps_in_use = 0, esps_running = 0; -irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs); +irqreturn_t esp_intr(int irq, void *dev_id); /* Debugging routines */ static struct esp_cmdstrings { @@ -3533,7 +3533,7 @@ state_machine: } #ifndef CONFIG_SMP -irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs) +irqreturn_t esp_intr(int irq, void *dev_id) { struct NCR_ESP *esp; unsigned long flags; @@ -3570,7 +3570,7 @@ repeat: } #else /* For SMP we only service one ESP on the list list at our IRQ level! */ -irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs) +irqreturn_t esp_intr(int irq, void *dev_id) { struct NCR_ESP *esp; unsigned long flags; diff --git a/drivers/scsi/NCR53C9x.h b/drivers/scsi/NCR53C9x.h index 481653c977c..521e3f842cf 100644 --- a/drivers/scsi/NCR53C9x.h +++ b/drivers/scsi/NCR53C9x.h @@ -656,7 +656,7 @@ extern struct NCR_ESP *esp_allocate(struct scsi_host_template *, void *); extern void esp_deallocate(struct NCR_ESP *); extern void esp_release(void); extern void esp_initialize(struct NCR_ESP *); -extern irqreturn_t esp_intr(int, void *, struct pt_regs *); +extern irqreturn_t esp_intr(int, void *); extern const char *esp_info(struct Scsi_Host *); extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); extern int esp_abort(Scsi_Cmnd *); diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index 8472c535902..3896278594c 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -168,8 +168,8 @@ enum Phase { }; /* Static function prototypes */ -static void NCR53c406a_intr(int, void *, struct pt_regs *); -static irqreturn_t do_NCR53c406a_intr(int, void *, struct pt_regs *); +static void NCR53c406a_intr(int, void *); +static irqreturn_t do_NCR53c406a_intr(int, void *); static void chip_init(void); static void ca |