PageRenderTime 26ms CodeModel.GetById 20ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/mn10300/mm/cache-smp.c

http://github.com/mirrors/linux
C | 105 lines | 69 code | 8 blank | 28 comment | 3 complexity | 8d0b838fda526015c8066b9cb21041a7 MD5 | raw file
  1/* SMP global caching code
  2 *
  3 * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved.
  4 * Written by David Howells (dhowells@redhat.com)
  5 *
  6 * This program is free software; you can redistribute it and/or
  7 * modify it under the terms of the GNU General Public Licence
  8 * as published by the Free Software Foundation; either version
  9 * 2 of the Licence, or (at your option) any later version.
 10 */
 11#include <linux/module.h>
 12#include <linux/mm.h>
 13#include <linux/mman.h>
 14#include <linux/threads.h>
 15#include <linux/interrupt.h>
 16#include <asm/page.h>
 17#include <asm/pgtable.h>
 18#include <asm/processor.h>
 19#include <asm/cacheflush.h>
 20#include <asm/io.h>
 21#include <asm/uaccess.h>
 22#include <asm/smp.h>
 23#include "cache-smp.h"
 24
 25DEFINE_SPINLOCK(smp_cache_lock);
 26static unsigned long smp_cache_mask;
 27static unsigned long smp_cache_start;
 28static unsigned long smp_cache_end;
 29static cpumask_t smp_cache_ipi_map;		/* Bitmask of cache IPI done CPUs */
 30
 31/**
 32 * smp_cache_interrupt - Handle IPI request to flush caches.
 33 *
 34 * Handle a request delivered by IPI to flush the current CPU's
 35 * caches.  The parameters are stored in smp_cache_*.
 36 */
 37void smp_cache_interrupt(void)
 38{
 39	unsigned long opr_mask = smp_cache_mask;
 40
 41	switch ((enum smp_dcache_ops)(opr_mask & SMP_DCACHE_OP_MASK)) {
 42	case SMP_DCACHE_NOP:
 43		break;
 44	case SMP_DCACHE_INV:
 45		mn10300_local_dcache_inv();
 46		break;
 47	case SMP_DCACHE_INV_RANGE:
 48		mn10300_local_dcache_inv_range(smp_cache_start, smp_cache_end);
 49		break;
 50	case SMP_DCACHE_FLUSH:
 51		mn10300_local_dcache_flush();
 52		break;
 53	case SMP_DCACHE_FLUSH_RANGE:
 54		mn10300_local_dcache_flush_range(smp_cache_start,
 55						 smp_cache_end);
 56		break;
 57	case SMP_DCACHE_FLUSH_INV:
 58		mn10300_local_dcache_flush_inv();
 59		break;
 60	case SMP_DCACHE_FLUSH_INV_RANGE:
 61		mn10300_local_dcache_flush_inv_range(smp_cache_start,
 62						     smp_cache_end);
 63		break;
 64	}
 65
 66	switch ((enum smp_icache_ops)(opr_mask & SMP_ICACHE_OP_MASK)) {
 67	case SMP_ICACHE_NOP:
 68		break;
 69	case SMP_ICACHE_INV:
 70		mn10300_local_icache_inv();
 71		break;
 72	case SMP_ICACHE_INV_RANGE:
 73		mn10300_local_icache_inv_range(smp_cache_start, smp_cache_end);
 74		break;
 75	}
 76
 77	cpumask_clear_cpu(smp_processor_id(), &smp_cache_ipi_map);
 78}
 79
 80/**
 81 * smp_cache_call - Issue an IPI to request the other CPUs flush caches
 82 * @opr_mask: Cache operation flags
 83 * @start: Start address of request
 84 * @end: End address of request
 85 *
 86 * Send cache flush IPI to other CPUs.  This invokes smp_cache_interrupt()
 87 * above on those other CPUs and then waits for them to finish.
 88 *
 89 * The caller must hold smp_cache_lock.
 90 */
 91void smp_cache_call(unsigned long opr_mask,
 92		    unsigned long start, unsigned long end)
 93{
 94	smp_cache_mask = opr_mask;
 95	smp_cache_start = start;
 96	smp_cache_end = end;
 97	cpumask_copy(&smp_cache_ipi_map, cpu_online_mask);
 98	cpumask_clear_cpu(smp_processor_id(), &smp_cache_ipi_map);
 99
100	send_IPI_allbutself(FLUSH_CACHE_IPI);
101
102	while (!cpumask_empty(&smp_cache_ipi_map))
103		/* nothing. lockup detection does not belong here */
104		mb();
105}