home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-x86_64 / ipi.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  2.5 KB  |  118 lines

  1. #ifndef __ASM_IPI_H
  2. #define __ASM_IPI_H
  3.  
  4. /*
  5.  * Copyright 2004 James Cleverdon, IBM.
  6.  * Subject to the GNU Public License, v.2
  7.  *
  8.  * Generic APIC InterProcessor Interrupt code.
  9.  *
  10.  * Moved to include file by James Cleverdon from
  11.  * arch/x86-64/kernel/smp.c
  12.  *
  13.  * Copyrights from kernel/smp.c:
  14.  *
  15.  * (c) 1995 Alan Cox, Building #3 <alan@redhat.com>
  16.  * (c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
  17.  * (c) 2002,2003 Andi Kleen, SuSE Labs.
  18.  * Subject to the GNU Public License, v.2
  19.  */
  20.  
  21. #include <asm/fixmap.h>
  22. #include <asm/hw_irq.h>
  23. #include <asm/apicdef.h>
  24. #include <asm/genapic.h>
  25.  
  26. /*
  27.  * the following functions deal with sending IPIs between CPUs.
  28.  *
  29.  * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
  30.  */
  31.  
  32. static inline unsigned int __prepare_ICR (unsigned int shortcut, int vector, unsigned int dest)
  33. {
  34.     unsigned int icr = shortcut | dest;
  35.  
  36.     switch (vector) {
  37.     default:
  38.         icr |= APIC_DM_FIXED | vector;
  39.         break;
  40.     case NMI_VECTOR:
  41.         icr |= APIC_DM_NMI;
  42.         break;
  43.     }
  44.     return icr;
  45. }
  46.  
  47. static inline int __prepare_ICR2 (unsigned int mask)
  48. {
  49.     return SET_APIC_DEST_FIELD(mask);
  50. }
  51.  
  52. static inline void __send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest)
  53. {
  54.     /*
  55.      * Subtle. In the case of the 'never do double writes' workaround
  56.      * we have to lock out interrupts to be safe.  As we don't care
  57.      * of the value read we use an atomic rmw access to avoid costly
  58.      * cli/sti.  Otherwise we use an even cheaper single atomic write
  59.      * to the APIC.
  60.      */
  61.     unsigned int cfg;
  62.  
  63.     /*
  64.      * Wait for idle.
  65.      */
  66.     apic_wait_icr_idle();
  67.  
  68.     /*
  69.      * No need to touch the target chip field
  70.      */
  71.     cfg = __prepare_ICR(shortcut, vector, dest);
  72.  
  73.     /*
  74.      * Send the IPI. The write to APIC_ICR fires this off.
  75.      */
  76.     apic_write(APIC_ICR, cfg);
  77. }
  78.  
  79.  
  80. static inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
  81. {
  82.     unsigned long cfg, flags;
  83.     unsigned long query_cpu;
  84.  
  85.     /*
  86.      * Hack. The clustered APIC addressing mode doesn't allow us to send
  87.      * to an arbitrary mask, so I do a unicast to each CPU instead.
  88.      * - mbligh
  89.      */
  90.     local_irq_save(flags);
  91.  
  92.     for_each_cpu_mask(query_cpu, mask) {
  93.         /*
  94.          * Wait for idle.
  95.          */
  96.         apic_wait_icr_idle();
  97.  
  98.         /*
  99.          * prepare target chip field
  100.          */
  101.         cfg = __prepare_ICR2(x86_cpu_to_apicid[query_cpu]);
  102.         apic_write(APIC_ICR2, cfg);
  103.  
  104.         /*
  105.          * program the ICR
  106.          */
  107.         cfg = __prepare_ICR(0, vector, APIC_DEST_PHYSICAL);
  108.  
  109.         /*
  110.          * Send the IPI. The write to APIC_ICR fires this off.
  111.          */
  112.         apic_write(APIC_ICR, cfg);
  113.     }
  114.     local_irq_restore(flags);
  115. }
  116.  
  117. #endif /* __ASM_IPI_H */
  118.