percpu: generalize embedding first chunk setup helper
[safe/jmp/linux-2.6] / arch / x86 / kernel / tlb_uv.c
index b362913..d038b9c 100644 (file)
@@ -6,19 +6,19 @@
  *     This code is released under the GNU General Public License version 2 or
  *     later.
  */
-#include <linux/mc146818rtc.h>
+#include <linux/seq_file.h>
 #include <linux/proc_fs.h>
 #include <linux/kernel.h>
 
 #include <asm/mmu_context.h>
+#include <asm/uv/uv.h>
 #include <asm/uv/uv_mmrs.h>
 #include <asm/uv/uv_hub.h>
 #include <asm/uv/uv_bau.h>
-#include <asm/genapic.h>
+#include <asm/apic.h>
 #include <asm/idle.h>
 #include <asm/tsc.h>
-
-#include <mach_apic.h>
+#include <asm/irq_vectors.h>
 
 static struct bau_control      **uv_bau_table_bases __read_mostly;
 static int                     uv_bau_retry_limit __read_mostly;
@@ -199,6 +199,7 @@ static int uv_wait_completion(struct bau_desc *bau_desc,
                                destination_timeouts = 0;
                        }
                }
+               cpu_relax();
        }
        return FLUSH_COMPLETE;
 }
@@ -208,14 +209,15 @@ static int uv_wait_completion(struct bau_desc *bau_desc,
  *
  * Send a broadcast and wait for a broadcast message to complete.
  *
- * The cpumaskp mask contains the cpus the broadcast was sent to.
+ * The flush_mask contains the cpus the broadcast was sent to.
  *
- * Returns 1 if all remote flushing was done. The mask is zeroed.
- * Returns 0 if some remote flushing remains to be done. The mask is left
- * unchanged.
+ * Returns NULL if all remote flushing was done. The mask is zeroed.
+ * Returns @flush_mask if some remote flushing remains to be done. The
+ * mask will have some bits still set.
  */
-int uv_flush_send_and_wait(int cpu, int this_blade, struct bau_desc *bau_desc,
-                          cpumask_t *cpumaskp)
+const struct cpumask *uv_flush_send_and_wait(int cpu, int this_blade,
+                                            struct bau_desc *bau_desc,
+                                            struct cpumask *flush_mask)
 {
        int completion_status = 0;
        int right_shift;
@@ -255,66 +257,74 @@ int uv_flush_send_and_wait(int cpu, int this_blade, struct bau_desc *bau_desc,
                 * the cpu's, all of which are still in the mask.
                 */
                __get_cpu_var(ptcstats).ptc_i++;
-               return 0;
+               return flush_mask;
        }
 
        /*
         * Success, so clear the remote cpu's from the mask so we don't
         * use the IPI method of shootdown on them.
         */
-       for_each_cpu_mask(bit, *cpumaskp) {
+       for_each_cpu(bit, flush_mask) {
                blade = uv_cpu_to_blade_id(bit);
                if (blade == this_blade)
                        continue;
-               cpu_clear(bit, *cpumaskp);
+               cpumask_clear_cpu(bit, flush_mask);
        }
-       if (!cpus_empty(*cpumaskp))
-               return 0;
-       return 1;
+       if (!cpumask_empty(flush_mask))
+               return flush_mask;
+       return NULL;
 }
 
 /**
  * uv_flush_tlb_others - globally purge translation cache of a virtual
  * address or all TLB's
- * @cpumaskp: mask of all cpu's in which the address is to be removed
+ * @cpumask: mask of all cpu's in which the address is to be removed
  * @mm: mm_struct containing virtual address range
  * @va: virtual address to be removed (or TLB_FLUSH_ALL for all TLB's on cpu)
+ * @cpu: the current cpu
  *
  * This is the entry point for initiating any UV global TLB shootdown.
  *
  * Purges the translation caches of all specified processors of the given
  * virtual address, or purges all TLB's on specified processors.
  *
- * The caller has derived the cpumaskp from the mm_struct and has subtracted
- * the local cpu from the mask.  This function is called only if there
- * are bits set in the mask. (e.g. flush_tlb_page())
+ * The caller has derived the cpumask from the mm_struct.  This function
+ * is called only if there are bits set in the mask. (e.g. flush_tlb_page())
  *
- * The cpumaskp is converted into a nodemask of the nodes containing
+ * The cpumask is converted into a nodemask of the nodes containing
  * the cpus.
  *
- * Returns 1 if all remote flushing was done.
- * Returns 0 if some remote flushing remains to be done.
+ * Note that this function should be called with preemption disabled.
+ *
+ * Returns NULL if all remote flushing was done.
+ * Returns pointer to cpumask if some remote flushing remains to be
+ * done.  The returned pointer is valid till preemption is re-enabled.
  */
-int uv_flush_tlb_others(cpumask_t *cpumaskp, struct mm_struct *mm,
-                       unsigned long va)
+const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
+                                         struct mm_struct *mm,
+                                         unsigned long va, unsigned int cpu)
 {
+       static DEFINE_PER_CPU(cpumask_t, flush_tlb_mask);
+       struct cpumask *flush_mask = &__get_cpu_var(flush_tlb_mask);
        int i;
        int bit;
        int blade;
-       int cpu;
+       int uv_cpu;
        int this_blade;
        int locals = 0;
        struct bau_desc *bau_desc;
 
-       cpu = uv_blade_processor_id();
+       cpumask_andnot(flush_mask, cpumask, cpumask_of(cpu));
+
+       uv_cpu = uv_blade_processor_id();
        this_blade = uv_numa_blade_id();
        bau_desc = __get_cpu_var(bau_control).descriptor_base;
-       bau_desc += UV_ITEMS_PER_DESCRIPTOR * cpu;
+       bau_desc += UV_ITEMS_PER_DESCRIPTOR * uv_cpu;
 
        bau_nodes_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE);
 
        i = 0;
-       for_each_cpu_mask(bit, *cpumaskp) {
+       for_each_cpu(bit, flush_mask) {
                blade = uv_cpu_to_blade_id(bit);
                BUG_ON(blade > (UV_DISTRIBUTION_SIZE - 1));
                if (blade == this_blade) {
@@ -329,17 +339,17 @@ int uv_flush_tlb_others(cpumask_t *cpumaskp, struct mm_struct *mm,
                 * no off_node flushing; return status for local node
                 */
                if (locals)
-                       return 0;
+                       return flush_mask;
                else
-                       return 1;
+                       return NULL;
        }
        __get_cpu_var(ptcstats).requestor++;
        __get_cpu_var(ptcstats).ntargeted += i;
 
        bau_desc->payload.address = va;
-       bau_desc->payload.sending_cpu = smp_processor_id();
+       bau_desc->payload.sending_cpu = cpu;
 
-       return uv_flush_send_and_wait(cpu, this_blade, bau_desc, cpumaskp);
+       return uv_flush_send_and_wait(uv_cpu, this_blade, bau_desc, flush_mask);
 }
 
 /*
@@ -492,6 +502,8 @@ static ssize_t uv_ptc_proc_write(struct file *file, const char __user *user,
        long newmode;
        char optstr[64];
 
+       if (count == 0 || count > sizeof(optstr))
+               return -EINVAL;
        if (copy_from_user(optstr, user, count))
                return -EFAULT;
        optstr[count - 1] = '\0';
@@ -563,14 +575,10 @@ static int __init uv_ptc_init(void)
        if (!is_uv_system())
                return 0;
 
-       if (!proc_mkdir("sgi_uv", NULL))
-               return -EINVAL;
-
        proc_uv_ptc = create_proc_entry(UV_PTC_BASENAME, 0444, NULL);
        if (!proc_uv_ptc) {
                printk(KERN_ERR "unable to create %s proc entry\n",
                       UV_PTC_BASENAME);
-               remove_proc_entry("sgi_uv", NULL);
                return -EINVAL;
        }
        proc_uv_ptc->proc_fops = &proc_uv_ptc_operations;
@@ -583,7 +591,6 @@ static int __init uv_ptc_init(void)
 static struct bau_control * __init uv_table_bases_init(int blade, int node)
 {
        int i;
-       int *ip;
        struct bau_msg_status *msp;
        struct bau_control *bau_tabp;
 
@@ -600,13 +607,6 @@ static struct bau_control * __init uv_table_bases_init(int blade, int node)
                bau_cpubits_clear(&msp->seen_by, (int)
                                  uv_blade_nr_possible_cpus(blade));
 
-       bau_tabp->watching =
-           kmalloc_node(sizeof(int) * DEST_NUM_RESOURCES, GFP_KERNEL, node);
-       BUG_ON(!bau_tabp->watching);
-
-       for (i = 0, ip = bau_tabp->watching; i < DEST_Q_SIZE; i++, ip++)
-               *ip = 0;
-
        uv_bau_table_bases[blade] = bau_tabp;
 
        return bau_tabp;
@@ -629,7 +629,6 @@ uv_table_bases_finish(int blade, int node, int cur_cpu,
                bcp->bau_msg_head       = bau_tablesp->va_queue_first;
                bcp->va_queue_first     = bau_tablesp->va_queue_first;
                bcp->va_queue_last      = bau_tablesp->va_queue_last;
-               bcp->watching           = bau_tablesp->watching;
                bcp->msg_statuses       = bau_tablesp->msg_statuses;
                bcp->descriptor_base    = adp;
        }
@@ -781,7 +780,7 @@ static int __init uv_bau_init(void)
                uv_init_blade(blade, node, cur_cpu);
                cur_cpu += uv_blade_nr_possible_cpus(blade);
        }
-       set_intr_gate(UV_BAU_MESSAGE, uv_bau_message_intr1);
+       alloc_intr_gate(UV_BAU_MESSAGE, uv_bau_message_intr1);
        uv_enable_timeouts();
 
        return 0;