aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2006-10-05 09:55:46 -0400
committerDavid Howells <dhowells@warthog.cambridge.redhat.com>2006-10-05 10:10:12 -0400
commit7d12e780e003f93433d49ce78cfedf4b4c52adc5 (patch)
tree6748550400445c11a306b132009f3001e3525df8 /arch/ia64
parentda482792a6d1a3fbaaa25fae867b343fb4db3246 (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 'arch/ia64')
-rw-r--r--arch/ia64/kernel/irq_ia64.c4
-rw-r--r--arch/ia64/kernel/machvec.c2
-rw-r--r--arch/ia64/kernel/mca.c32
-rw-r--r--arch/ia64/kernel/time.c8
-rw-r--r--arch/ia64/sn/pci/tioca_provider.c3
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c3
6 files changed, 24 insertions, 28 deletions
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index ab2d19c3661f..7fd3ef9e064d 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -138,6 +138,7 @@ void destroy_irq(unsigned int irq)
138void 138void
139ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) 139ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
140{ 140{
141 struct pt_regs *old_regs = set_irq_regs(regs);
141 unsigned long saved_tpr; 142 unsigned long saved_tpr;
142 143
143#if IRQ_DEBUG 144#if IRQ_DEBUG
@@ -183,7 +184,7 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
183 ia64_setreg(_IA64_REG_CR_TPR, vector); 184 ia64_setreg(_IA64_REG_CR_TPR, vector);
184 ia64_srlz_d(); 185 ia64_srlz_d();
185 186
186 __do_IRQ(local_vector_to_irq(vector), regs); 187 __do_IRQ(local_vector_to_irq(vector));
187 188
188 /* 189 /*
189 * Disable interrupts and send EOI: 190 * Disable interrupts and send EOI:
@@ -200,6 +201,7 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
200 * come through until ia64_eoi() has been done. 201 * come through until ia64_eoi() has been done.
201 */ 202 */
202 irq_exit(); 203 irq_exit();
204 set_irq_regs(old_regs);
203} 205}
204 206
205#ifdef CONFIG_HOTPLUG_CPU 207#ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/ia64/kernel/machvec.c b/arch/ia64/kernel/machvec.c
index d4a546aa5048..9620822270a6 100644
--- a/arch/ia64/kernel/machvec.c
+++ b/arch/ia64/kernel/machvec.c
@@ -60,7 +60,7 @@ machvec_setup (char **arg)
60EXPORT_SYMBOL(machvec_setup); 60EXPORT_SYMBOL(machvec_setup);
61 61
62void 62void
63machvec_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) 63machvec_timer_interrupt (int irq, void *dev_id)
64{ 64{
65} 65}
66EXPORT_SYMBOL(machvec_timer_interrupt); 66EXPORT_SYMBOL(machvec_timer_interrupt);
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 663230183254..7cfa63a98cb3 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -499,7 +499,7 @@ int cpe_vector = -1;
499int ia64_cpe_irq = -1; 499int ia64_cpe_irq = -1;
500 500
501static irqreturn_t 501static irqreturn_t
502ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs) 502ia64_mca_cpe_int_handler (int cpe_irq, void *arg)
503{ 503{
504 static unsigned long cpe_history[CPE_HISTORY_LENGTH]; 504 static unsigned long cpe_history[CPE_HISTORY_LENGTH];
505 static int index; 505 static int index;
@@ -744,7 +744,7 @@ ia64_mca_wakeup_all(void)
744 * Outputs : None 744 * Outputs : None
745 */ 745 */
746static irqreturn_t 746static irqreturn_t
747ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs) 747ia64_mca_rendez_int_handler(int rendez_irq, void *arg)
748{ 748{
749 unsigned long flags; 749 unsigned long flags;
750 int cpu = smp_processor_id(); 750 int cpu = smp_processor_id();
@@ -753,8 +753,8 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs)
753 753
754 /* Mask all interrupts */ 754 /* Mask all interrupts */
755 local_irq_save(flags); 755 local_irq_save(flags);
756 if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", regs, (long)&nd, 0, 0) 756 if (notify_die(DIE_MCA_RENDZVOUS_ENTER, "MCA", get_irq_regs(),
757 == NOTIFY_STOP) 757 (long)&nd, 0, 0) == NOTIFY_STOP)
758 ia64_mca_spin(__FUNCTION__); 758 ia64_mca_spin(__FUNCTION__);
759 759
760 ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE; 760 ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE;
@@ -763,16 +763,16 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs)
763 */ 763 */
764 ia64_sal_mc_rendez(); 764 ia64_sal_mc_rendez();
765 765
766 if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", regs, (long)&nd, 0, 0) 766 if (notify_die(DIE_MCA_RENDZVOUS_PROCESS, "MCA", get_irq_regs(),
767 == NOTIFY_STOP) 767 (long)&nd, 0, 0) == NOTIFY_STOP)
768 ia64_mca_spin(__FUNCTION__); 768 ia64_mca_spin(__FUNCTION__);
769 769
770 /* Wait for the monarch cpu to exit. */ 770 /* Wait for the monarch cpu to exit. */
771 while (monarch_cpu != -1) 771 while (monarch_cpu != -1)
772 cpu_relax(); /* spin until monarch leaves */ 772 cpu_relax(); /* spin until monarch leaves */
773 773
774 if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", regs, (long)&nd, 0, 0) 774 if (notify_die(DIE_MCA_RENDZVOUS_LEAVE, "MCA", get_irq_regs(),
775 == NOTIFY_STOP) 775 (long)&nd, 0, 0) == NOTIFY_STOP)
776 ia64_mca_spin(__FUNCTION__); 776 ia64_mca_spin(__FUNCTION__);
777 777
778 /* Enable all interrupts */ 778 /* Enable all interrupts */
@@ -791,12 +791,11 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *regs)
791 * 791 *
792 * Inputs : wakeup_irq (Wakeup-interrupt bit) 792 * Inputs : wakeup_irq (Wakeup-interrupt bit)
793 * arg (Interrupt handler specific argument) 793 * arg (Interrupt handler specific argument)
794 * ptregs (Exception frame at the time of the interrupt)
795 * Outputs : None 794 * Outputs : None
796 * 795 *
797 */ 796 */
798static irqreturn_t 797static irqreturn_t
799ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs) 798ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg)
800{ 799{
801 return IRQ_HANDLED; 800 return IRQ_HANDLED;
802} 801}
@@ -1261,13 +1260,12 @@ static DECLARE_WORK(cmc_enable_work, ia64_mca_cmc_vector_enable_keventd, NULL);
1261 * Inputs 1260 * Inputs
1262 * interrupt number 1261 * interrupt number
1263 * client data arg ptr 1262 * client data arg ptr
1264 * saved registers ptr
1265 * 1263 *
1266 * Outputs 1264 * Outputs
1267 * None 1265 * None
1268 */ 1266 */
1269static irqreturn_t 1267static irqreturn_t
1270ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs) 1268ia64_mca_cmc_int_handler(int cmc_irq, void *arg)
1271{ 1269{
1272 static unsigned long cmc_history[CMC_HISTORY_LENGTH]; 1270 static unsigned long cmc_history[CMC_HISTORY_LENGTH];
1273 static int index; 1271 static int index;
@@ -1336,12 +1334,11 @@ out:
1336 * Inputs 1334 * Inputs
1337 * interrupt number 1335 * interrupt number
1338 * client data arg ptr 1336 * client data arg ptr
1339 * saved registers ptr
1340 * Outputs 1337 * Outputs
1341 * handled 1338 * handled
1342 */ 1339 */
1343static irqreturn_t 1340static irqreturn_t
1344ia64_mca_cmc_int_caller(int cmc_irq, void *arg, struct pt_regs *ptregs) 1341ia64_mca_cmc_int_caller(int cmc_irq, void *arg)
1345{ 1342{
1346 static int start_count = -1; 1343 static int start_count = -1;
1347 unsigned int cpuid; 1344 unsigned int cpuid;
@@ -1352,7 +1349,7 @@ ia64_mca_cmc_int_caller(int cmc_irq, void *arg, struct pt_regs *ptregs)
1352 if (start_count == -1) 1349 if (start_count == -1)
1353 start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CMC); 1350 start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CMC);
1354 1351
1355 ia64_mca_cmc_int_handler(cmc_irq, arg, ptregs); 1352 ia64_mca_cmc_int_handler(cmc_irq, arg);
1356 1353
1357 for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++); 1354 for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++);
1358 1355
@@ -1403,14 +1400,13 @@ ia64_mca_cmc_poll (unsigned long dummy)
1403 * Inputs 1400 * Inputs
1404 * interrupt number 1401 * interrupt number
1405 * client data arg ptr 1402 * client data arg ptr
1406 * saved registers ptr
1407 * Outputs 1403 * Outputs
1408 * handled 1404 * handled
1409 */ 1405 */
1410#ifdef CONFIG_ACPI 1406#ifdef CONFIG_ACPI
1411 1407
1412static irqreturn_t 1408static irqreturn_t
1413ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) 1409ia64_mca_cpe_int_caller(int cpe_irq, void *arg)
1414{ 1410{
1415 static int start_count = -1; 1411 static int start_count = -1;
1416 static int poll_time = MIN_CPE_POLL_INTERVAL; 1412 static int poll_time = MIN_CPE_POLL_INTERVAL;
@@ -1422,7 +1418,7 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
1422 if (start_count == -1) 1418 if (start_count == -1)
1423 start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CPE); 1419 start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CPE);
1424 1420
1425 ia64_mca_cpe_int_handler(cpe_irq, arg, ptregs); 1421 ia64_mca_cpe_int_handler(cpe_irq, arg);
1426 1422
1427 for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++); 1423 for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++);
1428 1424
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 62e07f906e05..41169a9bc301 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -45,7 +45,7 @@ static struct time_interpolator itc_interpolator = {
45}; 45};
46 46
47static irqreturn_t 47static irqreturn_t
48timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) 48timer_interrupt (int irq, void *dev_id)
49{ 49{
50 unsigned long new_itm; 50 unsigned long new_itm;
51 51
@@ -53,7 +53,7 @@ timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
53 return IRQ_HANDLED; 53 return IRQ_HANDLED;
54 } 54 }
55 55
56 platform_timer_interrupt(irq, dev_id, regs); 56 platform_timer_interrupt(irq, dev_id);
57 57
58 new_itm = local_cpu_data->itm_next; 58 new_itm = local_cpu_data->itm_next;
59 59
@@ -61,10 +61,10 @@ timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
61 printk(KERN_ERR "Oops: timer tick before it's due (itc=%lx,itm=%lx)\n", 61 printk(KERN_ERR "Oops: timer tick before it's due (itc=%lx,itm=%lx)\n",
62 ia64_get_itc(), new_itm); 62 ia64_get_itc(), new_itm);
63 63
64 profile_tick(CPU_PROFILING, regs); 64 profile_tick(CPU_PROFILING);
65 65
66 while (1) { 66 while (1) {
67 update_process_times(user_mode(regs)); 67 update_process_times(user_mode(get_irq_regs()));
68 68
69 new_itm += local_cpu_data->itm_delta; 69 new_itm += local_cpu_data->itm_delta;
70 70
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index c36b0f5affb3..8a2cb4e691fd 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -550,13 +550,12 @@ tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
550 * tioca_error_intr_handler - SGI TIO CA error interrupt handler 550 * tioca_error_intr_handler - SGI TIO CA error interrupt handler
551 * @irq: unused 551 * @irq: unused
552 * @arg: pointer to tioca_common struct for the given CA 552 * @arg: pointer to tioca_common struct for the given CA
553 * @pt: unused
554 * 553 *
555 * Handle a CA error interrupt. Simply a wrapper around a SAL call which 554 * Handle a CA error interrupt. Simply a wrapper around a SAL call which
556 * defers processing to the SGI prom. 555 * defers processing to the SGI prom.
557 */ 556 */
558static irqreturn_t 557static irqreturn_t
559tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt) 558tioca_error_intr_handler(int irq, void *arg)
560{ 559{
561 struct tioca_common *soft = arg; 560 struct tioca_common *soft = arg;
562 struct ia64_sal_retval ret_stuff; 561 struct ia64_sal_retval ret_stuff;
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index af7171adcd2c..0e81f68aaf8e 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -666,12 +666,11 @@ tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma
666 * tioce_error_intr_handler - SGI TIO CE error interrupt handler 666 * tioce_error_intr_handler - SGI TIO CE error interrupt handler
667 * @irq: unused 667 * @irq: unused
668 * @arg: pointer to tioce_common struct for the given CE 668 * @arg: pointer to tioce_common struct for the given CE
669 * @pt: unused
670 * 669 *
671 * Handle a CE error interrupt. Simply a wrapper around a SAL call which 670 * Handle a CE error interrupt. Simply a wrapper around a SAL call which
672 * defers processing to the SGI prom. 671 * defers processing to the SGI prom.
673 */ static irqreturn_t 672 */ static irqreturn_t
674tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt) 673tioce_error_intr_handler(int irq, void *arg)
675{ 674{
676 struct tioce_common *soft = arg; 675 struct tioce_common *soft = arg;
677 struct ia64_sal_retval ret_stuff; 676 struct ia64_sal_retval ret_stuff;